EC2实例部署Django+Nginx+Gunicorn外部访问ERR_ADDRESS_UNREACHABLE问题排查
问题描述
我有一台部署了Nginx和Gunicorn的EC2实例,运行Django应用。Nginx、Gunicorn及Django应用均运行正常,在实例内执行curl -v 127.0.0.1:80可正常获取首页,但通过公网IP或公网DNS执行curl -v my_public_ip:80或curl -v my_public_dns:80时出现无法访问错误。
已简化Nginx配置为:
server { listen 80; server_name my_public_dns my_public_ip; return 200; }
问题仍未解决。
iptables规则:
sudo iptables -vnL Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 6 340 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 flags:0x17/0x02 ctstate NEW 2 120 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 flags:0x17/0x02 ctstate NEW
EC2实例安全组已开放80端口,防火墙状态关闭:
sudo ufw status verbose Status: inactive
Telnet测试结果:
telnet my_public_dns 80 Trying my_public_ip... telnet: Unable to connect to remote host: No route to host
排除防火墙、端口、Nginx、Gunicorn问题后,仍无法解决访问问题。
排查与解决步骤
1. 检查子网网络ACL配置
EC2的网络ACL是子网级别的流量控制规则,默认允许所有进出,但被修改后可能阻断80端口:
- 登录AWS控制台,找到实例所属子网
- 查看子网的网络ACL:
- 入站规则:确认存在允许
0.0.0.0/0访问TCP 80端口的规则,且优先级高于任何拒绝规则 - 出站规则:确认允许所有出站流量(至少要允许响应包返回公网)
- 入站规则:确认存在允许
2. 验证Nginx监听范围
执行命令检查Nginx是否监听所有网卡(而非仅本地回环):
sudo netstat -tulpn | grep nginx
输出需包含0.0.0.0:80或:::80,如果只有127.0.0.1:80,说明Nginx未绑定公网网卡,需确保listen指令未指定127.0.0.1,重启Nginx生效。
3. 确认实例公网网络配置
- 检查公网IP类型:如果是临时公网IP,重启实例后会变更,需确认使用的是当前实例的正确公网IP;建议绑定弹性公网IP(EIP)避免IP变动
- 检查子网类型:实例需处于公有子网(路由表指向互联网网关IGW),若在私有子网,需确保路由表指向NAT网关且NAT网关配置正常
4. 检查路由表
找到实例所属子网的路由表,确认存在目标为0.0.0.0/0、指向互联网网关(IGW)的路由条目;私有子网则需指向NAT网关。
5. 检查iptables完整规则
仅查看INPUT链不够,需检查FORWARD和OUTPUT链是否有阻断规则:
sudo iptables -vnL FORWARD sudo iptables -vnL OUTPUT
确保这两个链的策略为ACCEPT,或存在允许相关流量的规则。
6. 同VPC内实例测试
用同VPC内的其他EC2实例访问目标实例的80端口:
- 若能访问,说明问题出在公网到VPC的路由/ACL层面
- 若也无法访问,说明目标实例本身的网络配置存在问题
内容的提问来源于stack exchange,提问作者1ronmat
相关产品推荐
相关产品推荐

