Macvlan 和 IPvlan - MKY-门可意

四月 17, 2025 [网络与安全] #Linux #obsidian #网络

Macvlan 和 IPvlan - MKY-门可意

介绍

   macvlan 本身是 linxu kernel 模块,其功能是允许在同一个物理网卡上配置多个 MAC 地址,即多个 interface,每个 interface 可以配置自己的 IP。**macvlan 本质上是一种网卡虚拟化技术(最大优点是性能极好)**

  可以在linux命令行执行`lsmod | grep macvlan` 查看当前内核是否加载了该driver;如果没有查看到,可以通过`modprobe macvlan`来载入,然后重新查看。内核代码路径/drivers/net/macvlan.c

   Macvlan 允许你在主机的一个网络接口上配置多个虚拟的网络接口,这些网络 `interface` 有自己独立的 MAC 地址,也可以配置上 IP 地址进行通信。Macvlan 下的虚拟机或者容器网络和主机在同一个网段中,共享同一个广播域。Macvlan 和 `Bridge` 比较相似,但因为它省去了 Bridge 的存在,所以配置和调试起来比较简单,而且效率也相对高。除此之外,Macvlan 自身也完美支持 `VLAN`。

工作模式(Bridge VS MACVlan)

Bridge Mode

提示:

    **Bridge 有可能会遇到二层环路,如有需要,可以开启 STP 来防止出现环路。**

MACVlan Mode

MACVlan模式

前三种模式示意图:

image

实验

Bridge Mode:创建了两个macvlan接口,分别放到两个netns中;然后验证这两个macvlan口之间客户互通。

设置网卡混杂模式(PROMISC网卡混杂标志): [root@localhost ~]#ifconfig ens224 promisc[root@localhost ~]# ifconfig ens224 ens224: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500 ………………

创建两个macvlan接口,其parent接口都是ens224

[root@localhost ~]# ip link add link ens224 name macv1 type macvlan mode bridge [root@localhost ~]# ip link add link ens224 name macv2 type macvlan mode bridge

查看接口状态:

image

创建namespace [root@localhost ~]# ip netns add net1 [root@localhost ~]# ip netns add net2

将macvlan接口插入到namespace [root@localhost ~]# ip link set macv1 netns net1 [root@localhost ~]# ip link set macv2 netns net2

设置网卡IP,设置网卡UP状态 ip netns exec net1 ip addr add 52.1.1.151/24 dev macv1 ip netns exec net2 ip addr add 52.1.1.152/24 dev macv2

设置网卡IP,设置网卡UP状态 [root@localhost ~]#ip netns exec net1 ip addr add 52.1.1.151/24 dev macv1[root@localhost ~]#ip netns exec net2 ip addr add 52.1.1.152/24 dev macv2 [root@localhost ~]#ip netns exec net1 ip link set macv1 up[root@localhost ~]#ip netns exec net2 ip link set macv2 up

查看网卡状态 [root@localhost ~]# ip netns exec net1 ip a 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 4: macv1@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000 link/ether 4e:a1:51:a9:3f:ef brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 52.1.1.151/24 scope global eth0 valid_lft forever preferred_lft forever [root@localhost ~]# ip netns exec net2 ip a 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 5: macv2@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000 link/ether fe:b5:85:c1:77:c1 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 52.1.1.152/24 scope global macv2 valid_lft forever preferred_lft forever

ping测试结果: net1和net2无法ping通宿主机,ping自己也不通.2个容器互相ping没有问题

更改容器内网卡名字

ip netns exec net1 ip link set mac1 name eth0

ipvlan

IPVlan 和 macvlan 类似,都是从一个主机接口虚拟出多个虚拟网络接口。一个重要的区别就是所有的虚拟接口都有相同的 macv 地址,而拥有不同的 ip 地址。因为所有的虚拟接口要共享 mac 地址,所有有些需要注意的地方:

Ipvlan 是 linux kernel 比较新的特性,linux kernel 3.19 开始支持 ipvlan,但是比较稳定推荐的版本是 >=4.2(因为 docker 对之前版本的支持有 bug),具体代码见内核目录:/drivers/net/ipvlan/

ipvlan模式

L2:

 ipvlan L2 模式和 macvlan bridge 模式工作原理很相似,父接口作为交换机来转发子接口的数据。同一个网络的子接口可以通过父接口来转发数据,而如果想发送到其他网络,报文则会通过父接口的路由转发出去。

L3:

 ipvlan 有点像路由器的功能,它在各个虚拟网络和主机网络之间进行不同网络报文的路由转发工作。只要父接口相同,即使虚拟机/容器不在同一个网络,也可以互相 ping 通对方,因为 ipvlan 会在中间做报文的转发工作。

模式架构图:

image

实验

创建IPVlan L3模式 [root@localhost ~]#ip link add link ens224 ipvlan1 type ipvlan mode l3[root@localhost ~]#ip link add link ens224 ipvlan2 type ipvlan mode l3

注意看ipvlan1 和ipvlan2 的MAC地址跟ens224的一样 [root@localhost ~]# ip link 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000 link/ether 00:0c:29:05:18:ac brd ff:ff:ff:ff:ff:ff 3: ens224: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000 link/ether 00:0c:29:05:18:b6 brd ff:ff:ff:ff:ff:ff 4: ipvlan1@enp0s3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 00:0c:29:05:18:b6 brd ff:ff:ff:ff:ff:ff 5: ipvlan2@enp0s3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether 00:0c:29:05:18:b6 brd ff:ff:ff:ff:ff:ff

创建ns绑定接口 [root@localhost ~]#ip net add net-1[root@localhost ~]#ip net add net-2 [root@localhost ~]#ip link set ipvlan1 netns net-1[root@localhost ~]#ip link set ipvlan2 netns net-2

配置IP [root@localhost ~]#ip net exec net-1 ip addr add 10.0.2.18/24 dev ipvlan1[root@localhost ~]#ip net exec net-2 ip addr add 10.0.3.19/24 dev ipvlan2 [root@localhost ~]#ip net exec net-1 ip link set ipvlan1 up[root@localhost ~]#ip net exec net-2 ip link set ipvlan2 up

增加路由 [root@localhost ~]#ip net exec net-1 route add default dev ipvlan1[root@localhost ~]#ip net exec net-2 route add default dev ipvlan2

ping测试 2个ns可以正常互相ping通,无法ping通宿主机IP

抓取ARP报文,结果无法在L3模式中抓到ARP,说明二层广播和组播都不处理,工作在L3.(这就是和L2模式的区别) [root@localhost ~]#ip net exec net-1 tcpdump -ni ipvlan1 -p arp

创建L2模式,其余操作跟L3一样 ip link add link enp0s3 ipvlan1 type ipvlan mode l2 ip link add link enp0s3 ipvlan2 type ipvlan mode l2

区别在于L2可以在2个ns中抓取到ARP报文

总结: ipvlan L3模式中外部网络默认情况下是不知道 ipvlan 虚拟出来的网络的,如果不在外部路由器上配置好对应的路由规则,ipvlan 的网络是不能被外部直接访问的。