gpt4 book ai didi

关于linux网桥(LinuxBridge)的一些个人记录

转载 作者:撒哈拉 更新时间:2025-01-09 20:38:57 57 4
gpt4 key购买 nike

目录
  • 1. Linux Bridge简述
  • 2. 网桥创建
    • 创建
    • 配置持久化
      • 在Debian/Ubuntu系统上:
      • 在CentOS/RHEL系统上:
    • 启用和验证
  • 3. 关于linux网桥不转发ip帧的问题
    • 原因
    • 解决
    • 配置持久化
  • 4. 查看网桥学习交换表
    • 手动添加或删除条目
      • 添加条目
      • 删除条目
    • 配置静态条目
    • 设置条目的老化时间
    • 持久化配置
  • 5. 关于linux网桥STP
  • 6. 关于linux网桥不转发LLDP帧
    • 原因
    • 解决
    • 持久化配置
  • 7. 网桥vlan
    • 配置持久化
  • 8. 其他
    • 1. 网卡混杂模式配置
    • 2. 网卡接收多播包配置
    • 3. 创建VLAN接口
  • 参考链接

作为一个工业自动化行业,常游走于各种 OT 网络和 IT 网络之间的人,linux 网桥是常使用的工具之一,每每涉及Linux 网桥, 这些记忆性的操作都要现查,零散且麻烦,所以简单整理一下,主要方便自己查询,同时分享给大家参考,希望对你有所帮助.

1. Linux Bridge简述

有了虚拟网卡,我们很自然就会联想到让网卡接入到交换机里,来实现多个容器间的相互连接。而Linux Bridge就是 Linux 系统下的虚拟化交换机,虽然它是以“网桥”(Bridge)而不是“交换机”(Switch)为名,但在使用过程中,你会发现 Linux Bridge 看起来像交换机,功能使用起来像交换机、程序实现起来也像交换机,所以它实际就是一台虚拟交换机.

Linux Bridge 是在 Linux Kernel 2.2 版本开始提供的二层转发工具,由brctl命令创建和管理。Linux Bridge 创建以后,就能够接入任何位于二层的网络设备,无论是真实的物理设备(比如 eth0),还是虚拟的设备(比如 veth 或者 tap),都能与 Linux Bridge 配合工作。当有二层数据包(以太帧)从网卡进入 Linux Bridge,它就会根据数据包的类型和目标 MAC 地址,按照如下规则转发处理:

  • 如果数据包是广播帧,转发给所有接入网桥的设备。如果数据包是单播帧,且 MAC 地址在地址转发表中不存在,则洪泛(Flooding)给所有接入网桥的设备,并把响应设备的接口与 MAC 地址学习(MAC Learning)到自己的 MAC 地址转发表中.

  • 如果数据包是单播帧,且 MAC 地址在地址转发表中已存在,则直接转发到地址表中指定的设备.

  • 如果数据包是此前转发过的,又重新发回到此 Bridge,说明冗余链路产生了环路。由于以太帧不像 IP 报文那样有 TTL 来约束,所以一旦出现环路,如果没有额外措施来处理的话,就会永不停歇地转发下去。那么对于这种数据包,就需要交换机实现生成树协议(Spanning Tree Protocol,STP)来交换拓扑信息,生成唯一拓扑链路以切断环路.

刚刚提到的这些名词,比如二层转发、泛洪、STP、MAC 学习、地址转发表,等等,都是物理交换机中已经非常成熟的概念了,它们在 Linux Bridge 中都有对应的实现,所以我才说,Linux Bridge 不仅用起来像交换机,实现起来也像交换机.

不过,它与普通的物理交换机也还是有一点差别的,普通交换机只会单纯地做二层转发,Linux Bridge 却还支持把发给它自身的数据包,接入到主机的三层协议栈中.

对于通过brctl命令显式接入网桥的设备,Linux Bridge 与物理交换机的转发行为是完全一致的,它也不允许给接入的设备设置 IP 地址,因为网桥是根据 MAC 地址做二层转发的,就算设置了三层的 IP 地址也没有意义。然而,Linux Bridge 与普通交换机的区别是,除了显式接入的设备外,它自己也无可分割地连接着一台有着完整网络协议栈的 Linux 主机,因为 Linux Bridge 本身肯定是在某台 Linux 主机上创建的,我们可以看作是 Linux Bridge 有一个与自己名字相同的隐藏端口,隐式地连接了创建它的那台 Linux 主机.

因此,Linux Bridge 允许给自己设置 IP 地址,这样就比普通交换机多出了一种特殊的转发情况:如果数据包的目的 MAC 地址为网桥本身,并且网桥设置了 IP 地址的话,那该数据包就会被认为是收到发往创建网桥那台主机的数据包,这个数据包将不会转发到任何设备,而是直接交给上层(三层)协议栈去处理。这时,网桥就取代了物理网卡 eth0 设备来对接协议栈,进行三层协议的处理.

涉及工具:

sudo apt-get install bridge-utils iproute2   # 对于Debian/Ubuntu系统

2. 网桥创建

创建

创建网桥br0 并将eth0、eth1 添加到网桥

# 创建网桥 br0
sudo brctl addbr br0

# 添加物理接口 eth0 到网桥
sudo brctl addif br0 eth0
sudo brctl addif br0 eth1

# set up
sudo ifconfig br0 up
sudo ifconfig br0 eth0
sudo ifconfig br0 eth1

或者使用ip命令:

# 使用 ip 命令
sudo ip link add name br0 type bridge
sudo ip link set dev br0 up
sudo ip link set dev eth0 master br0
sudo ip link set dev eth1 master br0

可以使用以下命令验证网桥和接口的配置:

# 查看网桥信息
sudo bridge link show
sudo bridge fdb show br0

# 或者
sudo brctl show

配置持久化

为了在系统重启后保持网桥配置,你需要将相应的配置添加到网络配置文件中.

在Debian/Ubuntu系统上:

编辑/etc/network/interfaces文件,添加如下内容:

auto br0
iface br0 inet static
    address 192.168.1.100
    netmask 255.255.255.0
    bridge_ports eth0 eth1
    bridge_stp on

在CentOS/RHEL系统上:

创建或编辑/etc/sysconfig/network-scripts/ifcfg-br0文件,添加如下内容:

DEVICE=br0
TYPE=Bridge
BOOTPROTO=static
IPADDR=192.168.1.100
NETMASK=255.255.255.0
ONBOOT=yes
STP=on

# 添加桥接的接口
BRIDGE_PORTS="eth0 eth1"

并确保eth0和eth1的配置文件中有以下内容:

# /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
ONBOOT=yes
BRIDGE=br0

# /etc/sysconfig/network-scripts/ifcfg-eth1
DEVICE=eth1
ONBOOT=yes
BRIDGE=br0

启用和验证

重新启动网络服务以应用配置:

# 对于Debian/Ubuntu
sudo systemctl restart networking

# 对于CentOS/RHEL
sudo systemctl restart network

通过检查网桥状态和接口状态来验证配置:

# 查看网桥信息
sudo bridge link show
sudo bridge fdb show br0

# 或者
sudo brctl show

3. 关于linux网桥不转发ip帧的问题

原因

Docker使用iptables时,默认将通过网桥的数据包发送到iptables进行处理,sysctl属性net.bridge.bridge-nf-call-iptables=1).

这使得桥接帧(以太网,第2层)受制于iptables filter(IP,第3层),导致网桥上的3层协议通信异常.

允许{ip、ip6、arp}表看到桥接通信可以使用位于/proc/sys/net/bridge/中的适当proc条目禁用或启用:

bridge-nf-call-arptables
bridge-nf-call-iptables
bridge-nf-call-ip6tables

对应内核桥模块识别的3个“可调参数”的设置:

net.bridge.bridge-nf-call-arptables
net.bridge.bridge-nf-call-ip6tables
net.bridge.bridge-nf-call-iptables

它们控制是否将通过网桥的数据包发送到iptables进行处理。在使用网桥将虚拟机连接到网络的情况下,通常这种处理是不希望的,因为它会导致guests流量被阻止,因为主机iptables规则只考虑主机本身,而不是guests.

然而,内核中的桥模块将所有这三个值的默认值设置为“1”(“on”,即“do send the packets to iptables”),并且由于历史原因,内核维护人员拒绝更改此默认值(参见http://patchwork.ozlabs.org/patch/29319/).

在内核拒绝了上述对编译默认值的更改之后,许多Linux发行版(包括Fedora,RHEL和CentOS)试图通过在/etc/sysctl.conf中添加行来修改编译到桥模块中的默认设置来解决这个问题:

net.bridge.bridge-nf-call-arptables = 0
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0

解决

要禁用br_netfilter's代码对iptable的调用,如下所示:

sudo sysctl -w net.bridge.bridge-nf-call-iptables=0
#或者
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables

内核(>= 5.3),在每个桥单独启用,而不是每个命名空间启用.

sudo ip link set dev br0 type bridge nf_call_iptables 1

参考链接https://wiki.libvirt.org/Net.bridge.bridge-nf-call_and_sysctl.conf.html 。

配置持久化

除使用最原始的脚本配置外,可以使用udev+systemd,在桥的创建(加载模块)上重写udev规则来实现.

1)在文件/etc/udev/rules.d/99-bridge.rules中:

ACTION=="add", SUBSYSTEM=="module", KERNEL=="br_netfilter", RUN+="/usr/lib/systemd/systemd-sysctl --prefix=net/bridge

2)在文件/etc/sysctl.d/bridge.conf中:

net.bridge.bridge-nf-call-arptables = 0
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0

3)重新引导或重新加载udev和sysctl.

4. 查看网桥学习交换表

使用bridge命令查看网桥的学习交换表:

bridge fdb show br br0

这个命令会展示网桥br0的当前学习交换表,包括各个MAC地址和它们对应的端口.

手动添加或删除条目

添加条目

你可以手动添加一个MAC地址到网桥的学习交换表中。假设你要将MAC地址00:11:22:33:44:55绑定到接口eth0:

sudo bridge fdb add 00:11:22:33:44:55 dev eth0 master br0

删除条目

同样,你可以手动删除一个MAC地址条目:

sudo bridge fdb del 00:11:22:33:44:55 dev eth0 master br0

配置静态条目

你可以配置静态条目,这样这些MAC地址永远不会从网桥的学习交换表中删除:

sudo bridge fdb add 00:11:22:33:44:55 dev eth0 

设置条目的老化时间

网桥会自动老化条目,并在一段时间不使用后删除它们。可以设置这个老化时间(以秒为单位):

sudo ip link set dev br0 type bridge ageing_time 300

这会将老化时间设置为300秒(5分钟).

持久化配置

为了在系统重启后保持这些配置,可以将相应的命令添加到启动脚本中。例如,在Debian/Ubuntu系统中,可以将这些命令添加到/etc/network/interfaces文件中:

auto br0
iface br0 inet static
    address 192.168.1.100
    netmask 255.255.255.0
    bridge_ports eth0 eth1
    post-up bridge fdb add 00:11:22:33:44:55 dev eth0 master br0 static

在CentOS/RHEL系统中,可以将命令添加到/etc/sysconfig/network-scripts/ifcfg-br0文件中:

DEVICE=br0
TYPE=Bridge
BOOTPROTO=static
IPADDR=192.168.1.100
NETMASK=255.255.255.0
ONBOOT=yes

# Add these lines to the end of the file
BRIDGE_STP=no
BRIDGE_PORTS="eth0 eth1"
BRIDGE_AGEING_TIME=300

# Add static FDB entries
POST_UP="bridge fdb add 00:11:22:33:44:55 dev eth0 master br0 static"

5. 关于linux网桥STP

STP的目的是防止网络环路,这可能导致网络中的流量风暴。Linux桥接从2.4和2.6内核系列开始就支持STP。要在网桥上启用STP:

sudo ip link set br0 type bridge stp_state 1
#或者
sudo brctl stp br0 on

注意:Linux网桥不支持快速生成树协议(RSTP) 。

网桥上显示STP阻塞状态:

sudo ip -j -p -d link show br0 | grep root_port
sudo bridge link show
#或
sudo brctl showstp br0

要更改STP call时间:

sudo ip link set br0 type bridge hello_time 300

sudo ip -j -p -d link show br0 | grep \"hello_time\"
                "hello_time": 300,

可以使用相同的基本方法来更改其他STP参数,如最大年龄、转发延迟、老化时间等 。

6. 关于linux网桥不转发LLDP帧

原因

IEEE为标准协议留出的范围,使用这些地址的包将被网桥过滤,而不会被转发.

IEEE 802.1D MAC Bridge Filtered MAC Group Addresses: 01-80-C2-00-00-00 to 01-80-C2-00-00-0F; MAC frames that have a destination MAC address within this range are not relayed by MAC bridges conforming to IEEE 802.1D.

IEEE协议中规定的预留的MAC地址表如下:

MAC address Protocol
01-80-C2-00-00-00 Spanning Tree (STP/RSPT/MSTP)
生成树(STP/RSPT/MSTP)
01-80-C2-00-00-01 Ethernet Flow Control (pause frames)
以太网流量控制(暂停帧)
01-80-C2-00-00-02 Link Aggregation Control Protocol (LACP)
链路聚合控制协议(LACP)
01-80-C2-00-00-03 802.1X Port-Based Network Access Control
802.1X基于端口的网络访问控制
01-80-C2-00-00-08 Provider Bridge protocols (STP)
供应商桥接协议(STP)
01-80-C2-00-00-0D Provider Bridge protocols (MVRP)
提供商桥接协议(MVRP)
01-80-C2-00-00-0E 802.1AB Link Layer Discovery Protocol (LLDP)
802.1AB链路层发现协议(LLDP)

解决

综上网桥不转发LLDP(链路层发现协议)帧,但从Linux内核2.6开始,允许通过在/sys/class/net/bridge-iface/bridge/group_fwd_mask中设置特定的位掩码来控制网桥应该转发IEEE 802.1D中定义的范围内的哪些链路本地帧。默认值0表示Linux网桥不转发任何链路本地帧.

将此值设置为16384将允许网桥转发LLDP帧(01-80-C2-00-00- 0E):

# 关闭网桥的 LLDP 过滤
echo 16384 > /sys/class/net/br0/bridge/group_fwd_mask

需要注意的是,在默认的发行版本中,对于该MAC地址范围中的前三个(-00,-01,-02)是不能通过以上方式控制的, 意味着在gns3的模拟环境中,我们仍然不能成功的测试STP,流控和LACP。要克服这个限制,必须要自己编译linux kernel才行,也可以下载EVE编译好的版本,点击进入链接。这样就可以随意调整group_fwd_mask的值,支持不过滤01-80-C2-00-00-0x的所有地址了.

前文中把group_fwd_mask设为16384,对应的MAC是01-80-C2-00-00-0E,对应的协议是LLDP, 那么group_fwd_mask是如何计算的呢?

位掩码是一个16位的数字,其中第一位(最低有效位)表示MAC地址01-80-C2-00 - 00-00,第16位(最高有效位)表示01-80-C2-00-00-0F。默认值(所有位均为0)不转发任何链路本地帧。要启用特定MAC地址的帧转发,我们需要将相应的位设置为1。例如,为了允许转发LLDP帧(01-80-C2-00-00- 0E),我们需要将第15位设置为1,并将其余位保留为0:

MAC 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
BIt 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0

这意味着我们使用二进制数0100 0000 0000 0000作为位掩码,它转换为十进制数16384,就像我们在前面的例子中使用的那样.

如果我们想将LACP(01-80-C2-00-00-02)和802.1X(01-80-C2-00-00-03)添加到混合中,我们还将第3位和第4位设置为1.

MAC 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
BIt 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0

bitmasks是二进制数0100 0000 0000 1100, 转换成10进制则为16396。这样就可以允许LLDP,LACP,802.1x协议了.

按照这样的方法,要解除linux网桥对规定地址范围内所有地址的过滤,就把所有的bit都置为1 即可.

持久化配置

在/etc/rc.local中添加:

#!/bin/bash

# 设置网桥 br0 的组转发掩码
echo 65 > /sys/class/net/br0/bridge/group_fwd_mask
exit 0

确保脚本具有可执行权限:

sudo chmod +x /etc/rc.local

或者使用systemd 创建或编辑一个系统服务单元文件,例如/etc/systemd/system/set-group-fwd-mask.service:

[Unit]
Description=Set group forward mask for bridge br0
After=network.target

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo 65 > /sys/class/net/br0/bridge/group_fwd_mask'
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

启用并启动该服务:

sudo systemctl enable set-group-fwd-mask.service
sudo systemctl start set-group-fwd-mask.service

参考链接 。

https://interestingtraffic.nl/2017/11/21/an-oddly-specific-post-about-group_fwd_mask/ 。

http://standards.ieee.org/develop/regauth/tut/macgrp.pdf 。

7. 网桥vlan

查看网桥vlan信息 。

bridge vlan show

要显式禁用网桥的VLAN 过滤功能,可以使用以下命令:

sudo ip link set dev br0 type bridge vlan_filtering 0

这将确保网桥br0不会处理VLAN标签 。

要显示VLAN流量状态,启用VLAN统计(在内核4.7中添加):

sudo ip link set br0 type bridge vlan_stats_enabled 1

前面的命令只在网桥上启用全局VLAN统计信息,并且没有细粒度地显示每个VLAN的状态。要在网桥中没有端口号时启用每个VLAN的统计信息,还需要启用vlan_stats_per_port(在内核4.20中添加) 。

sudo ip link set br0 type bridge vlan_stats_per_port 1

显示vlan统计信息 。

sudo bridge -s vlan show

配置持久化

为了在系统重启后保持配置,你需要将相应的命令添加到网络配置文件中.

在Debian/Ubuntu系统上编辑/etc/network/interfaces文件,添加如下内容:

auto br0
iface br0 inet static
    address 192.168.1.100
    netmask 255.255.255.0
    bridge_ports eth0 eth1
    post-up ip link set dev br0 type bridge vlan_filtering 0

8. 其他

1. 网卡混杂模式配置

#打开混杂模式
sudo ip link set eth0 promisc on

#关闭混杂模式
sudo ip link set eth0 promisc off

或者使用ifconfig 。

#打开混杂模式
sudo ifconfig eth0 promisc

#关闭混杂模式
sudo ifconfig eth0 -promisc

2. 网卡接收多播包配置

# 确认你要配置的网络接口名称
ip link show

#加入多播组
sudo ip maddr add 239.255.255.250 dev eth0

#使能网卡接收多播帧
sudo ifconfig eth0 allmulti
#或
sudo ip link set dev eth0 allmulticast on

#验证配置
ip maddr show dev eth0

3. 创建VLAN接口

启用802.1Q VLAN标签支持 。

sudo modprobe 8021q

为了使网卡能够接收所有VLAN包,你需要为每个VLAN创建虚拟接口。假设你需要接收VLAN ID为10和20的包.

sudo ip link add link eth0 name eth0.10 type vlan id 10
sudo ip link add link eth0 name eth0.20 type vlan id 20
sudo ip link set dev eth0.10 up
sudo ip link set dev eth0.20 up

或者使用 vconfig 命令创建VLAN接口(旧版命令) 。

sudo vconfig add eth0 10
sudo vconfig add eth0 20
sudo ifconfig eth0.10 up
sudo ifconfig eth0.20 up

你可以使用以下命令来验证VLAN接口是否已正确配置:

ip -d link show eth0.10
ip -d link show eth0.20

为了在系统重启后保持这些配置,你需要将相应的命令添加到系统启动脚本中.

在ubuntu上,编辑/etc/network/interfaces文件,添加如下内容:

auto eth0
iface eth0 inet static
    address 192.168.1.100
    netmask 255.255.255.0
    up ip link set eth0 promisc on

auto eth0.10
iface eth0.10 inet manual
    vlan-raw-device eth0

auto eth0.20
iface eth0.20 inet manual
    vlan-raw-device eth0

在CentOS/RHEL系统上:

创建或编辑/etc/sysconfig/network-scripts/ifcfg-eth0文件,确保包含以下内容:

DEVICE=eth0
BOOTPROTO=none
ONBOOT=yes
PROMISC=yes

创建或编辑VLAN接口配置文件,例如/etc/sysconfig/network-scripts/ifcfg-eth0.10和/etc/sysconfig/network-scripts/ifcfg-eth0.20:

# /etc/sysconfig/network-scripts/ifcfg-eth0.10
DEVICE=eth0.10
BOOTPROTO=none
ONBOOT=yes
VLAN=yes

# /etc/sysconfig/network-scripts/ifcfg-eth0.20
DEVICE=eth0.20
BOOTPROTO=none
ONBOOT=yes
VLAN=yes

重新启动网络服务以应用配置:

# 对于Debian/Ubuntu
sudo systemctl restart networking

# 对于CentOS/RHEL
sudo systemctl restart network

参考链接

https://developers.redhat.com/articles/2022/04/06/introduction-linux-bridging-commands-and-features#vlan_filter 。

https://interestingtraffic.nl/2017/11/21/an-oddly-specific-post-about-group_fwd_mask/ 。

http://standards.ieee.org/develop/regauth/tut/macgrp.pdf 。

https://wiki.libvirt.org/Net.bridge.bridge-nf-call_and_sysctl.conf.html 。

最后此篇关于关于linux网桥(LinuxBridge)的一些个人记录的文章就讲到这里了,如果你想了解更多关于关于linux网桥(LinuxBridge)的一些个人记录的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

57 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com