iptables NAT不适用于来自dummynet的数据包

我有一个安装,我有主接口( eth0 )的多个接口别名(与私有IP)。

 eth0 Link encap:Ethernet HWaddr 0a:ed:01:17:53:b4 inet addr:10.0.1.220 Bcast:10.0.1.255 Mask:255.255.255.0 eth0:0 Link encap:Ethernet HWaddr 0a:ed:01:17:53:b4 inet addr:192.168.1.1 Bcast:0.0.0.0 Mask:255.255.255.0 eth0:1 Link encap:Ethernet HWaddr 0a:ed:01:17:53:b4 inet addr:192.168.1.2 Bcast:0.0.0.0 Mask:255.255.255.0 

我将这些别名分别应用于不同的networking整形策略。 为了使绑定到每个私有IP的进程能够与Internet通信,我使用iptables作为NAT来伪装IP地址到eth0的IP地址

 iptables -t nat -A POSTROUTING -s 192.168.1.1/24 -o eth0 -j MASQUERADE 

这很好。 如果我看到stream量离开eth0 ,我可以看到源IP已经正确更改。

 # Send pings using eth0:0 ping -I 192.168.1.1 www.google.com # Monitor packets sent out of eth0 tcpdump -i eth0 icmp # 21:34:18.664664 IP ip-10-0-1-220.ec2.internal > ord37s08-in-f4.1e100.net: ICMP echo request, id 3957, seq 2, length 64 # 21:34:18.683022 IP ord37s08-in-f4.1e100.net > ip-10-0-1-220.ec2.internal: ICMP echo reply, id 3957, seq 2, length 64 # 21:34:19.666137 IP ip-10-0-1-220.ec2.internal > ord37s08-in-f4.1e100.net: ICMP echo request, id 3957, seq 3, length 64 # 21:34:19.683954 IP ord37s08-in-f4.1e100.net > ip-10-0-1-220.ec2.internal: ICMP echo reply, id 3957, seq 3, length 64 # 21:34:28.774873 IP ip-10-0-1-220.ec2.internal > ord37s08-in-f4.1e100.net: ICMP echo request, id 3962, seq 1, length 64 # 21:34:28.793410 IP ord37s08-in-f4.1e100.net > ip-10-0-1-220.ec2.internal: ICMP echo reply, id 3962, seq 1, length 64 

对于stream量整形,我使用了dummynet + ipfw。 当我为每个别名创build必要的stream量调整策略时。

 # Apply an outbound bandwidth cap of 1Mbps to eth0:0 ipfw pipe 1 config bw 1Mbit/s ipfw queue 1 config pipe 1 queue 100 ipfw add queue 1 ip from 192.168.1.1 to any 

那么由dummynet生成的数据包实际上从来没有被iptables看到,所以当stream量离开eth0 ,它有内部的私有IP,显然是永远不会得到答复的。

 # Send pings using eth0:0 ping -I 192.168.1.1 www.google.com # Monitor packets sent out of eth0 tcpdump -i eth0 icmp # 21:34:29.776431 IP 192.168.1.1 > ord37s08-in-f4.1e100.net: ICMP echo request, id 3962, seq 2, length 64 # 21:34:30.784435 IP 192.168.1.1 > ord37s08-in-f4.1e100.net: ICMP echo request, id 3962, seq 3, length 64 # 21:34:31.792440 IP 192.168.1.1 > ord37s08-in-f4.1e100.net: ICMP echo request, id 3962, seq 4, length 64 # 21:34:32.800446 IP 192.168.1.1 > ord37s08-in-f4.1e100.net: ICMP echo request, id 3962, seq 5, length 64 

当我看着iptables -t nat -vnL我可以确认这些数据包从来没有被iptables看到。

我意识到, ipfwiptables都使用底层netfilter库来处理数据包,并根据我的阅读,他们都挂钩到POSTROUTING挂钩。 他们有可能以某种方式竞争吗? 如果是这样,我可以以某种方式对netfilter的规则进行“重新sorting”,这样dummynet会将数据包重新input到stream中,以便iptables 。 有没有其他的方法来创build这些私人IP的NAT,以便我可以避免这种冲突?

不幸的是, ipfw的NATfunction似乎在将其移植到Linux时被删除,所以这是不可能的。

更新

在挖掘dummynet代码的时候,好像使用dst_output ( 这里是基于我的读取)应该调用ip_output ,然后执行NF_INET_POST_ROUTING netfilter钩子,将延迟的数据包重新注入堆栈。

当添加一些TRACE iptables规则时,

 iptables -A PREROUTING -t raw -p icmp -j TRACE iptables -A OUTPUT -t raw -p icmp -j TRACE 

我得到了以下。

没有运行dummynet(但使用接口别名):

 [23416.053128] TRACE: raw:OUTPUT:policy:2 IN= OUT=eth0 SRC=192.168.1.1 DST=172.217.7.164 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=37956 DF PROTO=ICMP TYPE=8 CODE=0 ID=12659 SEQ=1 UID=0 GID=0 [23416.053136] TRACE: nat:OUTPUT:policy:1 IN= OUT=eth0 SRC=192.168.1.1 DST=172.217.7.164 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=37956 DF PROTO=ICMP TYPE=8 CODE=0 ID=12659 SEQ=1 UID=0 GID=0 [23416.053139] TRACE: filter:OUTPUT:policy:1 IN= OUT=eth0 SRC=192.168.1.1 DST=172.217.7.164 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=37956 DF PROTO=ICMP TYPE=8 CODE=0 ID=12659 SEQ=1 UID=0 GID=0 [23416.053143] TRACE: nat:POSTROUTING:rule:1 IN= OUT=eth0 SRC=192.168.1.1 DST=172.217.7.164 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=37956 DF PROTO=ICMP TYPE=8 CODE=0 ID=12659 SEQ=1 UID=0 GID=0 [23416.055612] TRACE: raw:PREROUTING:policy:2 IN=eth0 OUT= MAC=0a:0d:f8:70:35:b4:0a:86:45:e6:5c:49:08:00 SRC=172.217.7.164 DST=10.0.1.255 LEN=84 TOS=0x00 PREC=0x00 TTL=47 ID=0 PROTO=ICMP TYPE=0 CODE=0 ID=12659 SEQ=1 [23416.055628] TRACE: filter:INPUT:policy:1 IN=eth0 OUT= MAC=0a:0d:f8:70:35:b4:0a:86:45:e6:5c:49:08:00 SRC=172.217.7.164 DST=192.168.1.1 LEN=84 TOS=0x00 PREC=0x00 TTL=47 ID=0 PROTO=ICMP TYPE=0 CODE=0 ID=12659 SEQ=1 [23417.054547] TRACE: raw:OUTPUT:policy:2 IN= OUT=eth0 SRC=192.168.1.1 DST=172.217.7.164 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=38092 DF PROTO=ICMP TYPE=8 CODE=0 ID=12659 SEQ=2 UID=0 GID=0 [23417.054557] TRACE: filter:OUTPUT:policy:1 IN= OUT=eth0 SRC=192.168.1.1 DST=172.217.7.164 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=38092 DF PROTO=ICMP TYPE=8 CODE=0 ID=12659 SEQ=2 UID=0 GID=0 [23417.055950] TRACE: raw:PREROUTING:policy:2 IN=eth0 OUT= MAC=0a:0d:f8:70:35:b4:0a:86:45:e6:5c:49:08:00 SRC=172.217.7.164 DST=10.0.1.255 LEN=84 TOS=0x00 PREC=0x00 TTL=47 ID=0 PROTO=ICMP TYPE=0 CODE=0 ID=12659 SEQ=2 [23417.055969] TRACE: filter:INPUT:policy:1 IN=eth0 OUT= MAC=0a:0d:f8:70:35:b4:0a:86:45:e6:5c:49:08:00 SRC=172.217.7.164 DST=192.168.1.1 LEN=84 TOS=0x00 PREC=0x00 TTL=47 ID=0 PROTO=ICMP TYPE=0 CODE=0 ID=12659 SEQ=2 [23418.056141] TRACE: raw:OUTPUT:policy:2 IN= OUT=eth0 SRC=192.168.1.1 DST=172.217.7.164 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=38099 DF PROTO=ICMP TYPE=8 CODE=0 ID=12659 SEQ=3 UID=0 GID=0 [23418.056157] TRACE: filter:OUTPUT:policy:1 IN= OUT=eth0 SRC=192.168.1.1 DST=172.217.7.164 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=38099 DF PROTO=ICMP TYPE=8 CODE=0 ID=12659 SEQ=3 UID=0 GID=0 [23418.057635] TRACE: raw:PREROUTING:policy:2 IN=eth0 OUT= MAC=0a:0d:f8:70:35:b4:0a:86:45:e6:5c:49:08:00 SRC=172.217.7.164 DST=10.0.1.255 LEN=84 TOS=0x00 PREC=0x00 TTL=47 ID=0 PROTO=ICMP TYPE=0 CODE=0 ID=12659 SEQ=3 [23418.057646] TRACE: filter:INPUT:policy:1 IN=eth0 OUT= MAC=0a:0d:f8:70:35:b4:0a:86:45:e6:5c:49:08:00 SRC=172.217.7.164 DST=192.168.1.1 LEN=84 TOS=0x00 PREC=0x00 TTL=47 ID=0 PROTO=ICMP TYPE=0 CODE=0 ID=12659 SEQ=3 

在dummynet运行的情况下(你可以看到POSTROUTING NAT策略从未被应用。

 [23535.355649] TRACE: raw:OUTPUT:policy:2 IN= OUT=eth0 SRC=192.168.1.1 DST=216.58.217.132 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=43670 DF PROTO=ICMP TYPE=8 CODE=0 ID=12715 SEQ=1 UID=0 GID=0 [23535.355657] TRACE: nat:OUTPUT:policy:1 IN= OUT=eth0 SRC=192.168.1.1 DST=216.58.217.132 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=43670 DF PROTO=ICMP TYPE=8 CODE=0 ID=12715 SEQ=1 UID=0 GID=0 [23535.355661] TRACE: filter:OUTPUT:policy:1 IN= OUT=eth0 SRC=192.168.1.1 DST=216.58.217.132 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=43670 DF PROTO=ICMP TYPE=8 CODE=0 ID=12715 SEQ=1 UID=0 GID=0 [23536.362312] TRACE: raw:OUTPUT:policy:2 IN= OUT=eth0 SRC=192.168.1.1 DST=216.58.217.132 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=43689 DF PROTO=ICMP TYPE=8 CODE=0 ID=12715 SEQ=2 UID=0 GID=0 [23536.362324] TRACE: nat:OUTPUT:policy:1 IN= OUT=eth0 SRC=192.168.1.1 DST=216.58.217.132 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=43689 DF PROTO=ICMP TYPE=8 CODE=0 ID=12715 SEQ=2 UID=0 GID=0 [23536.362330] TRACE: filter:OUTPUT:policy:1 IN= OUT=eth0 SRC=192.168.1.1 DST=216.58.217.132 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=43689 DF PROTO=ICMP TYPE=8 CODE=0 ID=12715 SEQ=2 UID=0 GID=0 [23537.370345] TRACE: raw:OUTPUT:policy:2 IN= OUT=eth0 SRC=192.168.1.1 DST=216.58.217.132 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=43819 DF PROTO=ICMP TYPE=8 CODE=0 ID=12715 SEQ=3 UID=0 GID=0 [23537.370379] TRACE: nat:OUTPUT:policy:1 IN= OUT=eth0 SRC=192.168.1.1 DST=216.58.217.132 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=43819 DF PROTO=ICMP TYPE=8 CODE=0 ID=12715 SEQ=3 UID=0 GID=0 [23537.370385] TRACE: filter:OUTPUT:policy:1 IN= OUT=eth0 SRC=192.168.1.1 DST=216.58.217.132 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=43819 DF PROTO=ICMP TYPE=8 CODE=0 ID=12715 SEQ=3 UID=0 GID=0