Skip to content

linux虚拟网桥接入实体网卡

本文将介绍虚拟网桥(bridge)接入实体网卡。

此前已经介绍过linux虚拟网桥(bridge)在容器中的作用,本次将来介绍将网桥接入实体网卡。

本文所依赖的环境为:

root@debian:~# hostnamectl
 Static hostname: windows11pro
       Icon name: windowsBooks
         Chassis: laptop 💻
Operating System: Debian GNU/Linux 12 (bookworm)  
          Kernel: Linux 6.1.0-26-amd64
    Architecture: x86-64
 Hardware Vendor: ASUSTeK COMPUTER INC.
  Hardware Model: X441UVK
Firmware Version: X441UVK.314
root@debian:~#

操作的是切记不要使用虚拟机如,vmwarevirtualbox等。

默认网卡混杂模式,在虚拟机中是没有开启的:https://docs.vmware.com/cn/VMware-vSphere/6.7/com.vmware.vsphere.security.doc/GUID-92F3AB1F-B4C5-4F25-A010-8820D7250350.html

关闭网络服务

默认情况下,NetworkManager.serviceLinux系统中的网络管理工具,负责自动分配ip地址等。由于要操作bridge,所以需要暂时将其给关闭掉。否则,后续单独开启网卡,又会拉取到ip地址等。

NetworkManager.service给停用掉,并且禁止开机自启。然后重启机器。

[root@localhost]:[~][tty:0]# systemctl disable NetworkManager.service
[root@localhost]:[~][tty:0]# systemctl stop NetworkManager.service
[root@localhost]:[~][tty:0]# reboot

重启完毕后,查看网络,应该是无ip地址,且网卡状态为DOWN的。

[root@localhost]:[~][tty:0]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute
       valid_lft forever preferred_lft forever
2: enp4s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 02:42:ac:11:65:bd brd ff:ff:ff:ff:ff:ff
[root@localhost]:[~][tty:0]#

网卡关闭后,我们需要手动配置一下ip,确保机器能够上网。

[root@localhost]:[~][tty:0]# ip addr add 192.168.100.136/24 dev enp4s0
[root@localhost]:[~][tty:0]#
[root@localhost]:[~][tty:0]# ip link set enp4s0 up
[root@localhost]:[~][tty:0]#
[root@localhost]:[~][tty:0]# ping 192.168.100.1 -c 3
PING 192.168.100.1 (192.168.100.1) 56(84) bytes of data.
64 bytes from 192.168.100.1: icmp_seq=1 ttl=64 time=1.06 ms
64 bytes from 192.168.100.1: icmp_seq=2 ttl=64 time=0.651 ms
64 bytes from 192.168.100.1: icmp_seq=3 ttl=64 time=0.654 ms

--- 192.168.100.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2023ms
rtt min/avg/max/mdev = 0.651/0.789/1.062/0.193 ms
[root@localhost]:[~][tty:0]#

配置ip后,并且手动启动网卡,ping网关没问题。

[root@localhost]:[~][tty:0]# ping 8.8.8.8 -c 3
ping: connect: Network is unreachable
[root@localhost]:[~][tty:0]#

但是ping外网会显示网络不可达,这是因为是手动添加的ip地址,路由信息需要配置,需要添加一条默认路由,指向网关即可。

[root@localhost]:[~][tty:0]# ip route
192.168.100.0/24 dev enp4s0 proto kernel scope link src 192.168.100.136
[root@localhost]:[~][tty:0]#
[root@localhost]:[~][tty:0]# ip route add default via 192.168.100.1
[root@localhost]:[~][tty:0]#
[root@localhost]:[~][tty:0]# ping -c 3 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=55 time=33.7 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=55 time=34.0 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=55 time=34.7 ms

--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 33.735/34.158/34.742/0.426 ms
[root@localhost]:[~][tty:0]#

如上,手动配置的ip也可以进行上网。需要清除该网卡上的ip信息,并且给关闭掉网络。

[root@localhost]:[~][tty:0]# ip link set enp4s0 down
[root@localhost]:[~][tty:0]#
[root@localhost]:[~][tty:0]# ip addr flush dev enp4s0
[root@localhost]:[~][tty:0]#
[root@localhost]:[~][tty:0]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute
       valid_lft forever preferred_lft forever
2: enp4s0: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
    link/ether 02:42:ac:11:65:bd brd ff:ff:ff:ff:ff:ff
[root@localhost]:[~][tty:0]#

创建虚拟桥接

创建一个桥接bridge

[root@localhost]:[~][tty:0]# ip link add name br0 type bridge
[root@localhost]:[~][tty:0]#
[root@localhost]:[~][tty:0]# 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: enp4s0: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel state DOWN mode DEFAULT group default qlen 1000
    link/ether 02:42:ac:11:65:bd brd ff:ff:ff:ff:ff:ff
3: br0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 0a:27:75:b4:30:69 brd ff:ff:ff:ff:ff:ff
[root@localhost]:[~][tty:0]#

enp4s0实体网卡加入到该虚拟桥接设备br0中。

[root@localhost]:[~][tty:0]# ip link set enp4s0 master br0

br0配置ip地址,注意这里是为桥接配置ip地址,而非enp4s0实体网络哦,因为接入到了bridge中,可以将enp4s0看做是一根网线。

[root@localhost]:[~][tty:0]# ip addr add 192.168.100.136/24 dev br0
[root@localhost]:[~][tty:0]#
[root@localhost]:[~][tty:0]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute
       valid_lft forever preferred_lft forever
2: enp4s0: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master br0 state DOWN group default qlen 1000
    link/ether 02:42:ac:11:65:bd brd ff:ff:ff:ff:ff:ff
3: br0: <BROADCAST,MULTICAST> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 0a:27:75:b4:30:69 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.136/24 scope global br0
       valid_lft forever preferred_lft forever
[root@localhost]:[~][tty:0]#

配置完成后,需要启动br0enp4s0网卡,

[root@localhost]:[~][tty:0]# ip link set br0 up
[root@localhost]:[~][tty:0]# ip link set enp4s0 up
[root@localhost]:[~][tty:0]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute
       valid_lft forever preferred_lft forever
2: enp4s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
    link/ether 02:42:ac:11:65:bd brd ff:ff:ff:ff:ff:ff
    inet6 fe80::56e1:adff:fee7:de8d/64 scope link
       valid_lft forever preferred_lft forever
3: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 0a:27:75:b4:30:69 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.136/24 scope global br0
       valid_lft forever preferred_lft forever
    inet6 fe80::827:75ff:feb4:3069/64 scope link
       valid_lft forever preferred_lft forever
[root@localhost]:[~][tty:0]#

可以看到,此时2个网卡的状态都是UP

尝试ping一下网关。

[root@localhost]:[~][tty:0]# ping -c 3 192.168.100.1
PING 192.168.100.1 (192.168.100.1) 56(84) bytes of data.
64 bytes from 192.168.100.1: icmp_seq=1 ttl=64 time=1.53 ms
64 bytes from 192.168.100.1: icmp_seq=2 ttl=64 time=0.663 ms
64 bytes from 192.168.100.1: icmp_seq=3 ttl=64 time=0.666 ms

--- 192.168.100.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2009ms
rtt min/avg/max/mdev = 0.663/0.954/1.534/0.409 ms
[root@localhost]:[~][tty:0]#

再次添加默认路由后,ping外网。

[root@localhost]:[~][tty:0]# ip route add default via 192.168.100.1
[root@localhost]:[~][tty:0]# ping -c 3 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=55 time=40.6 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=55 time=36.2 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=55 time=40.2 ms

--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2005ms
rtt min/avg/max/mdev = 36.152/38.988/40.643/2.014 ms
[root@localhost]:[~][tty:0]#

可见,将实体网卡给到虚拟网桥,是行得通的。

创建虚拟网卡

现在需要操作的是,创建一对虚拟网卡,并且将其中一端放入net namespace中,另外一端加入刚刚创建好的bridge,并且为net namespace中的网卡配置ip地址,看是否能够和外部直接通信。

[root@localhost]:[~][tty:0]# ip link add name veth0 type veth peer name veth1
[root@localhost]:[~][tty:0]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute
       valid_lft forever preferred_lft forever
2: enp4s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
    link/ether 02:42:ac:11:65:bd brd ff:ff:ff:ff:ff:ff
    inet6 fe80::56e1:adff:fee7:de8d/64 scope link
       valid_lft forever preferred_lft forever
3: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 0a:27:75:b4:30:69 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.136/24 scope global br0
       valid_lft forever preferred_lft forever
    inet6 fe80::827:75ff:feb4:3069/64 scope link
       valid_lft forever preferred_lft forever
4: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether ba:00:10:0e:f2:df brd ff:ff:ff:ff:ff:ff
5: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether a6:27:b0:61:da:eb brd ff:ff:ff:ff:ff:ff
[root@localhost]:[~][tty:0]#

如上,创建了一对虚拟网卡,名称分别为veth0veth1

现在需要新开一个终端,创建一个全新的net namespace

[root@localhost]:[~][tty:1]# unshare -m -i -u -n -f /bin/bash
(unshare) [root@localhost]:[~][tty:1]#
(unshare) [root@localhost]:[~][tty:1]# echo $$
1283
(unshare) [root@localhost]:[~][tty:1]#
(unshare) [root@localhost]:[~][tty:1]# 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
(unshare) [root@localhost]:[~][tty:1]#

如上,创建了一个一个net namespace,查看ip,只有本地回环地址lo

切回原来的终端,将veth1移入到刚刚创建的net namespace中。

[root@localhost]:[~][tty:0]# ip link set veth1 netns 1283
[root@localhost]:[~][tty:0]#

回到net namespace后,可以看到已经移入过来的网卡地址。

(unshare) [root@localhost]:[~][tty:1]# 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: veth1@if6: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether ba:00:10:0e:f2:df brd ff:ff:ff:ff:ff:ff link-netnsid 0
(unshare) [root@localhost]:[~][tty:1]#

配置虚拟网卡地址

上述已经将veth1移入到了net namespace中,现在需要将外面的veth0给加入到bridge虚拟设备br0中,并且将网卡给打开。

[root@localhost]:[~][tty:0]# ip link set veth0 master br0
[root@localhost]:[~][tty:0]# ip link set veth0 up
[root@localhost]:[~][tty:0]#

net namespace中,需要为刚刚移入的veth1配置ip地址。

(unshare) [root@localhost]:[~][tty:1]# ip addr add 192.168.100.137/24 dev veth1
(unshare) [root@localhost]:[~][tty:1]#
(unshare) [root@localhost]:[~][tty:1]# 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: veth1@if6: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether ba:00:10:0e:f2:df brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.100.137/24 scope global veth1
       valid_lft forever preferred_lft forever
(unshare) [root@localhost]:[~][tty:1]#

并且将网卡给打开。

(unshare) [root@localhost]:[~][tty:1]# ip link set veth1 up
(unshare) [root@localhost]:[~][tty:1]#
(unshare) [root@localhost]:[~][tty:1]# 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: veth1@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether ba:00:10:0e:f2:df brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.100.137/24 scope global veth1
       valid_lft forever preferred_lft forever
    inet6 fe80::b800:10ff:fe0e:f2df/64 scope link tentative
       valid_lft forever preferred_lft forever
(unshare) [root@localhost]:[~][tty:1]#

尝试ping一下网关。

(unshare) [root@localhost]:[~][tty:1]# ping 192.168.100.1 -c 3
PING 192.168.100.1 (192.168.100.1) 56(84) bytes of data.
64 bytes from 192.168.100.1: icmp_seq=1 ttl=64 time=1.28 ms
64 bytes from 192.168.100.1: icmp_seq=2 ttl=64 time=0.704 ms
64 bytes from 192.168.100.1: icmp_seq=3 ttl=64 time=0.690 ms

--- 192.168.100.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2030ms
rtt min/avg/max/mdev = 0.690/0.890/1.278/0.273 ms
(unshare) [root@localhost]:[~][tty:1]#

但是ping外网,依然会报错网络不可达。

(unshare) [root@localhost]:[~][tty:1]# ping 8.8.8.8 -c 3
ping: connect: Network is unreachable
(unshare) [root@localhost]:[~][tty:1]#

这是因为在net namespace中,没有添加默认路由,需要添加上去即可。

(unshare) [root@localhost]:[~][tty:1]# ip route add default via 192.168.100.1
(unshare) [root@localhost]:[~][tty:1]#
(unshare) [root@localhost]:[~][tty:1]# ping 8.8.8.8 -c 3
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=55 time=36.9 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=55 time=34.6 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=55 time=33.5 ms

--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 33.493/35.014/36.908/1.418 ms
(unshare) [root@localhost]:[~][tty:1]#

总结

如果是桥接的真实网卡,且不做nat的话,则不需要进行ip转发,ip转发一般在不同网络之间通信才需要开启,比如,这台机器的转发就没有开,不影响它桥接虚拟网卡,和外部进行通信。

[root@localhost]:[~][tty:3]# cat /proc/sys/net/ipv4/ip_forward
0
[root@localhost]:[~][tty:3]#

还有,一定在真实的机器下操作,我操作了vmware等虚拟机,即使在linux中,开启了混合模式的情况下,外部ping veth的数据包最多只能达到br0,就丢了,应该是和虚拟机有关系。




linux虚拟网桥接入实体网卡

https://wangli2025.github.io/2024/11/22/linux_network_bridge-2.html

本站均为原创文章,采用 CC BY-NC-ND 4.0 协议。转载请注明出处,不得用于商业用途。

Comments