有了上一篇关于tun/tap的介绍之后,大家应该对虚拟网络设备有了一定的了解,本篇将接着介绍另一种虚拟网络设备veth。

veth设备的特点

  • veth和其它的网络设备都一样,一端连接的是内核协议栈。
  • veth设备是成对出现的,另一端两个设备彼此相连
  • 一个设备收到协议栈的数据发送请求后,会将数据发送到另一个设备上去。

下面这张关系图很清楚的说明了veth设备的特点:

+----------------------------------------------------------------+
|                                                                |
|       +------------------------------------------------+       |
|       |             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设备的特点。

只给一个veth设备配置IP

先通过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。

ping一下192.168.2.1,由于veth1还没配置IP,所以肯定不通

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不通呢?是到哪一步失败的呢?

先看看抓包的情况,从下面的输出可以看出,veth0和veth1收到了同样的ARP请求包,但没有看到ARP应答包:

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 28dev@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背后发生的事情后就明白了:

  1. ping进程构造ICMP echo请求包,并通过socket发给协议栈,
  2. 协议栈根据目的IP地址和系统路由表,知道去192.168.2.1的数据包应该要由192.168.2.11口出去
  3. 由于是第一次访问192.168.2.1,且目的IP和本地IP在同一个网段,所以协议栈会先发送ARP出去,询问192.168.2.1的mac地址
  4. 协议栈将ARP包交给veth0,让它发出去 由于veth0的另一端连的是veth1,所以ARP请求包就转发给了veth1
  5. veth1收到ARP包后,转交给另一端的协议栈
  6. 协议栈一看自己的设备列表,发现本地没有192.168.2.1这个IP,于是就丢弃了该ARP请求包,这就是为什么只能看到ARP请求包,看不到应答包的原因

给两个veth设备都配置IP

给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 64dev@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

看看数据包的流程就明白了:

  1. ping进程构造ICMP echo请求包,并通过socket发给协议栈,
  2. 由于ping程序指定了走veth0,并且本地ARP缓存里面已经有了相关记录,所以不用再发送ARP出去,协议栈就直接将该数据包交给了veth0
  3. 由于veth0的另一端连的是veth1,所以ICMP echo请求包就转发给了veth1
  4. veth1收到ICMP echo请求包后,转交给另一端的协议栈
  5. 协议栈一看自己的设备列表,发现本地有192.168.2.1这个IP,于是构造ICMP echo应答包,准备返回
  6. 协议栈查看自己的路由表,发现回给192.168.2.11的数据包应该走lo口,于是将应答包交给lo设备
  7. lo接到协议栈的应答包后,啥都没干,转手又把数据包还给了协议栈(相当于协议栈通过发送流程把数据包给lo,然后lo再将数据包交给协议栈的接收流程)
  8. 协议栈收到应答包后,发现有socket需要该包,于是交给了相应的socket
  9. 这个socket正好是ping进程创建的socket,于是ping进程收到了应答包

抓一下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下其它的IP

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 0msdev@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上去,即没法发送到外面的网络中去。

原文链接:https://segmentfault.com/a/1190000009251098

linux虚拟网络设备之veth(二)相关推荐

  1. Linux 虚拟网络设备

    一.tun/tap(虚拟网卡) TUN/TAP设备浅析(一) – 原理浅析 - 简书 (jianshu.com) (3条消息) Linux-虚拟网络设备-tun/tap_sld880311的专栏-CS ...

  2. Linux - 虚拟网络设备 - bridge,veth,namespace

    引用 轻松理解 Docker 网络虚拟化基础之网络 namespace! 轻松理解 Docker 网络虚拟化基础之 veth 设备! 深入理解 Linux 上软件实现的"交换机" ...

  3. 网络设备中的linux,理解linux虚拟网络设备veth

    原标题:理解linux虚拟网络设备veth 前面介绍了linux network namespace,接着介绍一下如何让一个独立的网络命名空间和主机的网络互通,这里我们需要用到linux虚拟网络设备v ...

  4. Linux 虚拟网络设备 tun/tap veth pair

    Linux 虚拟网络设备 tun/tap veth pair 本篇主要介绍一下 linux 下面的 虚拟网络设备 tun/tap veth pair 随着容器逐步取代虚拟机,成为云基础架构的标准,然而 ...

  5. linux 虚拟网络设备详解(四)

    Linux 抽象网络设备简介 和磁盘设备类似,Linux 用户想要使用网络功能,不能通过直接操作硬件完成,而需要直接或间接的操作一个 Linux 为我们抽象出来的设备,既通用的 Linux 网络设备来 ...

  6. linux虚拟网络设备--内核网桥的实现分析(六)

    一.Linux内核网桥的实现分析 Linux 内核分别在2.2 和 2.4内核中实现了网桥.但是2.2 内核和 2.4内核的实现有很大的区别,2.4中的实现几乎是全部重写了所有的实现代码.本文以2.4 ...

  7. linux虚拟网络设备之bridge(桥)(三)

    继前两篇介绍了tun/tap和veth之后,本篇将介绍Linux下常用的一种虚拟网络设备,那就是bridge(桥). 本篇将通过实际的例子来一步一步解释bridge是如何工作的. 什么是bridge? ...

  8. linux虚拟网络设备--eth, tap/tun, veth-pair(九)

    Linux 虚拟网络的背后都是由一个个的虚拟设备构成的.虚拟化技术没出现之前,计算机网络系统都只包含物理的网卡设备,通过网卡适配器,线缆介质,连接外部网络,构成庞大的 Internet. 然而,随着虚 ...

  9. linux虚拟网络设备--虚拟机网卡和linux bridge上tap设备的关系(七)

    1. 虚拟机进程 使用ps –ef |grepkvm可以看到虚拟机进程信息如下: /usr/libexec/qemu-kvm -nameinstance-0000001d -S -machine pc ...

最新文章

  1. C# 的快捷键汇总(一)
  2. python-opencv中的cv2.inRange函数
  3. shell基础:环境变量
  4. eureka 和zookeeper 区别 优势【转】
  5. 电脑工具栏怎么调整到下面_抖音怎么加字幕?如何制作短视频?
  6. Android的Recovery中font_10x10.h字库文件制作
  7. Codeforces 898E Squares and not squares
  8. 快速的找出元素是否在list中 python
  9. routing zuul_金三银四跳槽季快到了:送上Spring cloud全家桶系列之Zuul
  10. 【转】CSS transitions#CSS3变换入门
  11. 基于微信小程序做了个交友小程序
  12. 如何用JAVAC一次性编译多个包下的JAVA文件 ;JAVA和JAVAC 命令行;java 带有包名编译并运行,附带外部依赖jar包运行
  13. Java实现多个文件生成压缩包下载
  14. 串口的原始模式和标准模式
  15. 如何运营好微信公众号
  16. 我对价值投资的思考(二)
  17. Vue.js项目实战开发(4)- 必掌握知识点 - #博学谷IT学习技术支持#
  18. 计算机活动记录ppt,周村小学计算机兴趣小组活动记录.ppt
  19. 深度卷积神经网络是什么,计算机神经网络是什么
  20. 2.15 双创园区:武汉东湖高新区

热门文章

  1. python中数据分析的流程为-利用python进行数据分析——histogram
  2. python入门指南 许半仙 txt-第1题_峥嵘_玄幻奇幻_百家网
  3. python for-Python for 循环
  4. python入门教程非常详细-Python 基础教程
  5. 通过python建立一个web服务查看服务器上的文本、图片、视频等文件
  6. 如何获取html页面上的按钮列表,如何从一个html页面获取单选按钮的值到另一个?...
  7. lua学习笔记之开始
  8. LeetCode Binary Search Tree Iterator( 二叉树迭代器)
  9. 原理分析之三:初始化(配置文件读取和解析)
  10. libevent中的信号处理