线上机器端口转发配完了,本地curl 127.0.0.1:8080返回200,美滋滋。然后换个外网IP一打——timeout。反复确认安全组开了、iptables -t nat -L也看到规则了,就是不通。(别问我怎么知道的,问就是凌晨三点在机房群里发过疯。)
问题压根不在NAT规则本身。台湾服务器端口转发设置这件事,真正卡住人的是FORWARD链策略、conntrack连接跟踪表、以及多IP场景下的回程路由。下面拆成3个真实报错,逐条给修复命令。
报错一:FORWARD链默认DROP
iptables -t nat -A PREROUTING写了DNAT,包确实到了目标端口。但Linux内核的netfilter五张表里,FORWARD链默认策略是DROP的话,包进了PREROUTING、做完DNAT、然后被FORWARD链直接丢掉。通了才怪,你这FORWARD链默认DROP在那杵着。
修复就两行:
# 别问,问就是踩过坑
iptables -P FORWARD ACCEPT
iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i eth0 -o eth1 -p tcp --dport 8080 -j ACCEPT如果你用的是云厂商的安全组(台湾这边几家主流机房都有),还得在控制台把对应端口的inbound/outbound全放开,光改iptables没用,安全组是另一层。
报错二:conntrack表打满
dmesg里刷一堆 nf_conntrack: table full, dropping packet,这就是conntrack连接跟踪表溢出了。默认nf_conntrack_max才65536,台湾服务器跑个中等并发的转发业务,几天就能打满。更离谱的是nf_conntrack_tcp_timeout_established默认432000秒(五天,这默认值谁定的),大量ESTABLISHED僵尸连接占着坑不释放。
调优参数直接怼上去:
- 把 nf_conntrack_max 拉到 262144 或更高,看内存
- 把 nf_conntrack_tcp_timeout_established 砍到 7200 秒,够用了
- 开 nf_conntrack_tcp_loose 设为 0,减少半开连接占用
改完 sysctl -p 生效,然后 watch -n1 'cat /proc/sys/net/netfilter/nf_conntrack_count' 盯着看,别等再次打满。
报错三:多IP回包走错接口
台湾服务器绑了多个公网IP,DNAT把外部流量转到内网某个服务,但回包的SNAT没指定源地址,内核按默认路由表选了一个别的IP出去。对端一看,SYN是从A发的,SYN+ACK从B回来了,直接RST。三次握手变两次半,永远established不了。
修复:在POSTROUTING链里显式绑定SNAT源地址:
iptables -t nat -A POSTROUTING -o eth0 -p tcp --dport 8080 -j SNAT --to-source 203.0.113.5另外检查一下 rp_filter(反向路径校验),多IP多网卡场景下这个设为1会直接丢包。改成2(loose mode)或者0:
sysctl -w net.ipv4.conf.all.rp_filter=2
sysctl -w net.ipv4.conf.eth0.rp_filter=2三种转发方案参数对比
| 对比维度 | 仅DNAT(裸配) | DNAT+SNAT+FORWARD全链路 | nftables替代方案 |
|---|---|---|---|
| 配置行数 | 1-2行 | 5-8行 | 3-5行(语法合并) |
| conntrack压力 | 高(无超时调优) | 可控(配合timeout参数) | 同iptables,内核共用 |
| 多IP兼容 | 回包必出错 | 显式SNAT绑定,稳 | 同左,写法更紧凑 |
| 内核版本要求 | 2.6+ | 2.6+ | 3.13+(建议4.x以上) |
| 排错难度 | 高(不知道哪层丢的) | 低(逐链排查) | 中(nft list ruleset一把梭) |
这几个坑千万别踩
- 别在PREROUTING里写 -i lo 的DNAT规则,本地回环流量根本不走这条链,写了等于没写
- 别把conntrack模块黑名单(有些精简内核把nf_conntrack_ftp之类的编译成模块),模块没加载,相关协议追踪直接失效
- 别在没搞清楚上游运营商QoS策略的情况下,把转发端口设在1024以下的保留段,台湾几家ISP对低位端口有额外过滤策略
什么场景别折腾端口转发
说句实话:如果你的业务就是跑个标准Web,80/443直连就行,完全不需要搞端口转发。并发长期低于500的小站,默认conntrack配置绑绑有余,不用调。另外,如果你用的是台湾服务器做纯CDN回源节点,转发逻辑应该放在负载均衡层而不是单机iptables上,单机搞这个纯属给自己找事。
作者简介
前中华电信Hinet骨干网NOC轮班运维,干了6年L2/L3故障处理,现在一家跨境SaaS公司负责基础网络与IDC资源调度。iptables/nftables规则累计写过上万条,最擅长凌晨三点被oncall电话叫起来排NAT回程路由问题。
现在该干什么
打开终端,先跑 iptables -L FORWARD -n 看默认策略,再 cat /proc/sys/net/netfilter/nf_conntrack_count 看当前连接数。两个命令十秒钟的事,别等线上告警了再翻这篇内容。端口转发不通,90%的原因就藏在FORWARD链和conntrack里。