veth
概述
veth是Linux的虚拟网卡,和其他虚拟网卡一样,它有两端。不同之处在于veth设备通常成对出现,成对的两个veth设备一端互相连接(类似于一条网线连接两块网卡),另外一端各自连接协议栈。
数据从协议栈流入veth设备后,将从另外一个与之相连的veth设备流出。
案例
veth设备通常用作容器中,实现容器连通外部网络,容器其实就是通过Namespace和CGroup技术实现进程隔离和限制的进程。
下面演示与主机不在同一个
net namespace
的进程如何访问外部网络若在虚拟机中操作,需要设置虚拟机管理软件网卡开启混杂模式,让目的非本机的mac地址通过虚拟机网卡。
方法1:通过bridge实现
网络示意图如下所示
netnamespace-01
以下操作均在net-namespace01
中
创建网桥br0
,并配置网络
ip link add br0 type bridge
启动网桥
ip link set br0 up
将物理网卡enp0s3
加入网桥br0
中,此时网络会中断,因为enp0s3
上原有的地址会消失,此时enp0s3
的功能相当于一根网线,起到将br0
与外界连接的作用。
ip link set enp0s3 master br0
br0
相当于交换机和网卡的功能,可以在上面配置ip
ip addr add 192.168.0.183/24 dev br0
配置网关地址,DNS,此处均为临时配置。
$ ip route add default via 192.168.0.1
$ echo 'nameserver 192.168.0.1' >> /etc/resolv.conf
此时可以正常访问外部网络
创建veth设备
ip link add veth1 type veth peer veth0
激活veth0
,并加入网桥br0
$ ip link set veth0 up
$ ip link set veth0 master br0
重新打开一个shell窗口,方便在两个namespace中操作
使用unshare
命令创建新的net namespace
,通过-f
选项fork一个新进程加入新的namespace,新进程运行bash程序
unshare -u -n -f /bin/bash
此时已进入了新的net namespace
环境中,修改主机名为namespace-02
以便区分
以下操作均在net-namespace02
中
$ hostname namespace-02
$ exec bash
以下操作均在net-namespace01
中
将veth1
加入新的namespace中, 3129
为namespace 02
中bash进程的PID,此时当前namespace中看不到veth1
,在namespace02
中才能看到。
ip link set veth1 netns 3129
net-namespace02
以下操作均在net-namespace02
中
激活veth1,并配置默认路由和DNS
$ ip link set veth1 up
$ ip addr add 192.168.0.185/24 dev veth1
$ ip route add default via 192.168.0.1
$ echo 'nameserver 192.168.0.1' >> /etc/resolv.conf
此时namespace02
中可以访问外网了。
方法2:iptables SNAT实现
网络连接示意图如下所示
net-namespace 01
以下操作均在namespace 01
中
开启ip forward
功能,实现路由转发
$ sysctl net.ipv4.ip_forward=1
# 确认是否开启
cat /proc/sys/net/ipv4/ip_forward
1
创建一对veth
设备veth0
和veth1
,然后激活veth0
,并为其配置IP:172.17.0.1/24
# 创建一对veth设备
$ ip link add veth1 type veth peer veth0
# 激活 veth0
$ ip link set veth0 up
# 配置IP
$ ip addr add 172.17.0.1/24 dev veth0
配置SNAT
, 将源地址172.17.0.0/24
转换为物理网卡enp0s3
的地址
iptables -t nat -A POSTROUTING -s 172.17.0.0/24 -j SNAT --to-source 192.168.0.183
使用unshare
创建新的net-namespace 02
重新启动一个shell窗口,执行以下命令
unshare -n -u -f /bin/bash
回到上一个shell窗口,继续执行以下命令
将veth1
加入到新的net-namespace 02
中, 2668为新namespace的bash进程PID
ip link set veth1 netns 2668
net-namespace 02
以下操作在net-namespace 02
中完成
修改主机名为namespace-02
以便区分,两个namespace的主机名互不影响,这要感谢uts namespace
, 我们使用unshare
命令的时候使用了-u
参数就是实现该隔离功能的。
$ hostname namespace-02
$ exec bash
激活veth1
,并配置IP地址、默认路由和DNS
$ ip link set veth1 up
$ ip a a 172.17.0.100/24 dev veth1
$ ip r a default via 172.17.0.1
$ echo 'nameserver 223.5.5.5' >> /etc/resolv.conf
此时就可以访问外部网络了
$ ping www.baidu.com -c 2