- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
作为一个工业自动化行业,常游走于各种 OT 网络和 IT 网络之间的人,linux 网桥是常使用的工具之一,每每涉及Linux 网桥, 这些记忆性的操作都要现查,零散且麻烦,所以简单整理一下,主要方便自己查询,同时分享给大家参考,希望对你有所帮助.
有了虚拟网卡,我们很自然就会联想到让网卡接入到交换机里,来实现多个容器间的相互连接。而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系统
创建网桥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
为了在系统重启后保持网桥配置,你需要将相应的配置添加到网络配置文件中.
编辑/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
创建或编辑/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
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.
使用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"
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参数,如最大年龄、转发延迟、老化时间等 。
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 。
查看网桥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
#打开混杂模式
sudo ip link set eth0 promisc on
#关闭混杂模式
sudo ip link set eth0 promisc off
或者使用ifconfig 。
#打开混杂模式
sudo ifconfig eth0 promisc
#关闭混杂模式
sudo ifconfig eth0 -promisc
# 确认你要配置的网络接口名称
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
启用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的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
目录 1. Linux Bridge简述 2. 网桥创建 创建 配置持久化 在Debian/Ubuntu系统上:
我是一名优秀的程序员,十分优秀!