首先说明一下背景,在阿里云上开了台机器,替换掉这篇文章中需要绕行香港节点,以提高访问速度,降低延迟(虽然带宽大砍,哭)。但是遇到了奇怪的系统不转发报文的奇怪问题。
节点运行的是Debian 13,安装了podman(<–就是这玩意出的问题)。
检查0,抓包
毫无疑问,tcpdump -n -i any host <ip>可以看到包是否转发,最方便快捷的确认方式。
这次就是看到报文接收了但是没发出去,肯定是哪里的配置有问题了。
检查1,路由表
可以用以下的命令来测试包的转发路径是否正确:
ip route get 10.7.0.10 from 10.8.0.5 iif if1
上面的命令是查询从if1进来的,源为10.8.0.5,目的为10.7.0.10的报文,会匹配什么路由,从什么接口发出去,就像这样:
ip route get 10.7.0.10 from 10.8.0.5 iif if1
10.7.0.10 from 10.8.0.5 via 10.4.10.10 dev if2
cache iif if1
检查2,路由规则
这里不多叙述,一般没用,至于都懂得自己配路由规则了,就应该懂得怎么查了。
检查3,防火墙
看iptables的FORWARD链,默认ACCEPT,没拦截。这里有个大坑,具体后面再说。
顺便检查conntrack,因为是不对称的路由,所以conntrack没列出来,看起来也是正常现象。
检查4,内核转发
检查内核的ipv4 forward,是1。没啥问题。如果不是1,修改/etc/sysctl.conf,然后用sysctl -p应用。
检查5,rp_filter
rp_filter还是挺重要的安全设置,可以检查包是否从正确的源地址过来。但是因为这个节点被配置成路由器,有不对称路由,所以需要关闭。可以用以下命令查看接口的rp_filter设置:0是禁用,1是宽松,2是严格。
sysctl -a | grep \\.rp_filter
如果有需要,可以在sysctl.conf添加配置,禁用掉某个端口的rp_filter。
检查6,防火墙2
最后检查nftables,检查出问题了。
table inet netavark {
.....
chain FORWARD {
type filter hook forward priority filter; policy accept;
ct state invalid drop
jump NETAVARK-ISOLATION-1
.....
}
.....
如果conntrack的状态是invalid的话,就丢掉报文,结合之前conntrack没有追踪到会话,那问题估计就在这里了。
nftables拦截但是iptables放通的话,包依然是被拦截,但是iptables又看不到nftables的拦截策略……要不是AI助手提醒我都没想到这个。
根据AI助手的介绍,netavark是podman用来隔离流量的安全设计,和处理流量转发。如果用的是docker的话,应该用的是iptables而不是nftables就没这坑了吧(望天)。
最终关键处理
首先,用以下命令检查FORWARD链
nft -a list chain inet netavark FORWARD
会返回以下样子的结果:
table inet netavark {
chain FORWARD { # handle 2
type filter hook forward priority filter; policy accept;
ct state invalid drop # handle 15
jump NETAVARK-ISOLATION-1 # handle 16
ip daddr 172.22.222.0/24 ct state established,related accept # handle 25
ip saddr 172.22.222.0/24 accept # handle 26
ip daddr 10.89.0.0/24 ct state established,related accept # handle 82
ip saddr 10.89.0.0/24 accept # handle 83
}
}
然后,可以用以下命令去在丢弃报文的规则前插入放通的规则:
nft insert rule inet netavark FORWARD index 0 iifname "if1" oifname "if2" accept
上面的命令是放通了从接口if1到接口if2的流量转发。如果图省事,可以去掉源或者目的。插入完之后再检查的话,就会变成:
table inet netavark {
chain FORWARD { # handle 2
type filter hook forward priority filter; policy accept;
iifname "if1" accept # handle 96
iifname "if2" accept # handle 95
iifname "if3" accept # handle 94
ct state invalid drop # handle 15
jump NETAVARK-ISOLATION-1 # handle 16
ip daddr 172.22.222.0/24 ct state established,related accept # handle 25
ip saddr 172.22.222.0/24 accept # handle 26
ip daddr 10.89.0.0/24 ct state established,related accept # handle 82
ip saddr 10.89.0.0/24 accept # handle 83
}
}
这时候,转发就正常了。
希望这次的记录能够帮忙其他可能会遇到同样问题的人。