有了上一篇關於tun/tap的介紹以後,你們應該對虛擬網絡設備有了必定的瞭解,本篇將接着介紹另外一種虛擬網絡設備veth。ubuntu
下面這張關係圖很清楚的說明了veth設備的特色:segmentfault
+----------------------------------------------------------------+ | | | +------------------------------------------------+ | | | Newwork Protocol Stack | | | +------------------------------------------------+ | | ↑ ↑ ↑ | |..............|...............|...............|.................| | ↓ ↓ ↓ | | +----------+ +-----------+ +-----------+ | | | eth0 | | veth0 | | veth1 | | | +----------+ +-----------+ +-----------+ | |192.168.1.11 ↑ ↑ ↑ | | | +---------------+ | | | 192.168.2.11 192.168.2.1 | +--------------|-------------------------------------------------+ ↓ Physical Network
上圖中,咱們給物理網卡eth0配置的IP爲192.168.1.11, 而veth0和veth1的IP分別是192.168.2.11和192.168.2.1。緩存
咱們經過示例的方式來一步一步的看看veth設備的特色。bash
先經過ip link命令添加veth0和veth1,而後配置veth0的IP,並將兩個設備都啓動起來網絡
dev@debian:~$ sudo ip link add veth0 type veth peer name veth1 dev@debian:~$ sudo ip addr add 192.168.2.11/24 dev veth0 dev@debian:~$ sudo ip link set veth0 up dev@debian:~$ sudo ip link set veth1 up
這裏不給veth1設備配置IP的緣由就是想看看在veth1沒有IP的狀況下,veth0收到協議棧的數據後會不會轉發給veth1。socket
ping一下192.168.2.1,因爲veth1還沒配置IP,因此確定不通tcp
dev@debian:~$ ping -c 4 192.168.2.1 PING 192.168.2.1 (192.168.2.1) 56(84) bytes of data. From 192.168.2.11 icmp_seq=1 Destination Host Unreachable From 192.168.2.11 icmp_seq=2 Destination Host Unreachable From 192.168.2.11 icmp_seq=3 Destination Host Unreachable From 192.168.2.11 icmp_seq=4 Destination Host Unreachable --- 192.168.2.1 ping statistics --- 4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 3015ms pipe 3
但爲何ping不通呢?是到哪一步失敗的呢?spa
先看看抓包的狀況,從下面的輸出能夠看出,veth0和veth1收到了一樣的ARP請求包,但沒有看到ARP應答包:code
dev@debian:~$ sudo tcpdump -n -i veth0 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on veth0, link-type EN10MB (Ethernet), capture size 262144 bytes 20:20:18.285230 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28 20:20:19.282018 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28 20:20:20.282038 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28 20:20:21.300320 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28 20:20:22.298783 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28 20:20:23.298923 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28 dev@debian:~$ sudo 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 262144 bytes 20:20:48.570459 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28 20:20:49.570012 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28 20:20:50.570023 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28 20:20:51.570023 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28 20:20:52.569988 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28 20:20:53.570833 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28
爲何會這樣呢?瞭解ping背後發生的事情後就明白了:blog
給veth1也配置上IP
dev@debian:~$ sudo ip addr add 192.168.2.1/24 dev veth1
再ping 192.168.2.1成功(因爲192.168.2.1是本地IP,因此默認會走lo設備,爲了不這種狀況,這裏使用ping命令帶上了-I參數,指定數據包走指定設備)
dev@debian:~$ ping -c 4 192.168.2.1 -I veth0 PING 192.168.2.1 (192.168.2.1) from 192.168.2.11 veth0: 56(84) bytes of data. 64 bytes from 192.168.2.1: icmp_seq=1 ttl=64 time=0.032 ms 64 bytes from 192.168.2.1: icmp_seq=2 ttl=64 time=0.048 ms 64 bytes from 192.168.2.1: icmp_seq=3 ttl=64 time=0.055 ms 64 bytes from 192.168.2.1: icmp_seq=4 ttl=64 time=0.050 ms --- 192.168.2.1 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3002ms rtt min/avg/max/mdev = 0.032/0.046/0.055/0.009 ms
注意:對於非debian系統,這裏有可能ping不通,主要是由於內核中的一些ARP相關配置致使veth1不返回ARP應答包,如ubuntu上就會出現這種狀況,解決辦法以下:
root@ubuntu:~# echo 1 > /proc/sys/net/ipv4/conf/veth1/accept_local
root@ubuntu:~# echo 1 > /proc/sys/net/ipv4/conf/veth0/accept_local
root@ubuntu:~# echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
root@ubuntu:~# echo 0 > /proc/sys/net/ipv4/conf/veth0/rp_filter
root@ubuntu:~# echo 0 > /proc/sys/net/ipv4/conf/veth1/rp_filter
再來看看抓包狀況,咱們在veth0和veth1上都看到了ICMP echo的請求包,但爲何沒有應答包呢?上面不是顯示ping進程已經成功收到了應答包嗎?
dev@debian:~$ sudo tcpdump -n -i veth0 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on veth0, link-type EN10MB (Ethernet), capture size 262144 bytes 20:23:43.113062 IP 192.168.2.11 > 192.168.2.1: ICMP echo request, id 24169, seq 1, length 64 20:23:44.112078 IP 192.168.2.11 > 192.168.2.1: ICMP echo request, id 24169, seq 2, length 64 20:23:45.111091 IP 192.168.2.11 > 192.168.2.1: ICMP echo request, id 24169, seq 3, length 64 20:23:46.110082 IP 192.168.2.11 > 192.168.2.1: ICMP echo request, id 24169, seq 4, length 64 dev@debian:~$ sudo 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 262144 bytes 20:24:12.221372 IP 192.168.2.11 > 192.168.2.1: ICMP echo request, id 24174, seq 1, length 64 20:24:13.222089 IP 192.168.2.11 > 192.168.2.1: ICMP echo request, id 24174, seq 2, length 64 20:24:14.224836 IP 192.168.2.11 > 192.168.2.1: ICMP echo request, id 24174, seq 3, length 64 20:24:15.223826 IP 192.168.2.11 > 192.168.2.1: ICMP echo request, id 24174, seq 4, length 64
看看數據包的流程就明白了:
抓一下lo設備上的數據,發現應答包確實是從lo口回來的:
dev@debian:~$ sudo 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 262144 bytes 20:25:49.590273 IP 192.168.2.1 > 192.168.2.11: ICMP echo reply, id 24177, seq 1, length 64 20:25:50.590018 IP 192.168.2.1 > 192.168.2.11: ICMP echo reply, id 24177, seq 2, length 64 20:25:51.590027 IP 192.168.2.1 > 192.168.2.11: ICMP echo reply, id 24177, seq 3, length 64 20:25:52.590030 IP 192.168.2.1 > 192.168.2.11: ICMP echo reply, id 24177, seq 4, length 64
ping 192.168.2.0/24網段的其它IP失敗,ping一個公網的IP也失敗:
dev@debian:~$ ping -c 1 -I veth0 192.168.2.2 PING 192.168.2.2 (192.168.2.2) from 192.168.2.11 veth0: 56(84) bytes of data. From 192.168.2.11 icmp_seq=1 Destination Host Unreachable --- 192.168.2.2 ping statistics --- 1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms dev@debian:~$ ping -c 1 -I veth0 baidu.com PING baidu.com (111.13.101.208) from 192.168.2.11 veth0: 56(84) bytes of data. From 192.168.2.11 icmp_seq=1 Destination Host Unreachable --- baidu.com ping statistics --- 1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms
從抓包來看,和上面第一種veth1沒有配置IP的狀況是同樣的,ARP請求沒人處理
dev@debian:~$ sudo tcpdump -i veth1 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on veth1, link-type EN10MB (Ethernet), capture size 262144 bytes 02:25:23.223947 ARP, Request who-has 192.168.2.2 tell 192.168.2.11, length 28 02:25:24.224352 ARP, Request who-has 192.168.2.2 tell 192.168.2.11, length 28 02:25:25.223471 ARP, Request who-has 192.168.2.2 tell 192.168.2.11, length 28 02:25:27.946539 ARP, Request who-has 123.125.114.144 tell 192.168.2.11, length 28 02:25:28.946633 ARP, Request who-has 123.125.114.144 tell 192.168.2.11, length 28 02:25:29.948055 ARP, Request who-has 123.125.114.144 tell 192.168.2.11, length 28
從上面的介紹中能夠看出,從veth0設備出去的數據包,會轉發到veth1上,若是目的地址是veth1的IP的話,就能被協議棧處理,不然連ARP那關都過不了,IP forward啥的都用不上,因此不借助其它虛擬設備的話,這樣的數據包只能在本地協議棧裏面打轉轉,無法走到eth0上去,即無法發送到外面的網絡中去。
下一篇將介紹Linux下的網橋,到時候veth設備就有用武之地了。