问题:
使用 netplan 桥接多个 NIC 时,连接到桥接 NIC 的客户端主机无法与网关服务器通信。目标是让所有桥接 NIC 共享网关上的相同静态 IP 地址。如何配置 netplan 以正确桥接两个或更多 NIC?
动机:
我正在尝试模拟一个带网关的虚拟网络来模拟物理拓扑。这将允许我在部署到实时环境之前测试虚拟网络上的更改。
为此,我在 Ubuntu 22.04 主机上使用 Virtual Box、Ubuntu 22.04 客户虚拟机。我创建了一个网关虚拟机和四个客户端虚拟机进行测试。我创建了一个 VBox 桥接(网关)NIC 到我的物理 LAN。我还在虚拟网关上创建了四个 VBox 内部网络 NIC。每个 VBox 内部网络都有一个客户端虚拟机连接到每个 VBox 内部网络。四个客户端中的三个应该通过网关上的网桥共享相同的(静态)IP 地址。我不想使用 VBox DHCP 或 DNS,因为我正在尝试模拟物理拓扑。
故障排除:
我相信我已经将问题缩小到我的(虚拟)拓扑的桥接部分。
我可以从网关访问不在网桥上的客户端。事实上,如果我配置没有网桥的 netplan,我可以在各自的 NIC 上访问所有客户端。但是,如果我桥接任何 NIC,则远程主机没有响应。
网关上运行着 Kea DHCP 服务和 bind9 DNS 服务。所有客户端虚拟机都正确分配了地址。我可以通过运行
ip a
客户端来验证这一点。我也可以nslookup
在网关上验证客户端 IP 地址。我可以nslookup
在任何不在网桥中的客户端上为网关虚拟机执行此操作。通过网桥的客户端无法nslookup
在网关虚拟机上执行此操作。我曾经
tcpdump
在虚拟网关和客户端虚拟机上捕获 ICMP 数据包。捕获结果显示请求通过网桥和网卡离开网关。然后我看到客户端接收请求并发送回复。但是,网桥和网关网卡从未显示回复。将网桥上的yaml
macaddress
参数设置为任意网桥的 MAC 地址,interfaces
即可允许流量返回到该网关。设置
MACAddressPolicy=none
/usr/lib/systemd/network/99-default.link 从 yaml 列表中分配最后一个 NIC 的 MAC 地址,interfaces
允许流量返回到该网关。
虚拟机拓扑:
界面 | 桥 | IP地址 | 子网 CIDR | 附加主机 | 示例 DNS 地址 |
---|---|---|---|---|---|
enp0s3 | - | (来自外部局域网) | 192.168.1.0/24 | 栅极 * | 192.168.1.34/24 |
enp0s8 | - | 192.168.100.1 | 192.168.100.0/25 | 客户端3 + | 192.168.100.16/25 |
br0 | - | 192.168.100.129 | 192.168.100.128/26 | - | - |
enp0s9 | br0 | (来自 VM 网关) | “” | 客户端4 + | 192.168.100.130/26 |
enp0s10 | br0 | (来自 VM 网关) | “” | 客户5 + | 192.168.100.131/26 |
enp0s16 | br0 | (来自 VM 网关) | “” | 客户端6 + | 192.168.100.132/26 |
* 虚拟机网关
+ 虚拟机客户端
gateway
+---------------------------------+ client 3
| | +----------+
nnnnnnnnnn | enpos8 [ ]<--->[ ] enp0s3 |
nnnn nnnn | (192.168.100.1/25) | | (dhcp) |
( ) | | +----------+
( external network )<--->[ ] enp0s3 I |
( (192.168.1.0/24) ) | (dhcp) | client 4
( ) | | +----------+
uuuu uuuu | { enpos9 [ ]<--->[ ] enp0s3 |
uuuuuuuuuu | { | | (dhcp) |
| { | +----------+
| { |
| { | client 5
| { | +----------+
| br0 { enpos10 [ ]<--->[ ] enp0s3 |
| (192.168.100.129/26) { | | (dhcp) |
| { | +----------+
| { |
| { | client 6
| { | +----------+
| { enpos16 [ ]<--->[ ] enp0s3 |
| | | (dhcp) |
| | +----------+
+---------------------------------+
网络计划:
安装有netplan apply
。
网关网络计划
$> cat /etc/netplan/00-gateway.yaml
network:
version: 2
renderer: networkd
ethernets:
enp0s3:
dhcp4: true
dhcp6: false
nameservers:
search: [home.mylab.org]
addresses: [192.168.1.1]
enp0s8:
dhcp4: false
dhcp6: false
addresses: [192.168.100.1/25]
nameservers:
search: [home.mylabtest.org]
addresses: [192.168.100.1]
bridge4:
match:
name: enp0s9
bridge5:
match:
name: enp0s10
bridge6:
match:
name: enp0s16
bridges:
br0:
interfaces: [bridge4,bridge5,bridge6]
dhcp4: false
dhcp6: false
addresses: [192.168.100.129/26]
nameservers:
search: [home.mylabtest.org]
addresses: [192.168.100.1]
parameters:
stp: false
forward-delay: 30
客户网络计划
$> cat /etc/netplan/00-lan.yaml
network:
version: 2
renderer: networkd
ethernets:
enp0s3:
dhcp4: true
dhcp6: false
nameservers:
search: [home.mylabtest.org]
addresses: [192.168.100.1]
关口航线
$> ip r
default via 192.168.1.1 dev enp0s3 proto dhcp src 192.168.1.34 metric 100
192.168.1.0/24 dev enp0s3 proto kernel scope link src 192.168.1.34 metric 100
192.168.1.1 dev enp0s3 proto dhcp scope link src 192.168.1.34 metric 100
192.168.100.0/25 dev enp0s8 proto kernel scope link src 192.168.100.1
192.168.100.128/26 dev br0 proto kernel scope link src 192.168.100.129
网关 netfilter
$> nft list ruleset
table ip mangle {
chain PREROUTING {
type filter hook prerouting priority mangle; policy accept;
}
chain INPUT {
type filter hook input priority mangle; policy accept;
}
chain FORWARD {
type filter hook forward priority mangle; policy accept;
}
chain OUTPUT {
type route hook output priority mangle; policy accept;
}
chain POSTROUTING {
type filter hook postrouting priority mangle; policy accept;
}
}
table ip filter {
chain INPUT {
type filter hook input priority filter; policy accept;
iifname "enp0s3" ip daddr 192.168.100.0/24 ct state established,related counter packets 0 bytes 0 accept
}
chain FORWARD {
type filter hook forward priority filter; policy accept;
oifname "enp0s3" ip saddr 192.168.100.0/24 counter packets 0 bytes 0 accept
}
chain OUTPUT {
type filter hook output priority filter; policy accept;
}
chain LOGGING {
}
}
table ip nat {
chain PREROUTING {
type nat hook prerouting priority dstnat; policy accept;
}
chain INPUT {
type nat hook input priority 100; policy accept;
}
chain OUTPUT {
type nat hook output priority -100; policy accept;
}
chain POSTROUTING {
type nat hook postrouting priority srcnat; policy accept;
oifname "enp0s3" counter packets 189 bytes 15392 masquerade
}
}
网关接口
$> 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
valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 08:00:27:04:42:01 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.34/24 metric 100 brd 192.168.1.255 scope global dynamic enp0s3
valid_lft 554868sec preferred_lft 554868sec
inet6 fdca:ccc:607e:1c4b:a00:27ff:fe04:4201/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 1264sec preferred_lft 1264sec
inet6 fe80::a00:27ff:fe04:4201/64 scope link
valid_lft forever preferred_lft forever
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 08:00:27:9a:59:7b brd ff:ff:ff:ff:ff:ff
inet 192.168.100.1/25 brd 192.168.100.127 scope global enp0s8
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fe9a:597b/64 scope link
valid_lft forever preferred_lft forever
4: enp0s9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
link/ether 08:00:27:52:5a:65 brd ff:ff:ff:ff:ff:ff
5: enp0s10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
link/ether 08:00:27:54:3c:8a brd ff:ff:ff:ff:ff:ff
6: enp0s16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
link/ether 08:00:27:75:83:b4 brd ff:ff:ff:ff:ff:ff
7: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether da:13:a8:43:d8:34 brd ff:ff:ff:ff:ff:ff
inet 192.168.100.129/26 brd 192.168.100.191 scope global br0
valid_lft forever preferred_lft forever
inet6 fe80::d813:a8ff:fe43:d834/64 scope link
valid_lft forever preferred_lft forever
客户端接口
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
valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 08:00:27:47:8f:c7 brd ff:ff:ff:ff:ff:ff
inet 192.168.100.120/26 metric 100 brd 192.168.100.127 scope global dynamic enp0s3
valid_lft 3321sec preferred_lft 3321sec
inet6 fe80::a00:27ff:fe47:8fc7/64 scope link
valid_lft forever preferred_lft forever
VM 网关上的 tcpdump:
$> ping -c3 client4
PING client4.home.mylabtest.org (192.168.100.130) 56(84) bytes of data.
--- client4.home.mylabtest.org ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2025ms
$> tcpdump -i br0 -n icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on br0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
02:36:58.005888 IP 192.168.100.129 > 192.168.100.130: ICMP echo request, id 4, seq 1, length 64
02:36:59.008749 IP 192.168.100.129 > 192.168.100.130: ICMP echo request, id 4, seq 2, length 64
02:37:00.031348 IP 192.168.100.129 > 192.168.100.130: ICMP echo request, id 4, seq 3, length 64
$> tcpdump -i enp0s9 -n icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on enp0s9, link-type EN10MB (Ethernet), snapshot length 262144 bytes
02:36:58.005899 IP 192.168.100.129 > 192.168.100.130: ICMP echo request, id 4, seq 1, length 64
02:36:59.008773 IP 192.168.100.129 > 192.168.100.130: ICMP echo request, id 4, seq 2, length 64
02:37:00.031361 IP 192.168.100.129 > 192.168.100.130: ICMP echo request, id 4, seq 3, length 64
客户端虚拟机上的 tcpdump:
$> tcpdump -i enp0s3 -n icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on enp0s3, link-type EN10MB (Ethernet), snapshot length 262144 bytes
02:36:58.003563 IP 192.168.100.129 > 192.168.100.130: ICMP echo request, id 4, seq 1, length 64
02:36:58.003606 IP 192.168.100.130 > 192.168.100.129: ICMP echo reply, id 4, seq 1, length 64
02:36:59.006400 IP 192.168.100.129 > 192.168.100.130: ICMP echo request, id 4, seq 2, length 64
02:36:59.006436 IP 192.168.100.130 > 192.168.100.129: ICMP echo reply, id 4, seq 2, length 64
02:37:00.029006 IP 192.168.100.129 > 192.168.100.130: ICMP echo request, id 4, seq 3, length 64
02:37:00.029050 IP 192.168.100.130 > 192.168.100.129: ICMP echo reply, id 4, seq 3, length 64
VM 网关上的网络报告:
$> networkctl show
IDX LINK TYPE OPERATIONAL SETUP
1 lo loopback carrier unmanaged
2 enp0s3 ether routable configured
3 enp0s8 ether routable configured
4 enp0s9 ether enslaved configured
5 enp0s10 ether enslaved configured
6 enp0s16 ether enslaved configured
7 br0 bridge routable configured
7 links listed.
$> brctl show
bridge name bridge id STP enabled interfaces
br0 8000.da13a843d834 no enp0s10
enp0s16
enp0s9
$> netplan status
WARNING:root:Unknown device type: none
WARNING:root:Unknown device type: none
WARNING:root:Unknown device type: none
Online state: online
DNS Addresses: 127.0.0.53 (stub)
DNS Search: home.lab.org
home.labtest.org
● 1: lo ethernet UNKNOWN/UP (unmanaged)
MAC Address: 00:00:00:00:00:00
Addresses: 127.0.0.1/8
::1/128
Routes: ::1 metric 256
● 2: enp0s3 ethernet UP (networkd: enp0s3)
MAC Address: 08:00:27:89:13:55 (Intel Corporation)
Addresses: 192.168.13.117/24 (dhcp)
fdca:ccc:607e:1c4b:a00:27ff:fe89:1355/64
fe80::a00:27ff:fe89:1355/64 (link)
DNS Addresses: 192.168.13.1
DNS Search: home.lab.org
Routes: default via 192.168.13.1 from 192.168.13.117 metric 100 (dhcp)
192.168.13.0/24 from 192.168.13.117 metric 100 (link)
192.168.13.1 from 192.168.13.117 metric 100 (dhcp, link)
fdca:ccc:607e:1c4b::/64 metric 100 (ra)
fde7:2a4f:880b::/64 via fe80::185a:c799:e3d0:29f7 metric 100 (ra)
fe80::/64 metric 256
● 3: enp0s8 ethernet UP (networkd: enp0s8)
MAC Address: 08:00:27:53:59:8f (Intel Corporation)
Addresses: 192.168.100.1/25
fe80::a00:27ff:fe53:598f/64 (link)
DNS Addresses: 192.168.100.1
DNS Search: home.labtest.org
Routes: 192.168.100.0/25 from 192.168.100.1 (link)
fe80::/64 metric 256
● 4: enp0s9 ethernet UP (networkd: bridge4)
MAC Address: 08:00:27:f0:70:e5 (Intel Corporation)
● 5: enp0s10 ethernet UP (networkd: bridge5)
MAC Address: 08:00:27:90:f6:99 (Intel Corporation)
● 6: enp0s16 ethernet UP (networkd: bridge6)
MAC Address: 08:00:27:ae:41:4b (Intel Corporation)
● 7: br0 bridge UP (networkd: br0)
MAC Address: 42:dc:f8:69:8d:ad
Addresses: 192.168.100.129/26
fe80::40dc:f8ff:fe69:8dad/64 (link)
DNS Addresses: 192.168.100.1
DNS Search: home.labtest.org
Routes: 192.168.100.128/26 from 192.168.100.129 (link)
fe80::/64 metric 256
链接:
Netplan Yaml 桥
Netplan 如何
Netplan 示例
Ubuntu 手册页:systemd-networkd
Ubuntu 手册页:netplan
Netplan 错误 1
Netplan 错误 2