Bash编写简易Web服务器出现连接拒绝错误的排查求助
Bash Web服务器连接拒绝问题分析与修复
错误原因
- 端口重复监听冲突:主循环通过
nc -l -p $port监听端口并获取请求,而handle_request函数内又再次调用nc -l -p $port监听同一端口,导致端口被占用,新连接无法建立,触发连接拒绝错误。 - 连接生命周期处理错误:
nc是单次连接工具,主循环的nc在接收请求后会关闭连接,子进程尝试重新监听端口时,端口可能处于TIME_WAIT状态,无法立即复用,进一步加剧连接失败问题。 - 目录请求逻辑未匹配需求:原脚本处理目录请求时直接返回列表,未优先检查目录下的
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
关键修改说明
- 端口监听逻辑:主循环中通过管道将
nc的输入(客户端请求)传递给handle_request,再将处理函数的输出(响应)通过nc返回给客户端,避免重复监听端口。 - 路径安全处理:用
realpath标准化路径,并检查是否在根目录范围内,防止路径遍历攻击。 - 目录请求优化:访问目录时优先返回
index.html,符合需求要求。 - 响应头完善:添加了
Content-Type头,让浏览器正确解析响应内容。
内容的提问来源于stack exchange,提问作者Sonnka
相关产品推荐
相关产品推荐

