31.6. 桥接

Written by Andrew Thompson.

有时, 会有需要将一个物理网络分成两个独立的网段, 而不是创建新的 IP 子网, 并将其通过路由器相连。 以这种方式连接两个网络的设备称为 网桥 (bridge)。 有两个网络接口的 FreeBSD 系统可以作为网桥来使用。

网桥通过学习每个网络接口上的 MAC 地址 (以太网地址) 工作。 只当数据包的源地址和目标 MAC 地址处于不同的网络时, 网桥才进行转发。在很多方面,网桥就像一个带有很少端口的以太网交换机。具有多个网络接口的 FreeBSD 系统可以配置为充当网桥。

在以下情况下,桥接非常有用:

连接网络

网桥的基本操作是将两个或多个网段连接在一起。 由于各式各样的原因, 人们会希望使用一台真正的计算机, 而不是网络设备来充任网桥的角色, 常见的原因包括线缆的限制、 需要进行防火墙, 或为虚拟机网络接口连接虚拟网络。 网桥也可以将无线网卡以 hostap 模式接入有线网络。

过滤/数据整形防火墙

使用防火墙的常见情形是无需进行路由或网络地址转换的情况 (NAT)。

一个例子是一个小公司通过DSLISDN连接到ISPISP有十三个公共IP地址,网络上有十台电脑。在这种情况下,由于子网问题,使用基于路由器的防火墙是很困难的。基于网桥的防火墙可以在没有任何IP寻址问题的情况下配置。

Network Tap (网络分流器)

网桥可以连接两个网段,以便使用bpf(4)tcpdump(1)在网桥接口上或通过将所有帧的副本发送出一个称为跨端口(span port)的附加接口。

二层VPN

两个以太网网络可以通过将网桥接到 EtherIP 隧道或基于tap(4)的解决方案,如OpenVPN,通过IP链路连接两个以太网网络。

二层冗余(Layer 2 Redundancy)

一个网络可以用多个链路连接在一起,使用生成树协议(STP)来阻断冗余路径。

本节将介绍如何使用 if_bridge(4) 将 FreeBSD 系统配置为网桥。FreeBSD 还提供了 netgraph 桥接驱动程序, 并在 ng_bridge(4)中介绍详细信息。

注意:

包过滤可以与任何 hook 到pfil(9)框架的防火墙包一起使用。该网桥可以用altq(4)dummynet(4)作为流量整形器使用。

31.6.1. 开启桥接

在 FreeBSD 中, if_bridge(4) 是一个内核模块, 当创建桥接接口时, ifconfig(8)会自动加载。也可以通过在自定义内核配置文件中加入device if_bridge来为内核添加桥接功能。

网桥使用端口克隆创建。使用以下命令创建网桥:

# ifconfig bridge create
bridge0
# ifconfig bridge0
bridge0: flags=8802<BROADCAST,SIMPLEX,MULTICAST> metric 0 mtu 1500
        ether 96:3d:4b:f1:79:7a
        id 00:00:00:00:00:00 priority 32768 hellotime 2 fwddelay 15
        maxage 20 holdcnt 6 proto rstp maxaddr 100 timeout 1200
        root id 00:00:00:00:00:00 priority 0 ifcost 0 port 0

创建网桥接口时,会自动分配一个随机生成的以太网地址。maxaddrtimeout参数控制网桥将在转发表中保留多少个MAC地址,以及每个条目在最后一次被看到后多少秒后才会被删除。其他参数用于控制STP行为。

接下来,指定要添加为网桥成员的网络接口。为了使网桥转发数据包,所有成员接口和网桥都必须处于启用状态:

# ifconfig bridge0 addm fxp0 addm fxp1 up
# ifconfig fxp0 up
# ifconfig fxp1 up

该网桥现在可以在fxp0fxp1之间转发以太网帧。将以下行添加到/etc/rc.conf,以便在启动时创建网桥:

cloned_interfaces="bridge0"
ifconfig_bridge0="addm fxp0 addm fxp1 up"
ifconfig_fxp0="up"
ifconfig_fxp1="up"

如果网桥主机需要IP地址,则将其设置在网桥接口上,而不是在成员接口上。该地址可以手工设置或通过DHCP分配。此示例将设置静态IP地址:

# ifconfig bridge0 inet 192.168.0.1/24

也可以将IPv6地址分配给网桥接口。要使更改持久化,请将地址信息添加到/etc/rc.conf中。

注意:

当启用数据包过滤功能时,桥接数据包将在桥接接口上的发端接口上的入站数据包通过过滤器,在适当的接口上的出站数据包通过过滤器。这两个阶段都可以禁用。当数据包流的方向很重要时,最好在成员接口上启用防火墙,而不是网桥本身。

该网桥有几个可配置选项,用于传递非IPIP数据包,以及使用ipfw(8)二层防火墙。详细信息请参阅 if_bridge(4)

31.6.2. 开启Spanning Tree

为了使以太网网络正常运行,两个设备之间只能存在一条活动路径。STP协议会检测到环路,并将冗余链路置入阻塞状态。如果其中一条活动链路失效,STP会计算出不同的树,并使被阻塞的路径之一恢复到网络中所有点的连接。

快速生成树协议(RSTP 或 802.1w)兼容传统的STP协议。RSTP 提供了更快的收敛速度, 并与相邻交换机交换信息, 为了在不创建环路的情况下快速过渡到转发模式。FreeBSD 支持 RSTPSTP 作为工作模式, 其中 RSTP 是默认模式。

可以使用ifconfig(8)在成员接口上启用STP。对于当前接口为fxp0fxp1的网桥,使用以下命令启用STP

# ifconfig bridge0 stp fxp0 stp fxp1
bridge0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        ether d6:cf:d5:a0:94:6d
        id 00:01:02:4b:d4:50 priority 32768 hellotime 2 fwddelay 15
        maxage 20 holdcnt 6 proto rstp maxaddr 100 timeout 1200
        root id 00:01:02:4b:d4:50 priority 32768 ifcost 0 port 0
        member: fxp0 flags=1c7<LEARNING,DISCOVER,STP,AUTOEDGE,PTP,AUTOPTP>
                port 3 priority 128 path cost 200000 proto rstp
                role designated state forwarding
        member: fxp1 flags=1c7<LEARNING,DISCOVER,STP,AUTOEDGE,PTP,AUTOPTP>
                port 4 priority 128 path cost 200000 proto rstp
                role designated state forwarding

这个桥接的生成树ID为00:01:02:02:4B:D4:50,优先级为32768。由于root id是相同的,这表明这是该树的根桥。

网络上的另一个网桥也启用了 STP

bridge0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        ether 96:3d:4b:f1:79:7a
        id 00:13:d4:9a:06:7a priority 32768 hellotime 2 fwddelay 15
        maxage 20 holdcnt 6 proto rstp maxaddr 100 timeout 1200
        root id 00:01:02:4b:d4:50 priority 32768 ifcost 400000 port 4
        member: fxp0 flags=1c7<LEARNING,DISCOVER,STP,AUTOEDGE,PTP,AUTOPTP>
                port 4 priority 128 path cost 200000 proto rstp
                role root state forwarding
        member: fxp1 flags=1c7<LEARNING,DISCOVER,STP,AUTOEDGE,PTP,AUTOPTP>
                port 5 priority 128 path cost 200000 proto rstp
                role designated state forwarding

The line root id 00:01:02:4b:d4:50 priority 32768 ifcost 400000 port 4显示根网桥是00:01:02:4B:D4:50,从这个网桥的路径费用为400000。到 root 网桥的路径是通过port 4,它是fxp0

31.6.3. 桥接界面参数

有几个ifconfig参数是网桥接口所特有的。本节总结了这些参数的一些常用用途。可用参数的完整列表在 ifconfig(8)中描述。

private

私有接口不会转发流量到其他私有接口。流量被无条件阻止,因此不会转发任何以太网帧,包括ARP数据包。如果需要选择性地阻止流量,应使用防火墙。

span

跨接端口传输网桥接收到的每一个以太网帧的副本。网桥上配置的跨接端口的数量是无限的,但如果一个接口被指定为跨接端口,则不能同时作为普通网桥端口使用。这对于被动地窥探桥接网络中连接到桥接端口之一的另一台主机上的桥接主机是最有用的。例如,将所有帧的副本发送到名为fxp4的接口:

# ifconfig bridge0 span fxp4
sticky

如果网桥成员接口被标记为 "粘性(sticky)",则动态学习的地址条目将被视为转发缓存中的静态条目。即使在不同的接口上看到该地址,粘性条目也不会从缓存中老化或被替换。这就带来了静态地址项的好处,而不需要预先填充转发表。在网桥的某个网段上学习的客户端不能漫游到另一个网段。

使用粘性地址的一个例子是将网桥与VLAN结合在一起,以便在不浪费IP地址空间的情况下隔离客户网络。考虑CustomerAvlan100上,CustomerBvlan101上,而网桥的地址是192.168.0.1

# ifconfig bridge0 addm vlan100 sticky vlan100 addm vlan101 sticky vlan101
# ifconfig bridge0 inet 192.168.0.1/24

在这个例子中,两个客户机都将192.168.0.1视为默认网关。由于网桥缓存是粘性的,因此一台主机不能欺骗另一台客户的MAC地址来拦截他们的流量。

可以使用防火墙阻止VLAN之间的任何通信,或者如本示例所示,可以阻止专用接口:

# ifconfig bridge0 private vlan100 private vlan101

客户之间是完全隔离的,可以在没有子网的情况下分配完整的/24地址范围。

可以限制接口后面的唯一源MAC地址的数量。一旦达到限制,具有未知源地址的数据包将被丢弃,直到现有的主机缓存条目过期或被删除。

下面的示例将CustomerAvlan100上的最大以太网设备数量设置为10:

# ifconfig bridge0 ifmaxaddr vlan100 10

网桥接口还支持监控模式,即在bpf(4)处理后,数据包被丢弃,不再处理或转发。这可用于将两个或多个接口的输入复用到一个bpf(4)流中。这对于通过两个独立的接口将RX/TX信号传输出去的网络分路器的流量重构非常有用。例如,将四个网络接口的输入作为一个流读取:

# ifconfig bridge0 addm fxp0 addm fxp1 addm fxp2 addm fxp3 monitor up
# tcpdump -i bridge0

31.6.4. SNMP监视

网桥接口和 STP 参数可以通过 FreeBSD 基本系统中包含的 bsnmpd(1) 来监控。导出的桥接 MIB符合 IETF 标准, 因此任何 SNMP 客户端或监控包都可以用来检索数据。

要在网桥上启用监控,请删除/etc/snmpd.config中以#开头的行来取消对这该行注释:

begemotSnmpdModulePath."bridge" = "/usr/lib/snmp_bridge.so"

此文件中的其他设置,如社区名称和访问列表等,可能需要修改。请参阅bsnmpd(1)snmp_bridge(3)以了解更多信息。完成修改后,在 /etc/rc.conf中添加这一行:

bsnmpd_enable="YES"

然后启动 bsnmpd(1)

# service bsnmpd start

以下示例使用Net-SNMP软件(netmgmt/net-snmp)从客户端系统查询网桥。也可以使用net-mgmt/bsnmptools。在Net-SNMP运行的 SNMP客户端中,将以下行添加到$HOME/.snmp/snmp.conf以导入网桥MIB定义:

mibdirs +/usr/share/snmp/mibs
mibs +BRIDGE-MIB:RSTP-MIB:BEGEMOT-MIB:BEGEMOT-BRIDGE-MIB

使用 IETF BRIDGE-MIB (RFC4188) 监视网桥:

% snmpwalk -v 2c -c public bridge1.example.com mib-2.dot1dBridge
BRIDGE-MIB::dot1dBaseBridgeAddress.0 = STRING: 66:fb:9b:6e:5c:44
BRIDGE-MIB::dot1dBaseNumPorts.0 = INTEGER: 1 ports
BRIDGE-MIB::dot1dStpTimeSinceTopologyChange.0 = Timeticks: (189959) 0:31:39.59 centi-seconds
BRIDGE-MIB::dot1dStpTopChanges.0 = Counter32: 2
BRIDGE-MIB::dot1dStpDesignatedRoot.0 = Hex-STRING: 80 00 00 01 02 4B D4 50
...
BRIDGE-MIB::dot1dStpPortState.3 = INTEGER: forwarding(5)
BRIDGE-MIB::dot1dStpPortEnable.3 = INTEGER: enabled(1)
BRIDGE-MIB::dot1dStpPortPathCost.3 = INTEGER: 200000
BRIDGE-MIB::dot1dStpPortDesignatedRoot.3 = Hex-STRING: 80 00 00 01 02 4B D4 50
BRIDGE-MIB::dot1dStpPortDesignatedCost.3 = INTEGER: 0
BRIDGE-MIB::dot1dStpPortDesignatedBridge.3 = Hex-STRING: 80 00 00 01 02 4B D4 50
BRIDGE-MIB::dot1dStpPortDesignatedPort.3 = Hex-STRING: 03 80
BRIDGE-MIB::dot1dStpPortForwardTransitions.3 = Counter32: 1
RSTP-MIB::dot1dStpVersion.0 = INTEGER: rstp(2)

dot1dStpTopChanges.0 值为2,表示STP网桥拓扑改变了两次。拓扑结构改变意味着网络中的一个或多个链接发生了变化,并计算出了新的树。dot1dStpTimeSinceTopologyChange.0的值代表发生的时间。

要监视多个网桥接口,可以使用专用 BEGEMOT-BRIDGE-MIB:

% snmpwalk -v 2c -c public bridge1.example.com
enterprises.fokus.begemot.begemotBridge
BEGEMOT-BRIDGE-MIB::begemotBridgeBaseName."bridge0" = STRING: bridge0
BEGEMOT-BRIDGE-MIB::begemotBridgeBaseName."bridge2" = STRING: bridge2
BEGEMOT-BRIDGE-MIB::begemotBridgeBaseAddress."bridge0" = STRING: e:ce:3b:5a:9e:13
BEGEMOT-BRIDGE-MIB::begemotBridgeBaseAddress."bridge2" = STRING: 12:5e:4d:74:d:fc
BEGEMOT-BRIDGE-MIB::begemotBridgeBaseNumPorts."bridge0" = INTEGER: 1
BEGEMOT-BRIDGE-MIB::begemotBridgeBaseNumPorts."bridge2" = INTEGER: 1
...
BEGEMOT-BRIDGE-MIB::begemotBridgeStpTimeSinceTopologyChange."bridge0" = Timeticks: (116927) 0:19:29.27 centi-seconds
BEGEMOT-BRIDGE-MIB::begemotBridgeStpTimeSinceTopologyChange."bridge2" = Timeticks: (82773) 0:13:47.73 centi-seconds
BEGEMOT-BRIDGE-MIB::begemotBridgeStpTopChanges."bridge0" = Counter32: 1
BEGEMOT-BRIDGE-MIB::begemotBridgeStpTopChanges."bridge2" = Counter32: 1
BEGEMOT-BRIDGE-MIB::begemotBridgeStpDesignatedRoot."bridge0" = Hex-STRING: 80 00 00 40 95 30 5E 31
BEGEMOT-BRIDGE-MIB::begemotBridgeStpDesignatedRoot."bridge2" = Hex-STRING: 80 00 00 50 8B B8 C6 A9

修改通过mib-2.dot1dBridge子树监视的桥接接口:

% snmpset -v 2c -c private bridge1.example.com
BEGEMOT-BRIDGE-MIB::begemotBridgeDefaultBridgeIf.0 s bridge2

本文档和其它文档可从这里下载: ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

如果对于FreeBSD有问题,请先阅读 文档,如不能解决再联系 <questions@FreeBSD.org>.

关于本文档的问题请发信联系 <doc@FreeBSD.org>.