实验环境从 502 到公网可用的完整排查流程:
一、公网访问不通,一步步排查
由内向外,逐层验证。先从自己测起,再往外找。
第一步:确认服务本身活着
curl http://127.0.0.1:80/
本机 curl 通了,服务就是好的。不通就查进程:ps aux | grep nginx,没进程就启动,有进程就看日志 tail /var/log/nginx/error.log。
第二步:确认后端可达(如果有反向代理)
curl http://后端IP:80/
直接 curl 后端,502 就是后端挂了。去后端机器看进程、看端口、看防火墙。
第三步:确认监听范围
sudo ss -tunlp | grep :80
看 Nginx 监听的是 0.0.0.0:80 还是 127.0.0.1:80。如果是 127.0.0.1,外网永远连不上,必须改成 0.0.0.0 或者公网 IP。
第四步:确认端口是否被多实例抢占
ps aux | grep nginx
你系统里跑了三个 Nginx 实例,端口被瓜分,外网请求可能被错误的实例抢走。杀掉多余的,只留一个。
第五步:检查系统防火墙
sudo ufw status
sudo iptables -L -n | grep :80
iptables 里有一条规则只放行内网 10.1.0.0/16 访问 80 端口,外网全被拦了。删掉限源 IP 的规则,改成放行所有来源。
查看防火墙规则
# 1. 系统防火墙 ufw
sudo ufw status numbered
# 2. 底层 iptables 规则(ufw 最终也是翻译成这个)
sudo iptables -L -n --line-numbers
# 只看 80 端口相关
sudo iptables -L -n --line-numbers | grep -E ':80|dpt:80'
# -E 是 grep 的选项,表示使用扩展正则表达式
# 这条命令里 grep -E ':80|dpt:80',| 是正则里的"或"的意思,
# 不加 -E 的话 | 会被当成普通字符匹配,加了 -E 才会被解释成"匹配 :80 或 dpt:80"
# 只看指定端口,比如 443
sudo iptables -L -n --line-numbers | grep ':443'
# 3. 云安全组(必须去云控制台网页上看,命令行查不到)
第六步:检查云安全组
去腾讯云控制台 → 安全组 → 入站规则,确认 TCP:80 来源 0.0.0.0/0 已放行。
第七步:检查 DNS 解析
nslookup 是 DNS 查询工具,查域名解析到哪个 IP:
nslookup 你的域名
确认 A 记录指向正确的公网 IP。不对就去改。
第八步:检查内网互通(多台机器之间)
ping 不通不代表不通,用 curl 测。如果内网跨 VPC,配云联网或对等连接。安全组和防火墙也要放行内网段。
故障问题
- 后端 Python 服务挂了 → 502
- 后端防火墙只放行内网 IP → 网关 curl 不通
因为在网关机器上执行 curl http://172.16.0.9:80/ 时,请求的源 IP 不是 10.1.0.12,而是网关用来出公网或跨网段的路由 IP。后端防火墙只放行了 10.1.0.12,其他源 IP 的请求全被拦了。
解决方法:后端防火墙放行整个内网段,而不是只放行一个 IP。你现在已经配了 ufw allow from 10.1.0.0/16,这个问题已经解决了。
- 三台机器不在同一个 VPC → 内网不通
- 三台机器在不同网段 → 配云联网打通
- 公网 80 端口不通 → 安全组放行
- 公网还是不通 → 发现系统里跑了三个 Nginx 实例
- 公网仍然不通 → iptables 规则只放行内网,拦截了外网
之前照着视频在后端机器上配的 iptables 规则只允许 10.1.0.0/16 内网段访问 80 端口,外网 IP 全部被拦。但这台机器本身是网关,需要接受来自公网的请求,所以外网一直打不开。删掉那条限源的规则、改成放行所有来源后,外网才通。
sudo ufw allow from 10.1.0.0/16 to any port 80 proto tcp 应当是只允许内网网段对后端访问,网关对外网开放(网关机器不要限制来源 IP,必须放行所有来源访问 80/443;后端机器才需要限制只允许网关内网 IP 访问)。