iptables 后端双版本冲突

6 阅读21分钟

dist/images/vpcnatgateway/nat-gateway.sh dist/images/vpcnatgateway/lb-svc.sh 这两个脚本在设计上只能使用 /usr/sbin/iptables-legacy 是吧?

不是。两个脚本在设计上并不绑定 legacy,它们只要求 iptables 工具链的命令行接口一致iptables -t nat -A ...iptables-save | grep ... 这类标准用法),legacy 和 nft 后端都能正确执行这些命令。

问题出在内核层面

场景iptables 后端内核钩子结果
Alpine (原 Dockerfile)脚本检测后显式用 iptables-legacy旧内核两套都走正常
Ubuntu 24.04 未改 alternatives默认 iptables-nftnftables正常(nft 写 nft 读)
Ubuntu 24.04 脚本检测走了 legacyiptables-legacy新内核优先 nftables规则失效

所以真正的坑是:nat-gateway.sh 里的检测逻辑在容器内 iptables-legacy -t nat -S INPUT 1 可能成功(宿主机内核加载了 ip_tables 模块),脚本切到 legacy 写规则,但新内核数据路径只看 nftables 表。

Dockerfile.ubuntu 里 update-alternatives --set iptables /usr/sbin/iptables-legacy 解决的是:让 iptablesiptables-legacy 指向同一个二进制,脚本无论走哪条分支都用 legacy,内核侧通过 ip_tables 模块处理 legacy 规则(容器共享宿主机内核,宿主机通常会加载该模块)。

如果未来想让脚本同时兼容 nft 后端,只需要去掉 Dockerfile 里的 update-alternatives 并删除脚本中 iptables-legacy 的检测分支,让 iptables_cmd 始终用系统默认即可,不需要改脚本的 iptables 规则操作逻辑。

从你提供的 nat-gateway.sh 脚本和 Dockerfile 来看,问题的原因完全闭环了:这是一个典型的“新镜像跑在了老逻辑”上的兼容性故障。

1. 致命原因:Ubuntu 24.04 的默认行为

你的 Dockerfile 使用了 FROM ubuntu:24.04

  • 新特性: 在 Ubuntu 24.04 (Noble Numbat) 中,系统的 iptables 命令默认链接到 iptables-nft

  • 脚本逻辑: 你的脚本中有这样一段逻辑:

    Bash

    iptables_cmd=$(which iptables)
    if iptables-legacy -t nat -S INPUT 1 2>/dev/null; then
        # use iptables-legacy for centos 7
        iptables_cmd=$(which iptables-legacy)
        ...
    fi
    

    这段逻辑设计的初衷是检测系统是否偏好 legacy。但在 Ubuntu 24.04 镜像里,虽然安装了 iptables 包(包含 legacy 和 nft),但脚本的检测逻辑可能失效,或者更糟糕的是:它虽然识别并使用了 iptables-legacy 去写入规则,但 Ubuntu 24.04 的内核协议栈默认只通过 nftables 钩子处理流量。

2. 为什么规则“完全无法命中”?

在 Ubuntu 24.04 这种较新的系统里,内核往往不再加载 ip_tables (Legacy) 模块,而是全面转向 nf_tables

  • 脚本: 将 DNAT 规则强行写入了 iptables-legacy 表。
  • 内核: 只盯着 nftables 的链看。
  • 错位: 你的规则在 Legacy 表里静静躺着,而流量在 NFT 链里穿行,因为 NFT 链里是空的,所以没有执行任何 NAT 动作,包直接撞到了本地 22 端口,由于没进程监听,内核回了 RST。

3. 如何修复?

方案 A:在 Dockerfile 中强制切换系统默认模式(推荐)

DockerfileRUN 指令中,明确设置容器内的 iptables 优先级,让 iptables 命令直接指向 legacy

Dockerfile

RUN update-alternatives --set iptables /usr/sbin/iptables-legacy && \
    update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy


root@jfcs1001:~# kgp |grep fip-subnet-69897ff101ca5d975cb0fdbb
kube-system                     vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0     1/1     Running            0                 94s     10.1.255.254      jfcs1003   <none>           <none>
root@jfcs1001:~# k exec -it -n kube-system                     vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0 -- bash
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: net1@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc htb state UP group default qlen 1000
    link/ether fa:83:79:f4:b5:de brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 183.240.180.136/27 scope global net1
       valid_lft forever preferred_lft forever
    inet6 fe80::f883:79ff:fef4:b5de/64 scope link
       valid_lft forever preferred_lft forever
3: ifb-net1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc htb state UNKNOWN group default qlen 1000
    link/ether b2:03:eb:47:1c:ef brd ff:ff:ff:ff:ff:ff
    inet6 fe80::b003:ebff:fe47:1cef/64 scope link
       valid_lft forever preferred_lft forever
323: eth0@if324: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue state UP group default
    link/ether d2:5e:08:c7:02:b5 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.1.255.254/16 brd 10.1.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::d05e:8ff:fec7:2b5/64 scope link
       valid_lft forever preferred_lft forever
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         183.240.180.129 0.0.0.0         UG    0      0        0 net1
10.1.0.0        0.0.0.0         255.255.0.0     U     0      0        0 eth0
10.233.0.0      10.1.0.1        255.255.0.0     UG    0      0        0 eth0
100.121.68.26   0.0.0.0         255.255.255.255 UH    0      0        0 net1
183.240.180.128 0.0.0.0         255.255.255.224 U     0      0        0 net1
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# iptables-legacy-save
# Generated by iptables-save v1.8.10 on Wed Feb 11 12:47:38 2026
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:DNAT_FILTER - [0:0]
:EXCLUSIVE_DNAT - [0:0]
:EXCLUSIVE_SNAT - [0:0]
:SHARED_DNAT - [0:0]
:SHARED_SNAT - [0:0]
:SNAT_FILTER - [0:0]
-A PREROUTING -j DNAT_FILTER
-A POSTROUTING -j SNAT_FILTER
-A DNAT_FILTER -j EXCLUSIVE_DNAT
-A DNAT_FILTER -j SHARED_DNAT
-A EXCLUSIVE_DNAT -d 183.240.180.136/32 -j DNAT --to-destination 10.1.0.2
-A EXCLUSIVE_SNAT -s 10.1.0.2/32 -j SNAT --to-source 183.240.180.136
-A SNAT_FILTER -j EXCLUSIVE_SNAT
-A SNAT_FILTER -j SHARED_SNAT
COMMIT
# Completed on Wed Feb 11 12:47:38 2026
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# telnet 10.1.0.2 22
Trying 10.1.0.2...
Connected to 10.1.0.2.
Escape character is '^]'.
SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.11
^]
telnet>
Connection closed.
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# telnet 183.240.180.136 22
Trying 183.240.180.136...
telnet: Unable to connect to remote host: Connection refused
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# ping 183.240.180.136
PING 183.240.180.136 (183.240.180.136) 56(84) bytes of data.
64 bytes from 183.240.180.136: icmp_seq=1 ttl=64 time=0.037 ms
64 bytes from 183.240.180.136: icmp_seq=2 ttl=64 time=0.043 ms
^C
--- 183.240.180.136 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1025ms
rtt min/avg/max/mdev = 0.037/0.040/0.043/0.003 ms
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# arping 183.240.180.136
Interface "lo" is not ARPable
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# tcpdump -i any port 22  -netvv
tcpdump: data link type LINUX_SLL2
tcpdump: listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
net1  In  ifindex 2 2a:e5:0d:36:50:72 ethertype IPv4 (0x0800), length 72: (tos 0x10, ttl 64, id 7599, offset 0, flags [DF], proto TCP (6), length 52)
    100.121.68.26.13128 > 183.240.180.136.22: Flags [S], cksum 0x1533 (incorrect -> 0x8fff), seq 2525037877, win 64240, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
ifb-net1 Out ifindex 3 2a:e5:0d:36:50:72 ethertype IPv4 (0x0800), length 72: (tos 0x10, ttl 64, id 7599, offset 0, flags [DF], proto TCP (6), length 52)
    100.121.68.26.13128 > 183.240.180.136.22: Flags [S], cksum 0x1533 (incorrect -> 0x8fff), seq 2525037877, win 64240, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
net1  Out ifindex 2 fa:83:79:f4:b5:de ethertype IPv4 (0x0800), length 60: (tos 0x10, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
    183.240.180.136.22 > 100.121.68.26.13128: Flags [R.], cksum 0xcbae (correct), seq 0, ack 2525037878, win 0, length 0
net1  B   ifindex 2 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 241, id 54321, offset 0, flags [none], proto TCP (6), length 40)
    152.42.131.4.52436 > 103.129.52.128.22: Flags [S], cksum 0x1e7e (correct), seq 2509600692, win 65535, length 0
ifb-net1 Out ifindex 3 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 241, id 54321, offset 0, flags [none], proto TCP (6), length 40)
    152.42.131.4.52436 > 103.129.52.128.22: Flags [S], cksum 0x1e7e (correct), seq 2509600692, win 65535, length 0
net1  B   ifindex 2 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 239, id 54321, offset 0, flags [none], proto TCP (6), length 44)
    152.42.131.4.52436 > 103.129.52.128.22: Flags [S], cksum 0x078a (correct), seq 2509600692, win 65535, options [mss 1260], length 0
ifb-net1 Out ifindex 3 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 239, id 54321, offset 0, flags [none], proto TCP (6), length 44)
    152.42.131.4.52436 > 103.129.52.128.22: Flags [S], cksum 0x078a (correct), seq 2509600692, win 65535, options [mss 1260], length 0
net1  B   ifindex 2 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 239, id 54321, offset 0, flags [none], proto TCP (6), length 44)
    152.42.131.4.52436 > 103.129.52.128.22: Flags [S], cksum 0x06c2 (correct), seq 2509600692, win 65535, options [mss 1460], length 0
ifb-net1 Out ifindex 3 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 239, id 54321, offset 0, flags [none], proto TCP (6), length 44)
    152.42.131.4.52436 > 103.129.52.128.22: Flags [S], cksum 0x06c2 (correct), seq 2509600692, win 65535, options [mss 1460], length 0
net1  B   ifindex 2 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 239, id 54321, offset 0, flags [none], proto TCP (6), length 44)
    152.42.131.4.52436 > 103.129.52.128.22: Flags [S], cksum 0x06c2 (correct), seq 2509600692, win 65535, options [mss 1460], length 0
ifb-net1 Out ifindex 3 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 239, id 54321, offset 0, flags [none], proto TCP (6), length 44)
    152.42.131.4.52436 > 103.129.52.128.22: Flags [S], cksum 0x06c2 (correct), seq 2509600692, win 65535, options [mss 1460], length 0
net1  B   ifindex 2 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x74, ttl 237, id 54321, offset 0, flags [none], proto TCP (6), length 40)
    80.94.92.168.43295 > 120.240.166.128.22: Flags [S], cksum 0xd4f1 (correct), seq 529745329, win 65535, length 0
ifb-net1 Out ifindex 3 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x74, ttl 237, id 54321, offset 0, flags [none], proto TCP (6), length 40)
    80.94.92.168.43295 > 120.240.166.128.22: Flags [S], cksum 0xd4f1 (correct), seq 529745329, win 65535, length 0
net1  B   ifindex 2 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x74, ttl 235, id 54321, offset 0, flags [none], proto TCP (6), length 44)
    80.94.92.168.43295 > 120.240.166.128.22: Flags [S], cksum 0xbdfd (correct), seq 529745329, win 65535, options [mss 1260], length 0
ifb-net1 Out ifindex 3 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x74, ttl 235, id 54321, offset 0, flags [none], proto TCP (6), length 44)
    80.94.92.168.43295 > 120.240.166.128.22: Flags [S], cksum 0xbdfd (correct), seq 529745329, win 65535, options [mss 1260], length 0
net1  B   ifindex 2 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x74, ttl 235, id 54321, offset 0, flags [none], proto TCP (6), length 44)
    80.94.92.168.43295 > 120.240.166.128.22: Flags [S], cksum 0xbd35 (correct), seq 529745329, win 65535, options [mss 1460], length 0
ifb-net1 Out ifindex 3 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x74, ttl 235, id 54321, offset 0, flags [none], proto TCP (6), length 44)
    80.94.92.168.43295 > 120.240.166.128.22: Flags [S], cksum 0xbd35 (correct), seq 529745329, win 65535, options [mss 1460], length 0
net1  B   ifindex 2 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x74, ttl 235, id 54321, offset 0, flags [none], proto TCP (6), length 44)
    80.94.92.168.43295 > 120.240.166.128.22: Flags [S], cksum 0xbd35 (correct), seq 529745329, win 65535, options [mss 1460], length 0
ifb-net1 Out ifindex 3 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x74, ttl 235, id 54321, offset 0, flags [none], proto TCP (6), length 44)
    80.94.92.168.43295 > 120.240.166.128.22: Flags [S], cksum 0xbd35 (correct), seq 529745329, win 65535, options [mss 1460], length 0
net1  B   ifindex 2 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 234, id 54321, offset 0, flags [none], proto TCP (6), length 40)
    178.128.248.99.40912 > 163.142.153.128.22: Flags [S], cksum 0x5a0d (correct), seq 667067961, win 65535, length 0
ifb-net1 Out ifindex 3 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 234, id 54321, offset 0, flags [none], proto TCP (6), length 40)
    178.128.248.99.40912 > 163.142.153.128.22: Flags [S], cksum 0x5a0d (correct), seq 667067961, win 65535, length 0
net1  B   ifindex 2 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 232, id 54321, offset 0, flags [none], proto TCP (6), length 44)
    178.128.248.99.40912 > 163.142.153.128.22: Flags [S], cksum 0x4319 (correct), seq 667067961, win 65535, options [mss 1260], length 0
ifb-net1 Out ifindex 3 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 232, id 54321, offset 0, flags [none], proto TCP (6), length 44)
    178.128.248.99.40912 > 163.142.153.128.22: Flags [S], cksum 0x4319 (correct), seq 667067961, win 65535, options [mss 1260], length 0
net1  B   ifindex 2 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 232, id 54321, offset 0, flags [none], proto TCP (6), length 44)
    178.128.248.99.40912 > 163.142.153.128.22: Flags [S], cksum 0x4251 (correct), seq 667067961, win 65535, options [mss 1460], length 0
ifb-net1 Out ifindex 3 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 232, id 54321, offset 0, flags [none], proto TCP (6), length 44)
    178.128.248.99.40912 > 163.142.153.128.22: Flags [S], cksum 0x4251 (correct), seq 667067961, win 65535, options [mss 1460], length 0
net1  B   ifindex 2 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 232, id 54321, offset 0, flags [none], proto TCP (6), length 44)
    178.128.248.99.40912 > 163.142.153.128.22: Flags [S], cksum 0x4251 (correct), seq 667067961, win 65535, options [mss 1460], length 0
ifb-net1 Out ifindex 3 20:0b:c7:3b:ec:16 ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 232, id 54321, offset 0, flags [none], proto TCP (6), length 44)
    178.128.248.99.40912 > 163.142.153.128.22: Flags [S], cksum 0x4251 (correct), seq 667067961, win 65535, options [mss 1460], length 0
^C
27 packets captured
27 packets received by filter
0 packets dropped by kernel
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn#
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn#
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: net1@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc htb state UP group default qlen 1000
    link/ether fa:83:79:f4:b5:de brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 183.240.180.136/27 scope global net1
       valid_lft forever preferred_lft forever
    inet6 fe80::f883:79ff:fef4:b5de/64 scope link
       valid_lft forever preferred_lft forever
3: ifb-net1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc htb state UNKNOWN group default qlen 1000
    link/ether b2:03:eb:47:1c:ef brd ff:ff:ff:ff:ff:ff
    inet6 fe80::b003:ebff:fe47:1cef/64 scope link
       valid_lft forever preferred_lft forever
323: eth0@if324: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue state UP group default
    link/ether d2:5e:08:c7:02:b5 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.1.255.254/16 brd 10.1.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::d05e:8ff:fec7:2b5/64 scope link
       valid_lft forever preferred_lft forever
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# root@jfcs1001:~# k exec -it -n kube-system                     vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0 -- bash
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: net1@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc htb state UP group default qlen 1000
    link/ether fa:83:79:f4:b5:de brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 183.240.180.136/27 scope global net1
       valid_lft forever preferred_lft forever
    inet6 fe80::f883:79ff:fef4:b5de/64 scope link
       valid_lft forever preferred_lft forever
3: ifb-net1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc htb state UNKNOWN group default qlen 1000
    link/ether b2:03:eb:47:1c:ef brd ff:ff:ff:ff:ff:ff
    inet6 fe80::b003:ebff:fe47:1cef/64 scope link
       valid_lft forever preferred_lft forever
323: eth0@if324: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue state UP group default
    link/ether d2:5e:08:c7:02:b5 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.1.255.254/16 brd 10.1.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::d05e:8ff:fec7:2b5/64 scope link
       valid_lft forever preferred_lft forever
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         183.240.180.129 0.0.0.0         UG    0      0        0 net1
10.1.0.0        0.0.0.0         255.255.0.0     U     0      0        0 eth0
10.233.0.0      10.1.0.1        255.255.0.0     UG    0      0        0 eth0
100.121.68.26   0.0.0.0         255.255.255.255 UH    0      0        0 net1
183.240.180.128 0.0.0.0         255.255.255.224 U     0      0        0 net1
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# iptables-legacy-save
# Generated by iptables-save v1.8.10 on Wed Feb 11 12:47:38 2026
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:DNAT_FILTER - [0:0]
:EXCLUSIVE_DNAT - [0:0]
:EXCLUSIVE_SNAT - [0:0]
:SHARED_DNAT - [0:0]
:SHARED_SNAT - [0:0]
:SNAT_FILTER - [0:0]
-A PREROUTING -j DNAT_FILTER
-A POSTROUTING -j SNAT_FILTER
-A DNAT_FILTER -j EXCLUSIVE_DNAT
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn#^Cd 0ueue state UP group default000n 65535, options [mss 1460], length 0TCP (6), length 44)),wscale 7], length 0
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# sysctl -a | grep "\.rp_filter"
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 2
net.ipv4.conf.eth0.rp_filter = 2
net.ipv4.conf.ifb-net1.rp_filter = 2
net.ipv4.conf.lo.rp_filter = 2
net.ipv4.conf.net1.rp_filter = 2
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# iptables-nft
iptables v1.8.10 (nf_tables): no command specified
Try `iptables -h' or 'iptables --help' for more information.
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# iptables-nft
iptables-nft          iptables-nft-restore  iptables-nft-save
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# iptables-nft-save
# Warning: iptables-legacy tables present, use iptables-legacy-save to see them
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# watch -n 1 "iptables -t nat -L EXCLUSIVE_DNAT -v -n"
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# ss -tunlp
Netid              State              Recv-Q              Send-Q                            Local Address:Port                             Peer Address:Port              Process
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# watch -n 1 "iptables-legacy -t nat -L EXCLUSIVE_DNAT -v -n"
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn#
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn#
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn# iptables-legacy -t nat -L EXCLUSIVE_DNAT -v -n
Chain EXCLUSIVE_DNAT (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 DNAT       0    --  *      *       0.0.0.0/0            183.240.180.136      to:10.1.0.2
root@vpc-nat-gw-fip-subnet-69897ff101ca5d975cb0fdbb-0:/kube-ovn#

根据你提供的一系列终端输出、抓包数据和截图,当前的问题可以总结为:流量路径与规则链条的“空间错位” ,导致 DNAT 规则虽然存在,但实际上处于“离线”状态。

以下是详细的问题总结:

1. 核心矛盾:iptables 后端双版本冲突

这是问题的根源。你的系统内同时存在两个 iptables 后端:Legacy(传统模式)和 NFT(nf_tables 模式)。

  • 规则在 Legacy: Kube-OVN 生成的 DNAT 规则(如 EXCLUSIVE_DNAT 链)全都在 iptables-legacy 表中。
  • 流量走 NFT: 内核当前默认使用 nftables 处理数据包。当你执行 iptables-nft-save 时,发现里面几乎是空的,且系统提示存在 Legacy 表警告。
  • 结果: 进入系统的流量在 nftables 层级寻找规则,匹配不到任何 DNAT 指令,因此直接跳过 NAT 逻辑,进入了本地(Local Input)流程。

2. 故障表现:为何 Telnet 失败而 Ping 成功?

  • 外部访问 (Telnet/SSH):

    • 外部包(100.121.68.26)到达接口 net1,目标 IP 是网关 IP 183.240.180.136
    • 因为 DNAT 没生效,系统认为这个包是发给“网关自己”的。
    • 网关 Pod 本身没有监听 22 端口,所以内核协议栈直接回了一个 RST(Reset)包。这解释了你在 tcpdump 中看到的 Flags [R.]
  • 内部测试 (Ping/Local Telnet):

    • 你在 Pod 内部 telnet 10.1.0.2 能通,是因为这走的是纯内网路由,不涉及 net1 的 DNAT。
    • ping 183.240.180.136 能通,是因为 ICMP 包被本地回环或接口地址直接响应了,不需要经过 DNAT 转换。

3. 数据链路确认:规则命中率为零

通过你上传的 watch 截图可以确认:

  • 命中数为 0:iptables-legacy 视图下,EXCLUSIVE_DNAT 链中的 pkts(包数)和 bytes(字节数)始终为 0。
  • 链路断裂: 流量在 PREROUTING 阶段就没有被正确引导进 DNAT_FILTER 链,或者是因为内核压根没去查 Legacy 表。

4. 潜在的次要阻碍:RP Filter 限制

虽然不是主因,但你的网络配置中 net1 接口的 rp_filter(反向路径过滤)设置为 2(松散模式)。

  • 在某些复杂的 VPC 网络(如 Kube-OVN 这种多接口环境)中,即便 DNAT 生效,如果内核认为回程路由不一致,仍可能在后期丢包。

结论与建议

当前问题的实质是 Kube-OVN 写入的规则位置(Legacy)与内核当前生效的规则引擎(NFT)不匹配

建议下一步操作:

  1. 强制同步: 尝试将规则手动写入 iptables-nft 看看流量计数是否开始跳动。
  2. 后端切换: 在容器内尝试执行 update-alternatives --set iptables /usr/sbin/iptables-legacy,迫使系统工具链统一。
  3. CNI 检查: 检查该节点的 kube-proxykube-ovn-cni 是否使用了混合模式,通常建议在集群范围内统一 iptables 模式。

你想让我帮你生成一段可以直接在 nftables 模式下生效的临时 DNAT 规则来测试吗?