You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bash编写简易Web服务器出现连接拒绝错误的排查求助

Bash Web服务器连接拒绝问题分析与修复

错误原因

  1. 端口重复监听冲突:主循环通过nc -l -p $port监听端口并获取请求,而handle_request函数内又再次调用nc -l -p $port监听同一端口,导致端口被占用,新连接无法建立,触发连接拒绝错误。
  2. 连接生命周期处理错误:nc是单次连接工具,主循环的nc在接收请求后会关闭连接,子进程尝试重新监听端口时,端口可能处于TIME_WAIT状态,无法立即复用,进一步加剧连接失败问题。
  3. 目录请求逻辑未匹配需求:原脚本处理目录请求时直接返回列表,未优先检查目录下的index.html文件,不符合需求要求。

修复方案

  • 移除handle_request中的重复nc监听调用,改为直接通过标准输出发送响应给客户端。
  • 调整主循环逻辑,让nc在监听时直接将请求传递给处理函数,同时保持连接通道开放以发送响应。
  • 完善目录请求处理逻辑:访问目录时优先返回index.html,不存在时再返回目录列表。
  • 修复路径拼接问题,避免路径遍历风险。

完整修复后的脚本

#!/bin/bash

if [ $# -ne 2 ]; then
    echo "Usage: $0 <port> <root_directory>"
    exit 1
fi

port=$1
root_directory=$(realpath "$2")

if [ ! -d "$root_directory" ]; then
    echo "Root directory '$root_directory' does not exist."
    exit 1
fi

handle_request() {
    local request=$1
    local path=$(echo "$request" | awk '{print $2}')
    local method=$(echo "$request" | awk '{print $1}')

    # 只处理GET请求,其他直接返回400
    if [ "$method" != "GET" ]; then
        echo -e "HTTP/1.1 400 Bad Request\r\nContent-Type: text/plain\r\n\r\nBad Request"
        return
    fi

    # 处理根路径,默认指向目录
    if [ "$path" = "/" ]; then
        path=""
    fi

    # 拼接文件路径,用realpath防止路径遍历
    local file_path=$(realpath -m "$root_directory$path")
    # 检查路径是否在根目录范围内,防止越权访问
    if [[ "$file_path" != "$root_directory"* ]]; then
        echo -e "HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\n\r\nFile Not Found"
        return
    fi

    if [ -f "$file_path" ]; then
        # 返回文件内容,简单设置Content-Type(可根据后缀扩展)
        echo -e "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n$(cat "$file_path")"
    elif [ -d "$file_path" ]; then
        # 检查目录下的index.html
        local index_path="$file_path/index.html"
        if [ -f "$index_path" ]; then
            echo -e "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n$(cat "$index_path")"
        else
            # 返回目录列表
            echo -e "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n$(ls -l "$file_path")"
        fi
    else
        echo -e "HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\n\r\nFile Not Found"
    fi
}

echo "Starting web server on port $port, serving $root_directory"
# 使用nc监听端口,将请求通过管道传递给handle_request,同时将响应返回给客户端
while true; do
    nc -l -p "$port" | handle_request | nc -l -p "$port"
done

关键修改说明

  1. 端口监听逻辑:主循环中通过管道将nc的输入(客户端请求)传递给handle_request,再将处理函数的输出(响应)通过nc返回给客户端,避免重复监听端口。
  2. 路径安全处理:用realpath标准化路径,并检查是否在根目录范围内,防止路径遍历攻击。
  3. 目录请求优化:访问目录时优先返回index.html,符合需求要求。
  4. 响应头完善:添加了Content-Type头,让浏览器正确解析响应内容。

内容的提问来源于stack exchange,提问作者Sonnka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 07:37:45