套接字与端口诊断
目标
读取监听套接字,亲手复现绑定地址对远程访问的影响,并确认 Connection refused 与正常连接的区别。
为什么重要
监听 127.0.0.1:8080 的进程在同一主机上能够完美运行,但内核会用 RST 拒绝来自外部的连接——也就是出现 refused。因此,收到“本地正常,只有远程无法访问”的报告时,只需查看 ss -ltnp 的 Local Address 一栏,一半的调查就完成了。反之,如果该地址是 0.0.0.0,但外部访问仍然 timeout,这时才开始检查防火墙和网络策略。这个分岔能把调查范围缩小一半。
步骤
- 创建
/root/sock目录,将当前正在监听的 TCP 套接字列表保存到/root/sock/listen.txt。其中必须包含:2222。 - 在后台启动一个监听
0.0.0.0:8080的 HTTP 服务器。评分时它仍必须处于运行状态。 - 启动第二个只监听
127.0.0.1:8081的服务器,把两个套接字的Local Address:Port各写一行到/root/sock/bind.txt。(例如0.0.0.0:8080和127.0.0.1:8081) - 检查能否连接
127.0.0.1:8080,并将结果保存到/root/sock/nc-open.txt。 - 尝试连接无人监听的
127.0.0.1:9999,将结果保存到/root/sock/nc-refused.txt。输出中必须包含表示 refused 的语句。 - 在
/proc/net/tcp中找到 8080 端口的 LISTEN 套接字行,原样保存到/root/sock/proctcp.txt。 - 使用本机接口 IP(不是环回地址)分别连接 8080 和 8081,把结果分两行写入
/root/sock/scope-test.txt。8080=<open|closed>/8081=<open|closed> - 创建
/root/sock/report.csv。第一行为port,bind,proto表头,下面分别为 2222、8080、8081 三个端口各写一行。bind是实际监听地址,proto为tcp。
参考
- 组合使用
ss -ltnp、nc -zv -w 2 <ip> <port>、ip -4 -br addr show scope global就足够了。 - 使用类似
nohup python3 -m http.server 8080 --bind 0.0.0.0 >/dev/null 2>&1 &的命令启动服务器。 /proc/net/tcp中的端口采用十六进制。使用printf '%04X\n' 8080查看转换结果。- 常见错误 1:第 7 步使用环回地址测试,这会让两个端口看起来都已开放,无法体现差异。
- 常见错误 2:后台服务器随 shell 退出而终止。请使用
nohup或setsid将其分离。
检查监听套接字
创建 /root/sock 目录,将当前正在监听的 TCP 套接字列表保存到 /root/sock/listen.txt。其中必须包含 :2222。
需要组合使用只显示 TCP 监听套接字、不解析名称并显示进程的选项。sshd 正在 2222 端口运行。
启动测试服务器
在后台启动一个监听 0.0.0.0:8080 的 HTTP 服务器。评分时它仍必须处于运行状态。
在后台启动 Python 3 内置的 HTTP 服务器。评分时它仍必须处于运行状态,因此同时使用 nohup 或 setsid 会更安全。
绑定范围不同的两个服务器
启动第二个只监听 127.0.0.1:8081 的服务器,把两个套接字的 Local Address:Port 各写一行到 /root/sock/bind.txt。(例如 0.0.0.0:8080 和 127.0.0.1:8081)
python3 -m http.server 提供了指定绑定地址的选项。请比较两个服务器的 Local Address 列。
检查开放端口
检查能否连接 127.0.0.1:8080,并将结果保存到 /root/sock/nc-open.txt。
nc 的 -z 选项不会发送数据,只尝试建立连接。必须加上 -v 才会输出结果语句。
检查关闭端口
尝试连接无人监听的 127.0.0.1:9999,将结果保存到 /root/sock/nc-refused.txt。输出中必须包含表示 refused 的语句。
连接无人监听的端口时,内核会返回 RST。请原样保存结果语句。
直接读取 /proc/net/tcp
在 /proc/net/tcp 中找到 8080 端口的 LISTEN 套接字行,原样保存到 /root/sock/proctcp.txt。
端口以十六进制记录。8080 转换为十六进制是什么?状态列中的 0A 表示 LISTEN。
从外部地址尝试连接
使用本机接口 IP(不是环回地址)分别连接 8080 和 8081,把结果分两行写入 /root/sock/scope-test.txt。
8080=<open|closed> / 8081=<open|closed>
必须使用本机接口 IP 而不是环回地址进行访问,差异才会显现。两个端口的结果应当不同。
制作监听套接字表
创建 /root/sock/report.csv。第一行为 port,bind,proto 表头,下面分别为 2222、8080、8081 三个端口各写一行。bind 是实际监听地址,proto 为 tcp。
CSV 使用逗号分隔。必须包含表头行,并包含前面启动的两个端口。