连接失败主因有四:一是防火墙或安全组丢弃SYN包;二是服务未监听外网地址(如仅绑定127.0.0.1);三是syncookies启用导致NAT环境下ACK丢失;四是TIME_WAIT占满端口或本地端口耗尽。

连接被防火墙或安全组拦截
Linux 主机上 iptables、nftables 或云平台安全组规则,会直接丢弃 SYN 包,导致客户端收不到 SYN+ACK。现象是客户端 tcpdump 只能看到发出的 SYN,服务端抓包看不到任何入向 SYN。
- 检查本地防火墙:
sudo iptables -L -n -v或sudo nft list ruleset,重点关注 INPUT 链中是否有拒绝 TCP 目标端口的规则 - 云服务器务必确认安全组是否放行目标端口(不仅是协议和端口,还要检查源 IP 范围)
- 若使用
ufw,运行sudo ufw status verbose查看实际生效策略
服务进程未监听或绑定错误地址
netstat -tlnp 或 ss -tlnp 显示服务没在目标端口 LISTEN,或只绑定了 127.0.0.1(即 localhost),无法响应外部连接。
- 确认服务配置中监听地址不是
127.0.0.1:8080,而应为0.0.0.0:8080或具体外网 IP - 某些服务(如 Nginx、Redis)默认只监听本地,需显式修改配置项,例如 Redis 的
bind行要删掉或改成bind 0.0.0.0(注意配合protected-mode no) - 若服务启动失败但没报错,检查日志:
journalctl -u your-service-name -n 50
Syncookies 启用但客户端异常丢包
当连接请求洪峰到来时,内核可能启用 net.ipv4.tcp_syncookies=1(默认开启),此时不维护半连接队列,改用加密 cookie 回复 SYN+ACK。但如果客户端网络路径中存在 NAT 设备或中间件篡改 TCP 序列号,SYN+ACK 可能被丢弃或 ACK 无法返回,连接卡在 SYN_SENT。
- 临时关闭 syncookies 测试:
sudo sysctl -w net.ipv4.tcp_syncookies=0(仅用于排查,生产环境不建议长期关闭) - 更稳妥的方式是调大半连接队列:
net.ipv4.tcp_max_syn_backlog=65535,并确保应用层listen()的backlog参数足够(如 Node.js 的server.listen(port, host, backlog)) - 注意:syncookies 关闭后,若队列溢出,内核会直接丢弃 SYN,表现为客户端超时而非拒绝
TIME_WAIT 占满端口或本地端口耗尽
主动断连方(通常是客户端)大量处于 TIME_WAIT 状态,且复用同一源 IP+端口频繁连接同一服务,可能导致新连接因“地址已在使用”被拒绝(connect(): Address already in use);或本地 ephemeral 端口范围太小(默认 32768–60999,仅约 28K),并发连接数高时迅速耗尽。
- 查看当前连接状态分布:
ss -ant | awk '{print $NF}' | sort | uniq -c | sort -nr - 调整端口范围:
echo 'net.ipv4.ip_local_port_range = 1024 65535' | sudo tee -a /etc/sysctl.conf - 不推荐盲目缩短
net.ipv4.tcp_fin_timeout,更安全的做法是启用端口复用:net.ipv4.tcp_tw_reuse = 1(仅对客户端有效,且要求时间戳开启)
真正难定位的,往往是多个因素叠加:比如服务绑定了 localhost,同时防火墙又 DROP 了所有外网请求,而日志里只显示“Connection refused”,没人去查 ss -tlnp。










