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