我正在尝试在 Ubuntu 20.04 上配置桥接网络。桥接器中有 4 个以太网端口。相应的netplan
配置如下所示:
network:
version: 2
ethernets:
enp15s0:
dhcp4: no
dhcp6: no
enp12s0:
dhcp4: no
dhcp6: no
enp11s0:
dhcp4: no
dhcp6: no
enp10s0:
dhcp4: no
dhcp6: no
bridges:
br1:
interfaces: [enp12s0,enp11s0,enp10s0,enp15s0]
addresses: [192.168.1.1/24]
dhcp4: no
dhcp6: no
其中三个以太网端口连接了一些具有固定 IP 的硬件。这三个设备分别具有192.168.1.50
、192.168.1.51
和192.168.1.52
。此外,我们还有一个 dhcp 配置,它可确保当有人连接到 时enp15s0
,他将收到正确子网中的 IP,并能够访问连接的设备。dhcp 配置如下:
# dhcpd.conf
# option definitions common to all supported networks...
option domain-name "kira";
default-lease-time 600;
max-lease-time 7200;
# The ddns-updates-style parameter controls whether or not the server will
# attempt to do a DNS update when a lease is confirmed. We default to the
# behavior of the version 2 packages ('none', since DHCP v2 didn't
# have support for DDNS.)
ddns-update-style none;
# If this DHCP server is the official DHCP server for the local
# network, the authoritative directive should be uncommented.
#authoritative;
# Use this to send dhcp log messages to a different log file (you also
# have to hack syslog.conf to complete the redirection).
#log-facility local7;
# No service will be given on this subnet, but declaring it helps the
# DHCP server to understand the network topology.
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.100 192.168.1.199;
interface br1;
}
当我将 Windows PC 连接到enp15s0
端口时,我得到的结果如下:
- Windows PC 将获得 dhcp 分配的地址,例如
192.168.1.101
- 我可以从 Linux 机器顺利地 ping Windows PC
- 在 Linux 机器上,我可以使用
192.168.1.50-52
- 但是在 Windows 上,我只能 ping 通 Linux 机器
192.168.1.1
,但不能 ping 通这个桥接子网中的各个设备。 - 当我插入 PC 时,Windows 以太网配置如下所示:
有人能给我指出正确的方向吗,可能缺少了什么。我再次想要实现的是:插入 Windows PC 并能够让ping
所有设备挂在192.168.1.xx
子网中。
更新:
我已经在 dhcp 配置中添加了默认网关,现在 Windows PC 也接收了该网关,但问题仍然存在:
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.100 192.168.1.199;
interface br1;
option subnet-mask 255.255.255.0;
option routers 192.168.1.1;
}
更新 2
输出iptables-save
# Generated by iptables-save v1.8.4 on Fri Sep 25 17:05:52 2020
*filter
:INPUT ACCEPT [9581:2167049]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [9626:1660600]
:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
COMMIT
# Completed on Fri Sep 25 17:05:52 2020
# Generated by iptables-save v1.8.4 on Fri Sep 25 17:05:52 2020
*nat
:PREROUTING ACCEPT [2:398]
:INPUT ACCEPT [2:398]
:OUTPUT ACCEPT [259:17356]
:POSTROUTING ACCEPT [259:17356]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
COMMIT
# Completed on Fri Sep 25 17:05:52 2020
答案1
总结
在中添加例外规则DOCKER-用户Docker 用于此目的的链(从 filter/FORWARD 调用),以避免桥接以太网帧遍历iptables被最新版本的 Docker 设置的 filter/FORWARD 的 DROP 策略删除。如果没有模块帮助,iptables看到一个接口:桥接接口br1,而不是其桥接端口。
iptables -A DOCKER-USER -i br1 -o br1 -j ACCEPT
您必须弄清楚如何以及何时添加此规则。例如:Docker 是清空此链还是将其保留原样?如果没有清空,则任何顺序都可以,因此最早在启动时可能是最好的(在它前面加上iptables -N DOCKER-USER
);如果它被清空,则应该在启动 Docker 后完成。
请注意,下面描述的功能可能不会被需要,或者在很长时间内不会保持有用,因为nftables可以提供(大部分)都以更干净的方式。但一小部分还没有等效的nftables(喜欢VLAN 和 PPPoE 解封装/封装)。
还要注意br_netfilter
影响iptables-nft或者nftables‘知识产权家庭同样受到其影响iptables-旧版.它同样也会影响IPv6。
这br_netfilter
内核模块
当 Linux 配置为网桥时,要在此网桥上进行过滤,ebtables应该使用。但是ebtables功能比iptables处理 IPv4 流量时。特别是,要实现(透明)有状态桥接防火墙,Netfilter连接跟踪必须可用,但是ebtables无法使用它。因此,我们设计了一种机制,将包含 IPv4 数据包的第 2 层以太网帧暂时转换为第 3 层 IPv4 数据包,然后通过连接跟踪和iptables可以利用连接跟踪br_netfilter
然后将它们转换回以太网帧:这是内核模块在加载时的作用,并且bridge-nf-call-iptables
已设置(这是默认值)。这使得桥接框架横穿iptables甚至可能,如果它们最终被送往宿主,会再次穿过iptables作为路由数据包,如本文档。
该模块同样可以帮助其他协议(IPv6 和ip6tables、ARP、VLAN 和 PPPoE)在桥接级别进行过滤。此模块的其他用途包括iptables‘physdev
匹配模块(允许匹配每个桥接端口,而不仅仅是每个桥接端口)。此匹配模块,无论何时使用任何网络命名空间,自动触发的加载br_netfilter
,这对所有网络命名空间具有系统范围的影响(自内核 5.3 以来其他选项也是可能的,但它们与使用 Docker 不兼容)。
当然,当人们不需要这个模块或者根本不知道它的存在时,它可能会成为许多意想不到的后果的根源,甚至是错误的假设(例如:理所当然地认为iptables用于开启桥接转发功能(该接口为例外)。
Docker 加载br_netfilter
内核模块以便正确隔离容器。
链路层(蓝色)部分Netfilter 和常规网络中的数据包流br_netfilter
下面的示意图描述了当生效时包含 IPv4 数据包的以太网帧发生的情况:
一旦加载,所有帧都进入iptable的过滤器/FORWARD 链来自桥接路径(链路层蓝色字段内的绿色框),并达到其默认的 DROP 策略:没有任何东西被桥接,从那时起只有与桥接的通信有效iptables没有被调用。
解决不良影响
而不是阻止加载此模块或禁用它对 IPv4 的影响(可能对某些正在使用的功能是必要的)更好地应对了它的影响,如上一个链接. Docker 有一个专用链 DOCKER-USER它不会用于插入自定义规则,这就足够了:
iptables -A DOCKER-USER -i br1 -o br1 -j ACCEPT
或者如果没有外部 IP 地址:
iptables -A DOCKER-USER -s 192.168.1.0/24 -o 192.168.1.0/24 -j ACCEPT
该框架还会遍历其他表,例如纳特表,但现有的 Docker 规则不会影响此类帧(显然它也没有提供 DOCKER-USER 链)。不过,在添加自己的规则时要小心,以防止它们对桥接数据包产生影响,否则您的网桥可能会出现纳特任何穿越它的东西,在br1的 LAN 可以看到源 IP 为 192.168.1.1 的所有内容。
在不涉及标记的情况下,由于接口限制,这是一种可能的(但不完善的)方法,可以避免任何进一步制定的错误规则影响桥接路径(再次强调,目前根本不需要这些,所以我没有在 TL;DR 部分提及它们):
iptables -t nat -I PREROUTING -i br1 -d 192.168.1.0/24 -j ACCEPT
iptables -t nat -I POSTROUTING -s 192.168.1.0/24 -o br1 -j ACCEPT
不要使用任何“坏”规则。坏规则的一个例子是:
iptables -t nat -I POSTROUTING -o br1 -j MASQUERADE
这将不会桥接框架的源 IPv4 地址,不涉及路由。