Kernel Korner - Linux 作为以太网桥接器

作者:Jim Robinson

您是否曾被要求保护一个您没有管理权限的路由器?当您在一个不属于您的网络上,但又想保护您正在使用的网段时,该怎么办?一个类似于这样的请求将我带入了 Bridge 的奇妙世界,即 Linux 以太网桥接项目。

根据 Bridge 网站的说法

以太网桥接是一种将网络连接在一起以形成更大网络的方式。桥接的标准是 ANSI/IEEE 802.1d。桥接器是一种以协议无关的方式将两个独立的网段连接在一起的方法。数据包根据以太网地址而不是 IP 地址(如路由器)转发。由于转发是在第 2 层完成的,因此所有协议都可以透明地通过桥接器。

该代码目前由 Stephen Hemminger 为 Linux 2.4 和 2.6 内核维护。大多数使用 2.6 系列内核的现代发行版都内置了桥接代码。就本文而言,我们使用的是 Fedora Core 3,它构建在 2.6 内核之上。如果您仍然使用 2.4 内核,请不要绝望。Bridge 网站(请参阅在线资源)上提供了内核补丁,因此您也可以尝试。

桥接防火墙的防火墙组件是通过使用另一个相关的项目 ebtables 实现的。ebtables 程序是桥接防火墙的过滤层。该过滤连接到链路层以太网帧字段。除了过滤之外,您还可以操作以太网 MAC 地址。ebtables 代码还允许 iptables 规则在桥接模式下运行,为您提供 IP 和 MAC 级别的防火墙过滤器。

什么是桥接器?

桥接器是一种连接两个或多个使用相同网络技术的网段的设备。拓扑结构可能不同,因此您可以从光纤到铜缆,但技术必须保持相同。在其最简单的形式中,可以将其视为 Linux 集线器。根据需要向该框添加任意数量的端口,它们都将成为单个集线器设备的一部分。进入一个端口的内容将输出到集线器结构中的所有其他端口,除非您在规则中另有说明。一旦您的集线器启动,您就可以像使用任何其他 Linux 转发系统一样使用 iptables 和 ebtables 过滤流量。

入门

我们首先尝试在简单的双网卡机器之间实现连接。完成时,此 Linux 机器应充当标准集线器,根据需要将流量从一个端口传递到另一个端口。当我们将一个网卡插入到我们的常规网络插孔,并将笔记本电脑插入到第二个网卡时,我们将能够像直接连接一样从笔记本电脑使用网络。

Kernel Korner - Linux as an Ethernet Bridge

图 1. 在这个简单的网络中,Linux 系统充当以太网集线器,传递所有流量。

我们希望此桥接器对插入其中的任何设备都是透明的。有趣的是,除了远程连接到桥接器以维护和检查日志的能力之外,没有要求为桥接器分配 IP 地址。当然,在当今互联的世界中,分配 IP 地址是有意义的,我们在此处这样做。

我从一个旧的盒子开始,它一直在等待这样的项目。它是一台 AMD K6-450,配备 256MB 内存。它有一个 15GB IDE 硬盘和一个 3Com 10/100MB 以太网卡。我还有一个备用的 3Com 10/100MB 以太网卡,它可以与 Linux 良好配合,因此将其添加为第二个接口。我将仅运行桥接软件、一些简单的防火墙规则,也许还有 Snort 用于入侵检测。流量不大,我预计 Snort 数据量不会很大,因此 256MB 内存应该足够了。如果您要传递千兆位流量并想要实时嗅探,请大幅提高机器的规格。

现在安装 Fedora Core 3,选择您认为需要的附加组件。如果您在高度安全的环境中工作,我建议将您的软件选项保持在最低限度。如果您忘记了什么,可以随时使用 YUM 稍后获取附加组件。现在,只需获得一个正常运行的 Linux 安装,并确保它找到您的网卡。您需要内核源代码和常用的编译实用程序来制作 ebtables 代码,因此请添加这些。请记住保持安全,并在将设备投入生产后删除您不需要的任何软件。安装完成后,重新启动并以 root 用户身份登录。

现在您已准备好创建虚拟网络设备。您可以随意命名它;我选择了 br0——第一个桥接设备

#> brctl addbr br0

运行ifconfig。您是否看到您的网络接口(列表 1)?

列表 1. 在配置网络之前,检查两个以太网接口是否都已启动。

#> ifconfig

eth0      Link encap:Ethernet  HWaddr 00:CC:D0:99:EB:26
          inet6 addr: fe80::2b0:d0ff:fe99:eb26/64 Scope:Link
          UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1500  Metric:1
          RX packets:86208855 errors:0 dropped:0 overruns:63 frame:0
          TX packets:77098217 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:3871506445 (3692.1 Mb)  TX bytes:266311184 (253.9 Mb)
          Interrupt:5 Base address:0xec00

eth1      Link encap:Ethernet  HWaddr 00:CC:03:D8:3A:1A
          inet6 addr: fe80::201:3ff:fed8:3a1a/64 Scope:Link
          UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1500  Metric:1
          RX packets:77087614 errors:0 dropped:0 overruns:0 frame:0
          TX packets:85110321 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:264995582 (252.7 Mb)  TX bytes:3672580334 (3502.4 Mb)
          Interrupt:9 Base address:0xec80

在列表 1 中,您可以看到我们有两张网卡,但没有绑定到它们的 IP 地址。如果您的接口已分配 IP 地址,请删除它们以简化操作。在 Fedora 上,编辑文件 /etc/sysconfig/networking-scripts/ifcfg-X,其中 X 是网卡标识符。在我的系统上,这两个接口是 eth0 和 eth1。删除或注释掉与 IP 地址相关的行。重要的是确保网卡在启动时处于开启状态。列表 2 显示了一个基本配置,应该可以工作。完成上述操作后,不要忘记重新初始化网络,使用service network reload.

列表 2. 两个简单的网络卡配置文件,没有 IP 地址

/etc/sysconfig/networking-scripts/ifcfg-eth0:

DEVICE=eth0
ONBOOT=yes
BOOTPROTO=static


/etc/sysconfig/networking-scripts/ifcfg-eth1:

DEVICE=eth1
ONBOOT=yes
BOOTPROTO=static

接下来,告诉系统哪些设备属于此组,如下所示。另外,给出实际初始化虚拟设备的命令,如最后一行所示

#> brctl addif br0 eth0
#> brctl addif br0 eth1
#> ip link set br0 up

在其最基本的形式中,您的 Linux 盒子现在充当集线器。对于热衷者,您可以插入以太网适配器并开始玩耍。然而,该盒子本身目前正在盲目地传递流量,并且没有分配 IP 地址。我希望能够在安装设备后远程连接到我的设备,因此我将在虚拟设备 br0 中添加 IP 地址和一些路由信息。

要向桥接接口添加 IP 地址,请发出

#> ip addr add 10.1.1.18/16 brd + dev br0

我必须同时声明子网掩码 (/16) 和应该分配给哪个桥接设备。如果您的机器上有多个虚拟设备,这一点变得很重要。我只有一个,但语法要求这样做。如果您将桥接设备命名为其他名称,则需要在此处明确声明。

在您可以远程使用桥接器之前,要做的最后一件事是配置路由

#> route add default gw 10.1.1.1 dev br0

通常的路由规则和命令适用,并且对于所有意图和目的,您可以像使用任何其他 Linux 网络接口一样使用该设备 (br0)。

测试

现在我们已经完成了一切,让我们测试一下。首先,让我们确认我们所有的配置都已生效

#> brctl show
bridge name  bridge id          STP enabled  interfaces
br0          8000.0030843e5aa2  no           eth0
                                             eth1

如上所示,我们有一个名为 br0 的桥接设备,它使用接口 eth0 和 eth1。这证实我们应该可以正常工作了。

安装

现在是进行物理设置的时候了。像往常一样将一个网卡连接到您的网络交换机,就像对待任何其他计算机一样。您应该看到链路两端的指示灯都亮起。使用交叉电缆将台式机或笔记本电脑连接到 Linux 盒子上的另一个接口。等待链路指示灯亮起,数到十,然后从您的台式机或笔记本电脑 ping 网络上的另一个节点。您应该能够像直接连接一样使用 Linux 集线器另一侧的网络。

重启后仍然有效

如何设置您的安装以在重启后仍然有效是您的选择。一种简单的方法是将我们使用过的所有命令添加到 /etc/rc.local,它在启动结束时处理。将上面使用的命令输入到此文件中,您的桥接器在启动后即可正常工作。

防火墙

与任何传递或转发流量的 Linux 安装一样,您可以过滤信息流。桥接防火墙也没有什么不同。创建和维护防火墙配置的方法有很多。下面,我将解释如何使用最基本的防火墙类型:拒绝所有,允许部分。我们希望拒绝所有通过此防火墙的内容,除非我们明确声明允许某些内容。

此防火墙配置要求您从 ebtables 网站(请参阅资源)下载并安装 ebtables 用户空间工具。在撰写本文时,最新版本是 v2.0.6。从众多镜像之一获取副本。执行通常的解压和安装步骤,无需初始配置步骤

#> tar -xzf ebtables-v2.0.6.tar.gz
#> cd ebtables-v2.0.6
#> make
#> install

如果一切顺利,您应该可以在指尖使用 ebtables 命令集。通过输入ebtables在提示符下;您应该看到类似于以下内容

#> ebtables -V
ebtables v2.0.6 (November 2003)

让我们首先确保 iptables 设置为接受。记住我们使用的是 Fedora Core 3,所以我们可以简单地告诉服务退出,这会产生相同的效果

#> service iptables stop
#> chkconfig --level 35 iptables off

您可以通过发出 flush 命令来执行类似的操作。列出您的可用链,然后依次刷新每个链

#> iptables -L
#> iptables -F INPUT
#> iptables -F OUTPUT
#> iptables -F FORWARD
#> iptables -F RH-Firewall-1-INPUT

现在我们要阻止我们网络所有区域的所有流量通过防火墙。以下规则特定于我们在本示例中使用的网络;您需要修改子网或主机以反映您的具体要求

/sbin/ebtables -A FORWARD -p IPv4 \
--ip-source 10.2.0.0/16 -j DROP
/sbin/ebtables -A FORWARD -p IPv4 \
--ip-source 10.7.0.0/16 -j DROP
/sbin/ebtables -A FORWARD -p IPv4 \
--ip-source 10.4.0.0/16 -j DROP
/sbin/ebtables -A FORWARD -p IPv4 \
--ip-source 10.5.0.0/16 -j DROP
/sbin/ebtables -A FORWARD -p IPv4 \
--ip-source 10.6.0.0/16 -j DROP
/sbin/ebtables -A FORWARD -p IPv4 \
--ip-source 10.1.0.0/16 -j DROP

那些熟悉 iptables 的人应该注意到上面的语法是相似的。我们告诉 ebtables 程序,当使用 IPv4 协议进行转发时,丢弃来自 10.1.0.0/16 子网的任何数据包。然后,我们告诉它对其余子网重复此操作。

下一步是允许防火墙本身后面的设备。如果您不允许其 IP 地址通过,则任何内容都无法工作。此外,如果您为防火墙本身分配了 IP 地址,请不要忘记也允许它

/sbin/ebtables -I FORWARD 1 -p IPv4 \
--ip-source 10.1.1.5 -j ACCEPT
/sbin/ebtables -I FORWARD 1 -p IPv4 \
--ip-source 10.1.1.18 -j ACCEPT

在这里,我添加了我的网络上允许访问我的笔记本电脑的设备

/sbin/ebtables -I FORWARD 1 -p IPv4 \
--ip-source 10.1.10.30 -j ACCEPT
/sbin/ebtables -I FORWARD 1 -p IPv4 \
--ip-source 10.1.10.19 -j ACCEPT
/sbin/ebtables -I FORWARD 1 -p IPv4 \
--ip-source 10.1.10.87 -j ACCEPT

为了测试这一点,我只需转到上面 ACCEPT 规则中列出的机器,看看我是否可以 ping 我的笔记本电脑 10.1.1.5。现在移动到上面未列出的节点——您无法 ping 通!

实际应用

最近,我被叫到客户现场以保护一台金融服务器。要求很简单:我们需要在这台系统前面安装防火墙,但我们无法更改其 IP 地址。借助两个网卡和一个 Linux 操作系统,我能够在几分钟内启动并运行一个可用的防火墙。安装也很轻松。我只是使用交叉电缆将防火墙连接到服务器,并使用普通电缆将防火墙上的另一个网卡连接到网络插孔。就是这样。无需重新设计现有 IP 方案的任何部分;它真正实现了即插即用。一旦设置了一些规则来丢弃所有数据包,除非它们来自列为可接受的 IP 地址和端口,该项目就完成了。

Linux 最美妙的方面之一是它能够在单个系统上运行许多服务。以上面的例子为例。我快速地为一台敏感服务器设置了防火墙,但这并不是项目的结束。利用使用 Linux 节省的所有额外时间和金钱,我们能够在防火墙上加载 Snort。通过对嗅探器的配置文件进行快速修改——在我们的例子中是 /etc/snort.conf——我们告诉 Snort 监听接口 br0,snort 立即开始在桥接接口上工作。

这就是桥接代码的真正威力所在。是否曾经遇到网络段运行缓慢但您不知道原因?下次,加载一个装有 Snort 和您喜欢的任何其他侦查软件的 Linux 盒子,并启动并运行桥接器。找到您可靠的交叉电缆,然后前往现场。由于桥接器充当集线器,因此您可以简单地将 Linux 盒子插入网络中的任何点。只要您有物理连接,就可以将盒子插入并开始在几秒钟内进行实时嗅探。我们一直在进行的最新项目包括透明的 Squid 缓存服务器,这些服务器是真正透明的,无需对 IP 方案、客户端或浏览器进行任何重新配置。只需将 Squid 盒子插入路由器前面,并将所有端口 80 流量重定向到盒子本身,您就完成了。

Linux 透明地滑入现有网络基础设施的能力开启了一个全新的、改进的服务世界,企鹅可以提供这些服务。凭借将不同的网络设备放入一个虚拟实体的能力,您可以使用单个设备来防火墙和监视网络的任何方面。您唯一的限制是硬件的速度及其可用插槽的数量。

致谢

作者向编写 Bridging 代码的人员以及 ebtables 命令集的作者致以敬意,感谢他们制作了稳定、可用的工具并根据 GPL 发布它们。

本文资源: /article/8261

Jim Robinson 是 Linux Solutions Provider, Inc. 的总裁,该公司是一家总部位于佐治亚州梅肯市的咨询公司。他喜欢做丈夫和父亲,弹吉他,当然还有使用 Linux。

加载 Disqus 评论