veth 虚拟网络设备一端连着协议栈,另外一端不是物理网络,而是另一个 veth 设备,成对的 veth 设备中一个数据包发送出去后会直接到另一个 veth 设备上去。每个 veth 设备都可以被配置 IP 地址,并参与三层 IP 网络路由过程。

下面就是一个典型的 veth 设备对的例子:

我们配置物理网卡 eth0 的 IP 为 12.124.10.11, 而成对出现的 veth 设备分别为 veth0 和 veth1,它们的 IP 分别是 20.1.0.1020.1.0.11

1
2
3
4
5
# ip link add veth0 type veth peer name veth1
# ip addr add 20.1.0.10/24 dev veth0
# ip addr add 20.1.0.11/24 dev veth1
# ip link set veth0 up
# ip link set veth1 up

然后尝试从 veth0 设备 ping 另一个设备 veth1:

1
2
3
4
5
6
7
# ping -c 2 20.1.0.11 -I veth0
PING 20.1.0.11 (20.1.0.11) from 20.1.0.11 veth0: 28(42) bytes of data.
64 bytes from 20.1.0.11: icmp_seq=1 ttl=64 time=0.034 ms
64 bytes from 20.1.0.11: icmp_seq=2 ttl=64 time=0.052 ms

--- 20.1.0.11 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1500ms

Note: 在有些 Ubuntu 中有可能 ping 不通,原因是默认情况下内核网络配置导致 veth 设备对无法返回 ARP 返回包。解决办法是:

1
2
3
4
5
# echo 1 > /proc/sys/net/ipv4/conf/veth1/accept_local
# echo 1 > /proc/sys/net/ipv4/conf/veth0/accept_local
# echo 0 > /proc/sys/net/ipv4/conf/veth0/rp_filter
# echo 0 > /proc/sys/net/ipv4/conf/veth1/rp_filter
# echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter

可以尝试使用 tcpdump 看看在 veth 设备对上的请求包:

1
2
3
4
5
6
7
# tcpdump -n -i veth1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth1, link-type EN10MB (Ethernet), capture size 458122 bytes
20:24:12.220002 ARP, Request who-has 20.1.0.11 tell 20.1.0.10, length 28
20:24:12.220198 ARP, Request who-has 20.1.0.11 tell 20.1.0.10, length 28
20:24:12.221372 IP 20.1.0.10 > 20.1.0.11: ICMP echo request, id 18174, seq 1, length 64
20:24:13.222089 IP 20.1.0.10 > 20.1.0.11: ICMP echo request, id 18174, seq 2, length 64

可以看到在 veth1 上面只有 ICMP echo 的请求包,但是没有应答包。仔细想一下,veth1 收到 ICMP echo 请求包后,转交给另一端的协议栈,但是协议栈检查当前的设备列表,发现本地有 20.1.0.10,于是构造 ICMP echo 应答包,并转发给 lo 设备,lo 设备收到数据包之后直接交给协议栈,紧接着给交给用户空间的 ping 进程。

我们可以尝试使用 tcpdump 抓取 lo 设备上的数据:

1
2
3
4
5
# tcpdump -n -i lo
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 458122 bytes
20:25:49.486019 IP IP 20.1.0.11 > 20.1.0.10: ICMP echo reply, id 24177, seq 1, length 64
20:25:50.4861228 IP IP 20.1.0.11 > 20.1.0.10: ICMP echo reply, id 24177, seq 2, length 64

由此可见,对于成对出现的 veth 设备对,从一个设备出去的数据包会直接发给另外一个设备。在实际的应用场景中,比如容器网络中,成对的 veth 设备对处于不同的网络命名空间中,数据包的转发在不同网络命名空间之间进行,后续在介绍容器网络的时候会详细说明。