veth pair上的两个ip能否ping通?

veth pair的两端在OS上表现为两块网卡,这两块网卡可以各自指定自己的ip地址,假设这两块网卡为veth1(10.10.10.101)和veth2(10.10.10.102)。

我试图弄清两个问题

问题一:经由ip1去ping ip2,能通吗?

ping -c 3 -I 10.10.10.101   10.10.10.102

问题二:经由网卡veth1去ping ip2,能通吗?

ping -c 3 -I veth1   10.10.10.102

先说答案:问题一能ping通,问题二无法ping通

对于问题二,书<<Kubernetes网络权威指南:基础、原理与实践>>中 1.3 连接你我他:Linux bridge,以及广为流传的文章“Linux 虚拟网络设备 veth-pair 详解,看这一篇就够了”,都说可以通的。但,我认为他们都错了,正确答案是不通。

前提:先设置环境

1. 使用 Ubuntu 20.04.1 LTS 进行验证

~$ sudo uname -a
Linux vm205 5.4.0-80-generic #90-Ubuntu SMP Fri Jul 9 22:49:44 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
~$ sudo lsb_release -a
No LSB modules are available.
Distributor ID:    Ubuntu
Description:    Ubuntu 20.04.1 LTS
Release:    20.04
Codename:    focal

2. 创建和设置veth pair

# 先删除 veth1和veth2。(注:为了方便多次验证执行)
sudo ip link del dev veth1
sudo ip link del dev veth2

# 创建veth pair,设置其ip并将其开启
sudo ip link add veth1 type veth peer name veth2
sudo ip addr add 10.10.10.101/24 dev veth1
sudo ip addr add 10.10.10.102/24 dev veth2
sudo ip link set veth1 up
sudo ip link set veth2 up

# 开启混杂模式。ens33是物理网卡
sudo ip link set dev ens33 promisc on
sudo ip link set dev veth1 promisc on
sudo ip link set dev veth2 promisc on

# 进入root 进行设置
su - root

# 设置内存中的ip_forward 和 持久化该设置
echo 1 > /proc/sys/net/ipv4/ip_forward
sudo vim /etc/sysctl.conf

# 设置veth pair的arp参数
echo 1 > /proc/sys/net/ipv4/conf/veth1/accept_local
echo 1 > /proc/sys/net/ipv4/conf/veth2/accept_local
echo 0 > /proc/sys/net/ipv4/conf/veth1/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/veth2/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter

# 退出root模式
exit

3. 创建完成后看下情况

marvin@vm205:~$ sudo ip -c addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:36:6c:24 brd ff:ff:ff:ff:ff:ff
    inet 192.168.86.205/24 brd 192.168.86.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 192.168.86.215/24 brd 192.168.86.255 scope global secondary noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe36:6c24/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:90:b4:6d:35 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
13: veth2@veth1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 0a:f9:9e:e6:f5:72 brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.102/24 scope global veth2
       valid_lft forever preferred_lft forever
    inet6 fe80::8f9:9eff:fee6:f572/64 scope link 
       valid_lft forever preferred_lft forever
14: veth1@veth2: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 1e:a8:d0:d6:6f:e4 brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.101/24 scope global veth1
       valid_lft forever preferred_lft forever
    inet6 fe80::1ca8:d0ff:fed6:6fe4/64 scope link 
       valid_lft forever preferred_lft forever
marvin@vm205:~$ 

一:验证问题一

问题一:经由ip1去ping ip2,能通吗?能通

marvin@vm205:~$ ping -c 3 -I 10.10.10.101   10.10.10.102
PING 10.10.10.102 (10.10.10.102) from 10.10.10.101 : 56(84) bytes of data.
64 bytes from 10.10.10.102: icmp_seq=1 ttl=64 time=0.056 ms
64 bytes from 10.10.10.102: icmp_seq=2 ttl=64 time=0.032 ms
64 bytes from 10.10.10.102: icmp_seq=3 ttl=64 time=0.034 ms

--- 10.10.10.102 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2033ms
rtt min/avg/max/mdev = 0.032/0.040/0.056/0.010 ms
marvin@vm205:~$ 

二:验证问题二

问题二:经由网卡veth1去ping ip2,能通吗?不通

marvin@vm205:~$ ping -c 3 -I veth1   10.10.10.102
PING 10.10.10.102 (10.10.10.102) from 10.10.10.101 veth1: 56(84) bytes of data.

--- 10.10.10.102 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2053ms

marvin@vm205:~$ 

三:解惑

为什么 经由veth1 ping ip2时,就不通了?我们先放下这个不管

先看下 能ping通的“经由ip1去ping ip2”抓包情况

ping -c 3 -I 10.10.10.101   10.10.10.102

在 veth1(10.10.10.101)、veth2(10.10.10.102)、loopback回环网卡 上同时抓包看情况
sudo tcpdump -n  -i  veth1
sudo tcpdump -n  -i  veth2
sudo tcpdump -n  -i  lo

结果如下:
veth1和veth2 都未捕获任何packet;loopback回环网卡上则抓到了如下包
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
17:20:38.337649 IP 10.10.10.101 > 10.10.10.102: ICMP echo request, id 4, seq 1, length 64
17:20:38.337658 IP 10.10.10.102 > 10.10.10.101: ICMP echo reply, id 4, seq 1, length 64
17:20:39.341490 IP 10.10.10.101 > 10.10.10.102: ICMP echo request, id 4, seq 2, length 64
17:20:39.341501 IP 10.10.10.102 > 10.10.10.101: ICMP echo reply, id 4, seq 2, length 64
17:20:40.366130 IP 10.10.10.101 > 10.10.10.102: ICMP echo request, id 4, seq 3, length 64
17:20:40.366142 IP 10.10.10.102 > 10.10.10.101: ICMP echo reply, id 4, seq 3, length 64

也就是说:ping -c 3 -I 10.10.10.101   10.10.10.102 时,ICMP request-reply 都是从 loopback回环网卡上 走的,根本就没走veth1和veth2。

再来看

ping -c 3 -I veth1   10.10.10.102
在 veth1(10.10.10.101)、veth2(10.10.10.102)、loopback回环网卡 上同时抓包看情况
sudo tcpdump -n  -i  veth1
sudo tcpdump -n  -i  veth2
sudo tcpdump -n  -i  lo

结果如下:

veth1
listening on veth1, link-type EN10MB (Ethernet), capture size 262144 bytes
16:21:58.234617 IP 10.10.10.101 > 10.10.10.102: ICMP echo request, id 3, seq 1, length 64
16:21:59.245917 IP 10.10.10.101 > 10.10.10.102: ICMP echo request, id 3, seq 2, length 64
16:22:00.269374 IP 10.10.10.101 > 10.10.10.102: ICMP echo request, id 3, seq 3, length 64
16:22:03.277288 ARP, Request who-has 10.10.10.102 tell 10.10.10.101, length 28
16:22:03.277335 ARP, Reply 10.10.10.102 is-at 0a:f9:9e:e6:f5:72, length 28
^C

veth2
listening on veth2, link-type EN10MB (Ethernet), capture size 262144 bytes
16:21:58.234623 IP 10.10.10.101 > 10.10.10.102: ICMP echo request, id 3, seq 1, length 64
16:21:59.245932 IP 10.10.10.101 > 10.10.10.102: ICMP echo request, id 3, seq 2, length 64
16:22:00.269392 IP 10.10.10.101 > 10.10.10.102: ICMP echo request, id 3, seq 3, length 64
16:22:03.277306 ARP, Request who-has 10.10.10.102 tell 10.10.10.101, length 28
16:22:03.277334 ARP, Reply 10.10.10.102 is-at 0a:f9:9e:e6:f5:72, length 28
^C

lo
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
16:21:58.234657 IP 10.10.10.102 > 10.10.10.101: ICMP echo reply, id 3, seq 1, length 64
16:21:59.245969 IP 10.10.10.102 > 10.10.10.101: ICMP echo reply, id 3, seq 2, length 64
16:22:00.269431 IP 10.10.10.102 > 10.10.10.101: ICMP echo reply, id 3, seq 3, length 64
^C

从veth1和veth2上的抓包可以看到

1. veth1不知道10.10.10.102的MAC地址,于是,veth1广播了arp request

2. veth2收到了arp请求,且,veth2广播了arp reply,且,veth1收到了广播的arp reply

arp层面上一切OK,再来看ICMP request-reply

1. veth1发出了ICMP request,且,veth2也收到了ICMP request

2. 但,veth2并未发出ICMP reply,当然,veth1也未收到ICMP reply

3. lo没收到ICMP request,但,lo发出了ICMP reply

最终,网卡veth1 并未收到 ICMP reply,因此也就ping不通。出现这种现象的原因是什么?

所有的网络不通,都可以从路由上找原因(我自己说的),看下路由表

marvin@vm205:~$ sudo ip -c route show
default via 192.168.86.2 dev ens33 proto static metric 100 
10.10.10.0/24 dev veth1 proto kernel scope link src 10.10.10.101 
10.10.10.0/24 dev veth2 proto kernel scope link src 10.10.10.102 
169.254.0.0/16 dev ens33 scope link metric 1000 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown 
192.168.86.0/24 dev ens33 proto kernel scope link src 192.168.86.205 metric 100 
192.168.86.0/24 dev ens33 proto kernel scope link src 192.168.86.215 metric 100 
marvin@vm205:~$ 

上面的路由表,看起来没啥问题,就是可以从veth1/veth2走,但, sudo ip route show 并不是全部路由。事实上,默认存在三张路由表,sudo ip route show 展示的是main。

sudo ip rule show 则展示了全部路由表,kernel搜索时的优先级就是此处的展示顺序

marvin@vm205:~$ sudo ip  rule show
0:	from all lookup local
32766:	from all lookup main
32767:	from all lookup default
marvin@vm205:~$ 

如上面的返回所示,local路由表优先级最高,它里面存放了 “如果抵达本地地址,以及,如果广播 该怎么走”的路由。 换句话说,local路由表告知kernel “如何抵达 OS自己的,OS本地的 地址”。

在我的实验中,local路由表内容如下

marvin@vm205:~$ sudo ip -c route show table local
broadcast 10.10.10.0 dev veth1 proto kernel scope link src 10.10.10.101 
broadcast 10.10.10.0 dev veth2 proto kernel scope link src 10.10.10.102 
local 10.10.10.101 dev veth1 proto kernel scope host src 10.10.10.101 
local 10.10.10.102 dev veth2 proto kernel scope host src 10.10.10.102 
broadcast 10.10.10.255 dev veth1 proto kernel scope link src 10.10.10.101 
broadcast 10.10.10.255 dev veth2 proto kernel scope link src 10.10.10.102 
broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1 
local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1 
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1 
broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1 
broadcast 172.17.0.0 dev docker0 proto kernel scope link src 172.17.0.1 linkdown 
local 172.17.0.1 dev docker0 proto kernel scope host src 172.17.0.1 
broadcast 172.17.255.255 dev docker0 proto kernel scope link src 172.17.0.1 linkdown 
broadcast 192.168.86.0 dev ens33 proto kernel scope link src 192.168.86.205 
local 192.168.86.205 dev ens33 proto kernel scope host src 192.168.86.205 
local 192.168.86.215 dev ens33 proto kernel scope host src 192.168.86.205 
broadcast 192.168.86.255 dev ens33 proto kernel scope link src 192.168.86.205 
marvin@vm205:~$ sudo ip -c route show table main

原文中说的是:It says 192.168.1.1 is a local address, which means if we want to send an ARP reply to 192.168.1.1, it's easy; we send it to ourself.
我这不是arp reply,而是ICMP reply,对于local路由表中的local address,给它发ICMP reply就很简单,发给自己就好了,此时就走 loopback回环网卡。

(注:最后这个结论是我根据下面链接推断的,但,写完这句话后,我就开始怀疑我的推断了,既然由于是local address,因此回来的ICMP reply走了loopback回环网卡,那为什么最初发出去的ICMP request不也走loopback回环网卡呢?)。 

https://unix.stackexchange.com/questions/205708/linux-does-not-reply-to-arp-request-messages-if-requested-ip-address-is-associat

完!

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值