我决定玩veth:创build一个veth对并从一端发送ping到另一端。
$ ip link add type veth $ ip addr add 192.168.99.1 dev veth4 $ ip addr add 192.168.99.2 dev veth5 $ ip link dev veth4 set up $ ip link dev veth5 set up
让我们检查。
$ ip a 18: veth4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 6a:dc:02:5b:f0:f3 brd ff:ff:ff:ff:ff:ff inet 192.168.99.1/24 scope global veth4 valid_lft forever preferred_lft forever 19: veth5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 22:ec:d5:e8:7c:3e brd ff:ff:ff:ff:ff:ff inet 192.168.99.2/24 scope global veth5 valid_lft forever preferred_lft forever
一切似乎都没问题。 现在尝试ping。
$ ping -I veth4 192.168.99.2 PING 192.168.99.2 (192.168.99.2) from 192.168.99.1 veth4: 56(84) bytes of data. From 192.168.99.1 icmp_seq=1 Destination Host Unreachable From 192.168.99.1 icmp_seq=2 Destination Host Unreachable From 192.168.99.1 icmp_seq=3 Destination Host Unreachable $ sudo tshark -i veth5 Capturing on 'veth5' l 1 0.000000 6a:dc:02:5b:f0:f3 -> Broadcast ARP 42 Who has 192.168.99.2? Tell 192.168.99.1 1 2 1.003206 6a:dc:02:5b:f0:f3 -> Broadcast ARP 42 Who has 192.168.99.2? Tell 192.168.99.1
所以veth5收到ARP请求,但不麻烦回答。 怎么了?
Veth对不是这样使用的。 一个veth对实际上是一个设备pipe道,pipe道包的一端从另一端出来。
我能够提供的最简单的同义词是想象一半是一个以太网设备,而另一端是设备插入的交换机端口。 你不应该把它看作是两个独立的设备,而是一个有两个“端”的设备。
这是一个非常复杂,非常古老的问题,涉及几个不同的领域,特别是VETH,networking命名空间,ARP,路由表和NAT …
我为这个问题增加了答案,不仅仅是为了OP,而是为了那些其他人,希望能够拯救别人,让他们脱离白发。
只要经过大量研究和testing – 完全可以用这种方式来使用 ,因为它们实际上是两个独立的虚拟接口。 但是,由于它们是虚拟的 – 你会遇到一些关于ARP表/条目的非常奇怪的问题。 经过几个星期的处理这个确切的场景(工作所必需的),我已经弄清楚了如何做到这一点,并在这个过程中学到了更多关于ARP,NAT和路由的方法,而不是我想要的。
为了完成你想要的东西,input以下内容(在我的情况下,Ubuntu 16.04)。 请注意 ,一旦你在test命名空间,你必须退出bash离开,因为从这一点上的一切(路由表,iptables等)是不同于在主机上。 我通常会打开两个terminal,一个留在主机 – 另一个留在客人名字空间。
# Tell the system we want to support IPv4 forwarding add/verify that the following is in `/etc/sysctl.conf` `net.ipv4.ip_forward = 1` # if it wasn't there, reparse syscrtl + restart networking sysctl -p; /etc/init.d/networking restart;
# create a veth pair ip link add name vHOST type veth peer name vGUEST # choose a private MAC address and private IP address ifconfig vHOST hw ether 02:1d:8d:dd:0c:61 ifconfig vHOST 10.11.0.1/24 up # have to setup routes FROM HOST -> GUEST ip route add 10.111.0.0/24 via 10.11.0.1 dev vHOST # gateway # have to explicitly assign what the MAC is for the vGUEST in the vHOST interface ARP table arp -i vHOST -s 10.111.0.1 02:1d:8d:dd:0c:60 # vGUEST ip + mac address # We must tell vHOST-vGUEST "tunnel", vHOST side that it's not a REAL bridge, so any ARP requests must be answered by vHOST echo 1 > /proc/sys/net/ipv4/conf/vHOST/proxy_arp # setup forwarding + NAT (so packets can come back) iptables -A FORWARD -s 10.111.0.0/24 -o vHOST -j ACCEPT iptables -t nat -A POSTROUTING -s 10.111.0.1 -j SNAT --to 192.168.42.124
# create the "test" namespace, so we can verfiy settings ip netns add test # add vGUEST "interface" to the "test" namespace ip link set vGUEST netns test # enter the "test" namespace with a bash shell ip netns exec test bash # choose a private MAC address and private IP address ifconfig vGUEST hw ether 02:1d:8d:dd:0c:60 ifconfig vGUEST 10.111.0.1/24 up # have to setup routes FROM GUEST -> HOST ip route add default via 10.111.0.1 dev vGUEST # gateway # have to explicitly assign what the MAC is for the vHOST in the vGUEST interface ARP table arp -i vGUEST -s 10.11.0.1 02:1d:8d:dd:0c:61 # vHOST ip + mac address
特别注意的是, multimac也可以做一些与veth完全相同的事情,方式稍微不同,multimac支持多对一的关系,veth是一对一的关系。
为了在没有命名空间的情况下支持这个,你必须使用策略路由 (这比networking命名空间稍微复杂一些)