我有一个设置,其中主网络接口()有多个接口别名(带有私有IP)eth0
。
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
我正在分别对每个别名应用不同的网络整形策略。为了让绑定到每个私有 IP 的进程能够与互联网通信,我使用iptables
NAT 将 IP 地址伪装成eth0
iptables -t nat -A POSTROUTING -s 192.168.1.1/24 -o eth0 -j MASQUERADE
这很有效。如果我观察离开的流量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
对于流量整形,我使用的是 dummynet+ipfw。当我为每个别名创建必要的流量整形策略时。
# 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
,因此当流量离开 时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
。
我意识到和都ipfw
在iptables
使用底层netfilter
库来处理数据包,根据我的阅读,它们都挂在钩子上POSTROUTING
。它们有可能以某种方式竞争吗?如果是这样,我是否可以以某种方式“重新排序”中的规则,netfilter
以便 dummynet 将数据包重新注入流中,以便 拾取它iptables
?有没有其他方法可以为这些私有 IP 创建 NAT,以便我可以避免这种冲突?
不幸的是,在将其移植到 Linux 时,NAT 功能ipfw
似乎已被删除,因此这是不可能的。
更新
当深入研究 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