我们目前有几台服务器都使用同一个局域网:
Host1: eth0 10.0.0.1/24 Host2: eth0 10.0.0.2/24 Host3: eth0 10.0.0.3/24 Gateway: 10.0.0.254
我们想在这些服务器上运行一些虚拟机(VirtualBox)。 我们可以将它们设置为桥接到主机的eth0上,但是我们不能使用10.0.0.0/24范围内的地址,因为它们可能在将来被分配。
所以我们认为我们会使用一个不同的子网:
Host1VM: eth0 192.168.0.1/24 (bridge to host eth0) Host2VM: eth0 192.168.0.2/24 (bridge to host eth0) Host3VM: eth0 192.168.0.3/24 (bridge to host eth0)
这很好,所有的虚拟机都可以互相通信,因为它们使用相同的物理接口在同一个子网上。
我们面临的问题是我们需要通过10.0.0.254网关让这些虚拟机访问互联网。 所以我们计算了为什么不select其中一个主机,并将其用作路由器/ NAT?
Host1: eth0 10.0.0.1/24, eth0:0 192.168.0.254/24
现在我们可以给虚拟机一个192.168.0.254的网关。 然后我们看到的问题是,Host1似乎没有正确的NAT。
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j SNAT --to 10.0.0.1
我认为这将工作,我们确实看到它匹配的数据包。 如果一个虚拟机ping通了互联网,我们看到ICMP数据包进入到Host1(因为它是路由器),然后主机重新发送ICMP,因为它是NAT的,互联网主机回应主机 – 但随后它死在那里。 我希望主机然后将数据包转发回虚拟机,但它不。
我错过了什么,或者这个设置根本不可能?
编辑 :只是为了澄清,我们在iptables中没有DENY规则,一切都是默认的接受。 我们也启用IP转发。
Update1 – iptables
忽略virbr0 – 这与VirtualBox虚拟机无关
# Completed on Fri Sep 20 16:50:45 2013 # Generated by iptables-save v1.4.12 on Fri Sep 20 16:50:45 2013 *nat :PREROUTING ACCEPT [171383:10358740] :INPUT ACCEPT [1923:115365] :OUTPUT ACCEPT [192:21531] :POSTROUTING ACCEPT [169544:10254463] -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j SNAT --to-source 10.0.0.1 COMMIT # Completed on Fri Sep 20 16:50:45 2013 # Generated by iptables-save v1.4.12 on Fri Sep 20 16:50:45 2013 *filter :INPUT ACCEPT [96628707:25146145432] :FORWARD ACCEPT [195035595:22524430122] :OUTPUT ACCEPT [44035412:304951330498] -A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT -A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT -A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT -A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT -A FORWARD -d 192.168.122.0/24 -o virbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT -A FORWARD -s 192.168.122.0/24 -i virbr0 -j ACCEPT -A FORWARD -i virbr0 -o virbr0 -j ACCEPT -A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable -A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable COMMIT # Completed on Fri Sep 20 16:50:45 2013 # Generated by iptables-save v1.4.12 on Fri Sep 20 16:50:45 2013 *mangle :PREROUTING ACCEPT [291641356:47665886851] :INPUT ACCEPT [96628707:25146145432] :FORWARD ACCEPT [195035595:22524430122] :OUTPUT ACCEPT [44035838:304951365412] :POSTROUTING ACCEPT [239078922:327477732680] -A POSTROUTING -o virbr0 -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill -A POSTROUTING -o virbr0 -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill COMMIT # Completed on Fri Sep 20 16:50:45 2013
更新2 – tcpdump
16:58:37.189758 IP 192.168.0.2 > 74.125.128.106: ICMP echo request, id 1, seq 2, length 40 16:58:37.189805 IP 10.0.0.1 > 74.125.128.106: ICMP echo request, id 1, seq 2, length 40 16:58:37.194607 IP 74.125.128.106 > 10.0.0.1: ICMP echo reply, id 1, seq 2, length 40 (no final reply back to the VM)
这是说:
16:58:37.189758 IP 192.168.0.2 > 74.125.128.106: ICMP echo request, id 1, seq 2, length 40 16:58:37.189805 IP 10.0.0.1 > 74.125.128.106: ICMP echo request, id 1, seq 2, length 40 16:58:37.194607 IP 74.125.128.106 > 10.0.0.1: ICMP echo reply, id 1, seq 2, length 40
上游路由器( 10.0.0.254 )正在将回复发送回Host1,以便您的路由和SNAT正在工作。 问题是Host1没有将该答复传递回192.168.0.0/24networking。
你有适当的连接跟踪内核模块加载?
确保stream量进入连接跟踪表:
grep src=192.168.0.2 /proc/1/net/nf_conntrack
我发现TCP数据包有一个类似的问题,就是rp_filter一天,这是由内核中的rp_filter的。 我看不出这会是什么问题,但是非常相似。 你能从Host1发布路由表( ip route show )并检查你的rp_filter设置吗? ( cat /proc/sys/net/ipv4/conf/default/rp_filter )
我要回答我自己的问题,因为这是我解决它的方法。 我很确定其他答案在正常情况下比其他答案更准确,但我相信他们不工作,由于使用接口别名的错误或警告。
所以想到接口别名导致的问题,我寻找其他方式提供虚拟接口,事实certificate有一个虚拟接口types称为MAC-VLAN,它本质上附加到物理接口作为其虚拟接口自己的MAC地址。
使用NAT第一次完美地工作,所以我认为这只是由于MAC-VLAN接口在内核中作为一个完全独立的接口出现,而接口别名在某个地方引起了一些混淆。
作为参考,创buildMAC-VLAN的命令很简单:
ip link add dev macvlan0 link eth0 type macvlan
这是一个非常好的function,我不能相信我以前没有听说过。
我想知道为什么你需要NAT呢? 由于前缀不同,并且您正在路由stream量,为什么不在10.0.0.0/24networking的网关中通过虚拟机设置路由?
另外,当你configurationeth0:0 ,一般你configurationeth0 ,反之亦然。 使用eth0:1 ,或者更好的是,停止使用古代的networking工具工具,并改用iproute2( ip addr add 192.168.0.254/24 dev eth0等)。 这可能是问题,因为你的SNAT规则是正确的。 如果你的路由器不知道它是10.0.0.1,它不会返回返回的stream量。
如果ip addr show dev eth0显示你设置的两个地址,你的NATconfiguration正确,应该工作。 您可能遇到了一个错误,因为NAT正在使用不同的源地址在相同的接口上发送数据包,这是一种不寻常的情况。
然而,这个场景混乱的部分原因是ICMPredirect的存在。 通常认为这些东西是邪恶的(因为它们允许攻击者在某些情况下修改你的路由表),所以它们几乎总是被禁用的,但是当把stream量转发出来的时候,linux通常会发送它们。 在这种情况下,它基本上是一个消息,说“该主机在你的本地部分,你不需要通过我转发”。 这通常是正确的,除了因为SNAT,(前一跳)主机实际上确实需要这样做。 要禁用它们,使用这些sysctl设置:
net.ipv4.conf.eth0.send_redirects = 0 net.ipv4.conf.eth0.accept_redirects = 0
根据下一跳设备的不同,您可能需要重新启动该设备,以某种方式进行configuration,或者等待一会儿redirect消失,如果这是造成问题的原因。
考虑到拓扑结构,正如我所理解的,你最好的select就是让networking192.168.0.0/24networking访问路由器上的互联网。 你必须给路由器在networking192.168.0.0/24的地址才能工作。
如果您无法做到这一点,则必须使用MASQUERADE,但将其限制为不在VMnetworking上的目标。 每个主机上都有这样的东西:
iptables -A POSTROUTING -o eth0 ! -d 192.168.0.0/24 -j MASQUERADE
这样,所有虚拟机之间的stream量都不会改变,从虚拟机到其他networking的所有stream量都会随着主机地址一起出现。