luckygood logo

台湾服务器端口转发设置3个高频报错的排查与修复实录

StrataServer

线上机器端口转发配完了,本地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里。

常见问题解答

01 iptables报 'No chain/target/match by that name' 怎么解决?

大概率是nf_conntrack或xt_nat模块没加载。跑 modprobe nf_conntrack && modprobe xt_nat,然后重新执行规则。精简内核常见这毛病。

02 dmesg刷 nf_conntrack: table full 但实际并发不高,为啥?

检查nf_conntrack_tcp_timeout_established,默认432000秒太长,僵尸连接堆积。砍到7200秒,同时把nf_conntrack_max提到262144。

03 多IP服务器DNAT后对端收到RST,握手失败怎么查?

tcpdump -i eth0 抓包看SYN+ACK的源IP是不是跟SYN的目标IP一致。不一致就是SNAT没绑,POSTROUTING链加 --to-source 显式指定。

04 rp_filter设成1之后端口转发全挂了,必须关掉吗?

不用全关。多网卡多IP场景设成2(loose mode)就行,既保留基本反欺骗校验,又不会误杀合法的非对称路由回包。

05 nftables和iptables能同时跑吗?迁移要注意啥?

能共存但别混用同一张表。迁移时先 iptables-save 导出,用 iptables-translate 转成nft语法,验证无误后再 systemctl disable netfilter-persistent。