FreeBSD 使用手册
上一页 | 第31章 　高级网络 | 下一页

# 31.5 桥接

原作 Andrew Thompson.

## 31.5.1 简介

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

网桥通过学习每个网络接口上的 MAC 层地址 (以太网地址) 工作。 只当数据包的源地址和目标地址处于不同的网络时， 网桥才进行转发。

在很多方面，网桥就像一个带有很少端口的以太网交换机。

## 31.5.2 适合桥接的情况

适合使用网桥的， 有许多种不同的情况。

### 31.5.2.1 使多个网络相互联通

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

### 31.5.2.2 过滤/数据整形防火墙

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

举例来说， 一家通过 DSL 或 ISDN 连接到 ISP 的小公司， 拥有 13 个 ISP 分配的全局 IP 地址和 10 台 PC。 在这种情况下， 由于划分子网的问题， 采用路由来实现防火墙会比较困难。

基于网桥的防火墙可以串接在 DSL/ISDN 路由器的后面， 而无需考虑 IP 编制的问题。

### 31.5.2.3 网络监视

网桥可以用于连接两个不同的网段， 并用于监视往返的以太网帧。 这可以通过在网桥接口上使用 bpf(4)/tcpdump(1)， 或通过将全部以太网帧复制到另一个网络接口 (span 口) 来实现。

### 31.5.2.4 2层 VPN

通过 IP 连接的网桥， 可以利用 EtherIP 隧道或基于 tap(4) 的解决方案， 如 OpenVPN 可以将两个以太网连接到一起。

### 31.5.2.5 2层 冗余

网络可以通过多条链路连接在一起， 并使用生成树协议 (Spanning Tree Protocol) 来阻止多余的通路。 为使以太网能够正确工作， 两个设备之间应该只有一条激活通路， 而生成树能够检测环路， 并将多余的链路置为阻断状态。 当激活通路断开时， 协议能够计算另外一棵树， 并重新激活阻断的通路， 以恢复到网络各点的连通性。

## 31.5.3 内核配置

这一节主要介绍 if_bridge(4) 网桥实现。 除此之外， 还有一个基于 netgraph 的网桥实现， 如欲了解进一步细节， 请参见联机手册 ng_bridge(4)。

网桥驱动是一个内核模块， 并会随使用 ifconfig(8) 创建网桥接口时自动加载。 您也可以将 `device if_bridge` 加入到内核配置文件中， 以便将其静态联编进内核。

包过滤可以通过使用了 pfil(9) 框架的任意一种防火墙软件包来完成。 这些防火墙可以以模块形式加载， 也可以静态联编进内核。

通过配合 altq(4) 和 dummynet(4)， 网桥也可以用于流量控制。

## 31.5.4 启用网桥

网桥是通过接口复制来创建的。 您可以使用 ifconfig(8) 来创建网桥接口， 如果内核不包括网桥驱动， 则它会自动将其载入。

    # 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

如此就建立了一个网桥接口， 并为其随机分配了以太网地址。 `maxaddr` 和 `timeout` 参数能够控制网桥在转发表中保存多少个 MAC 地址， 以及表项中主机的过期时间。 其他参数控制生成树的运转方式。

将成员网络接口加入网桥。 为了让网桥能够为所有网桥成员接口转发包， 网桥接口和所有成员接口都需要处于启用状态：

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

网桥现在会在 `fxp0` 和 `fxp1` 之间转发以太网帧。 等效的 `/etc/rc.conf` 配置如下， 如此配置将在系统启动时创建同样的网桥。

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

如果网桥主机需要 IP 地址， 则应将其绑在网桥设备本身， 而不是某个成员设备上。 这可以通过静态设置或 DHCP 来完成：

    # ifconfig bridge0 inet 192.168.0.1/24

除此之外， 也可以为网桥接口指定 IPv6 地址。

## 31.5.5 防火墙

当启用包过滤时， 通过网桥的包可以分别在进入的网络接口、 网桥接口和发出的网络接口上进行过滤。 这些阶段均可禁用。 当包的流向很重要时， 最好在成员接口而非网桥接口上配置防火墙。

网桥上可以进行许多配置以决定非 IP 及 ARP 包能否通过， 以及通过 IPFW 实现二层防火墙。 请参见 if_bridge(4) 联机手册以了解进一步的细节。

## 31.5.6 生成树

网桥驱动实现了快速生成树协议 (RSTP 或 802.1w)， 并与较早的生成树协议 (STP) 兼容。 生成树可以用来在网络拓扑中检测并消除环路。 RSTP 提供了比传统 STP 更快的生成树覆盖速度， 这种协议会在相邻的交换机之间交换信息， 以迅速进入转发状态， 而不会产生环路。

下表展示了支持的运行模式：

OS 版本 | STP 模式 | 默认模式
--- | --- | ---
FreeBSD 5.4──FreeBSD 6.2 | STP | STP
FreeBSD 6.3+ | RSTP 或 STP | STP
FreeBSD 7.0+ | RSTP 或 STP | RSTP

使用 `stp` 命令可以在成员接口上启用生成树。 对包含 `fxp0` 和 `fxp1` 的网桥， 可以用下列命令启用 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:4b:d4:50` 而优先级为 `32768`。 其中 `root id` 与生成树相同， 表示这是作为生成树根的网桥。

另一个网桥也启用了生成树：

    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

这里的 `root id 00:01:02:4b:d4:50 priority 32768 ifcost 400000 port 4` 表示根网桥是前面的 `00:01:02:4b:d4:50`， 而从此网桥出发的通路代价为 `400000`, 此通路到根网桥是通过 `port 4` 即 `fxp0` 连接的。

## 31.5.7 网桥的高级用法

### 31.5.7.1 重建流量流

网桥支持监视模式， 在 bpf(4) 处理之后会将包丢弃， 而不是继续处理或转发。 这可以用于将两个或多个接口上的输入转化为一个 bpf(4) 流。 在将两个独立的接口上的传输的 RX/TX 信号重整为一个时， 这会非常有用。

如果希望将四个网络接口上的输入转成一个流：

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

### 31.5.7.2 镜像口 (Span port)

网桥收到的每个以太网帧都可以发到镜像口上。 网桥上的镜像口数量没有限制， 如果一个接口已经被配置为镜像口， 则它就不能再作为网桥的成员口来使用。 这种用法主要是为与网桥镜像口相连的监听机配合使用。

如果希望将所有帧发到名为 `fxp4` 的接口上：

    # ifconfig bridge0 span fxp4

### 31.5.7.3 专用接口 (Private interface)

专用接口不会转发流量到除专用接口之外的其他端口。 这些流量会无条件地阻断， 因此包括 ARP 在内的以太网帧均不会被转发。 如果需要选择性地阻断流量， 则应使用防火墙。

### 31.5.7.4 自学习接口 (Sticky Interfaces)

如果网桥的成员接口标记为自学习， 则动态学习的地址项一旦进入转发快取缓存， 即被认为是静态项。 自学习项不会从快取缓存中过期或替换掉， 即使地址在另一接口上出现也是如此。 这使得不必事先发布转发表， 也能根据学习结果得到静态项的有点， 但在这些网段被网桥看到的客户机， 就不能漫游至另一网段了。

另一种用法是将网桥与 VLAN 功能连用， 这样客户网络会被隔离在一边， 而不会浪费 IP 地址空间。 考虑 `CustomerA` 在 `vlan100` 上， 而 `CustomerB` 则在 `vlan101` 上。 网桥地址为 `192.168.0.1`， 同时作为 internet 路由器使用。

    # 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` 地址空间， 而无需划分子网。

### 31.5.7.5 地址限制

接口后的源 MAC 地址数量是可以控制的。 一旦到达了限制未知源地址的包将会被丢弃， 直至现有缓存中的一项过期或被移除。

下面的例子是设置 `CustomerA` 在 `vlan100` 上可连接的以太网设备最大值为 10。

    # ifconfig bridge0 ifmaxaddr vlan100 10

### 31.5.7.6 SNMP 管理

网桥接口和 STP 参数能够由 FreeBSD 基本系统的 SNMP 守护进程进行管理。导出的网桥 MIB 符和 IETF 标准， 所以任何 SNMP 客户端或管理包都可以被用来接收数据。

在网桥机器上从`/etc/snmp.config` 文件中去掉以下这行的注释 `begemotSnmpdModulePath."bridge" = "/usr/lib/snmp_bridge.so"` 并启动 bsnmpd 守护进程。 其他的配置选项诸如 community names 和 access lists 可能也许也需要修改。 参阅 bsnmpd(1) 和 snmp_bridge(3) 获取更多信息。

以下的例子中使用了 Net-SNMP 软件 (`net-mgmt/net-snmp`) 来查询一个网桥，当然同样也能够使用port `net-mgmt/bsnmptools`。 在 SNMP 客户端 Net-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 网桥拓扑改变了2次，拓扑的改变表示1个或多个 网络中的连接改变或失效并且有一个新树生成。 `dot1dStpTimeSinceTopologyChange.0` 的值则能够显示这是何时改变的。

监测多个网桥接口可以使用 private 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>.