Netplan/DHCP 配置:将请求从一个桥接端口转发到另一个桥接端口

Netplan/DHCP 配置:将请求从一个桥接端口转发到另一个桥接端口

我正在尝试在 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.50192.168.1.51192.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;
}

带网关的 Windows 以太网配置

更新 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)在桥接级别进行过滤。此模块的其他用途包括iptablesphysdev匹配模块(允许匹配每个桥接端口,而不仅仅是每个桥接端口)。此匹配模块,无论何时使用任何网络命名空间,自动触发的加载br_netfilter,这对所有网络命名空间具有系统范围的影响(自内核 5.3 以来其他选项也是可能的,但它们与使用 Docker 不兼容)。

当然,当人们不需要这个模块或者根本不知道它的存在时,它可能会成为许多意想不到的后果的根源,甚至是错误的假设(例如:理所当然地认为iptables用于开启桥接转发功能(该接口为例外)。

Docker 加载br_netfilter内核模块以便正确隔离容器。

链路层(蓝色)部分Netfilter 和常规网络中的数据包流br_netfilter下面的示意图描述了当生效时包含 IPv4 数据包的以太网帧发生的情况:

Netfilter 和常规网络中的数据包流

一旦加载,所有帧都进入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 地址,不涉及路由。

相关内容