Home -- Michael's Blog :: Just Do IT -- Manuals

24.2. 网关和路由

贡献者:Coranth Gryphon. 中文翻译: 张 雪平 和 袁 苏义.

为了让一台主机在网能找到另一台主机,就必须要有一种机制来描述如何从一台主机连至另一台上。这个就叫做路由选择(routing). 一个``路由''是一对预先定义的地址: ``目的地(destination)'' 和 ``网关(gateway)''. 这对地址表明如果你想要试着到达这个目的地(destination),那么就通过这个网关(gateway)进行通信。目的地有三种类型: 单个主机(individual hosts),子网(subnets)和``默认(default)''。如果没有其它路由应用,就使用``默认路由(default route)''。关于默认路由我们以后为讨论多一点。有三种类型的网关: 单个主机,接口(也叫``连接(links)'')和以太网硬件地址(MAC addresses)。

24.2.1. 实例

为了说明路由选择的各个部分,我们使用以用下面这个例子。以下是命令netstat的输出:

% netstat -r Routing tables

Destination      Gateway            Flags     Refs     Use     Netif Expire

default          outside-gw         UGSc       37      418      ppp0 localhost        localhost          UH          0      181       lo0 test0            0:e0:b5:36:cf:4f   UHLW        5    63288       ed0     77 10.20.30.255     link#1             UHLW        1     2421 example.com      link#1             UC          0        0 host1            0:e0:a8:37:8:1e    UHLW        3     4601       lo0 host2            0:e0:a8:37:8:1e    UHLW        0        5       lo0 => host2.example.com link#1             UC          0        0 224              link#1             UC          0        0

头两行指定默认路由(我们会在下一节说明) 和 本地(localhost)路由。

这张路由表里指定用于localhost的接口(Netif 列)是lo0,也就是众所周知的“回环设备(loopback device)”。这就使得所有以此为“目的地”的通信留在了内部,而不是通过LAN发送出去,因为它会在开始的地方就结束返回。

接着出现的是以0:e0:开头的地址。这些是以太网硬件地址,也称为MAC地址。 FreeBSD会自动识别在同一个以太网中的任何主机(如test0),并为这个主机新增一个路由,以并通过那个以太网接口——ed0直接到达它(译者注:那台主机)。与这类路由表相关的也有一个超时项(Expire列),当我们在指定时间内没有收到从那个主机发来的信息,这项就派上用场了。这种情况下,到这个主机的路由就会被自动删除。这些主机被使用一种叫做RIP(路由信息协议--Routing Information Protocol)的机制所识别,这种机制利用基于“最短路径选择(shortest path determination)”的办法计算出到本地主机的路由。

FreeBSD也会为本地子网添加子网路由(10.20.30.255是子网10.20.30的广播地址,而example.com是这个子网相联的域名)。名称link#1代表主机上的第一块以太网卡。你会发现,对于它们没有指定另外的接口。

这两个组(本地网络主机和本地子网)的路由是由守护进程routed自动配置的。如果它没有运行,那就只有被静态定义(例如,明确输入的)的路由才存在了。

host1行代表我们的主机,它通过以太网地址来识别。因为我们是发送端, FreeBSD知道使用回还接口(lo0)而不是通过以太网接口来进行发送。

两个host2是我们使用ifconfig(8)别名(请看关于以太网的那部分就会知道我们为什么这么做)时产生的一个实例。在lo0接口之后的=>符号表明我们不仅使用了回环(因为这个地址也涉及了本地主机),而且明确指出它是个别名。这类路由只有在支持别名的主机上才能显现出来。所有本地网上的其它的主机对于这类路由只会简单拥有link#1

最后一行(目标子网224)用于处理多播——它会覆盖到其它的区域。

最后,每个路由的不同属性可以在Flags列中看到。下边是个关于这些标志和它们的含义的一个简表:

U Up: 路由处于活动状态。
H Host: 路由目标是单个主机。
G Gateway: 所有发到目的地的网络传到这一远程系统上,并由它决定最后发到哪里。
S Static: 这个路由是手工配置的,不是由系统自动生成的。
C Clone: 生成一个新的路由,通过这个路由我们可以连接上这些机子。这种类型的路由通常用于本地网络。
W WasCloned: 指明一个路由——它是基于本地区域网络(克隆)路由自动配置的。
L Link: 路由涉及到了以太网硬件。

24.2.2. 默认路由

当本地系统需要与远程主机建立连接时,它会检查路由表以决定是否有已知的路径存在。如果远程主机属于一个我们已知如何到达(克隆的路由)的子网内,那么系统会检查看沿着那个接口是否能够连接。

如果所有已知路径都失败,系统还有最后一个选择: ``默认''路由。这个路由是特殊类型的网关路由(通常只有一个存在于系统里),并且总是在标志栏使用一个c来进行标识。对于本地区域网络里的主机,这个网关被设置到任何与外界有直接连接的机子里(无论是通过PPP连接,DSL,cable modem,T1或其它的网络接口)。

如果你正为某台本身就做为网关连接外界的机子配置默认路由的话,那么该默认路由应该是你的“互联网服务商(ISP)”那方的网关机子。

让我们来看一个关于默认路由的例子。这是个很普遍的配置:

主机Local1Local2 在你那边。 Local1通过PPP拨号连接到了ISP。这个PPP服务器通过一个局域网连接到另一台网关机子——它又通过一个外部接口连接到ISP提供的互联网上。

你的每一台机子的默认路由应该是:

Host Default Gateway Interface
Local2 Local1 Ethernet
Local1 T1-GW PPP

一个常见的问题是``我们为什么(或怎样)能T1-GW 设置成为Local1默认网关,而不是它所连接ISP服务器?''

记住,因为PPP接口使用的一个地址是在ISP的局域网里的,用于你那边的连接,对于ISP的局域网里的其它机子,其路由会自动产生。 因此,你就已经知道了如何到达机子T1-GW,那么也就没必要中那一步了——发送通信给ISP服务器。

通常使用地址X.X.X.1做为一个局域网的网关。因此(使用相同的例子),如果你本地的C类地址空间是10.20.30,而你的ISP使用的是10.9.9,那么默认路由表将是:

Host Default Route
Local2 (10.20.30.2) Local1 (10.20.30.1)
Local1 (10.20.30.1, 10.9.9.30) T1-GW (10.9.9.1)

你可以很轻易地通过/etc/rc.conf文件设定默认路由。在我们的实例里,在主机Local2里,我们在文件/etc/rc.conf里增加了下边内容:

defaultrouter="10.20.30.1"

也可以直接在命令行使用route(8)命令:

# route add default 10.20.30.1

想要了解更多关于手工处理网络路由表的信息,参考route(8)手册页。

24.2.3. 重宿主机(Dual Homed Hosts)

还有一种其它的类型的配置是我们要提及的,这就是一个主机处于两个不同的网络。技术上,任何做为网关(上边的实例中,使用了PPP连接)的机子就算作是重宿主机。但这个词实际上仅用来指那种处于两个局域网这中的机子。

有一种情形,一台机子有两个网卡,对于各个子网都有个自的一个地址。另一种情况,这台机子仅有一张网卡,但使用ifconfig(8)做了别名。如果有两个独立的以太网在使用的情形就使用前者,如果只有一个物理网段,但逻辑上分成了两个独立的子网,就使用后者。

每种情况都要设置路由表以便两子网都知道这台主机是到其它子网的网关——入站路由(inbound route) 。将一台主机配置成两个子网间的路由器,这种配置经常在我们需要实现单向或双向的包过滤或防火墙时被用到。

如果想让主机在两个接口间转发数据包,你需要激活FreBSD的这项功能。至于怎么做,请看下一部分了解更多。

24.2.4. 建立路由器

网络路由器只是一个将数据包从一个接口转发到另一个接口的系统。互联网标准和良好的工程实践阻止了FreeBSD计划在FreeBSD中把它置成默认地。你在可以在rc.conf(5)中改变下列变量的值为YES,使用这个功能生效:

gateway_enable=YES          # Set to YES if this host will be a gateway

这个选项会把sysctl(8) 变量——net.inet.ip.forwarding 设置成 1。如果你要临时地停止路由,你可以把它重为0

新的路由器需要有路由才知道将数据传向何处。如果网络够简单,你可以使用静态路由。FreeBSD也自带一个标准的BSD路由选择守护进程routed(8),称之为 RIP ( version 1和 version 2)和IRDP。对 BGP v4, OSPF v2和其它复杂路由选择协议的支持可以从net/zebra包中得到。 像GateD®一样的商业产品也提供了更复杂的网络路由解决方案。

即使FreeBSD按照这种方法进行了配置,它也并不完全符合Internet标准对路由器的要求。但对于一般应用已经足够了。

24.2.5. 设置静态路由

贡献者:Coranth Gryphon. 中文翻译: 张 雪平 和 袁 苏义.

24.2.5.1. 手动配置

假设如下这样一个网络:

在这里, RouterA 是我们的 FreeBSD 机子,它充当连接到互联网其它部分的路由器的角色。默认路由设置为10.0.0.1,它就允许与外界连接。我们假定已经正确配置了RouterB,并且知道如何连接到想去的任何地方。(在这个图里很简单。只须在RouterB上增加默认路由,使用192.168.1.1做为网关。)

如果我们查看一下RouterA的路由表,我们就会看到如下一些内容:

% netstat -nr
Routing tables

Internet:
Destination        Gateway            Flags    Refs      Use  Netif  Expire
default            10.0.0.1           UGS         0    49378    xl0
127.0.0.1          127.0.0.1          UH          0        6    lo0
10.0.0/24          link#1             UC          0        0    xl0
192.168.1/24       link#2             UC          0        0    xl1

使用当前的路由表, RouterA 是不能到达我们的内网——Internal Net 2的。它没有到192.168.2.0/24的路由。一种可以接受的方法是手工增加这条路由。以下的命令会把Internal Net 2 网络加入到RouterA的路由表中,使用192.168.1.2做为下一个跳跃:

# route add -net 192.168.2.0/24 192.168.1.2

现在RouterA 就可以到达192.168.2.0/24 网络上的任何主机了。

24.2.5.2. 永久的配置

上面的实例对于运行着的系统来说配置静态路由是相当不错了。只是,有一个问题——如果你重启你的FreeBSD机子,路由信息就会消失。处理附加的静态路由的方法是把它放到你的/etc/rc.conf文件里去。

# Add Internal Net 2 as a static route
static_routes="internalnet2"
route_internalnet2="-net 192.168.2.0/24 192.168.1.2"

配置变量static_routes是一串以空格格开的字符串。每一串表示一个路由名字。在上面的例子中我们中有一个串在static_routes里。 这个字符串中internalnet2。然后我们新增一个配置变量route_internalnet2,这里我们把所有传给 route(8)命令的参数拿了过来。在上面的实例中的我使用的命令是:

# route add -net 192.168.2.0/24 192.168.1.2

因此,我们需要的是 "-net 192.168.2.0/24 192.168.1.2"

前边已经说了,我们可以有不只一个字符串的static_routes里边。下面我们就建立多个静态路由。下面几行显示了一个为192.168.0.0/24192.168.1.0/24网络在一个假想的路由器上增加静态路由的例子:

static_routes="net1 net2" route_net1="-net 192.168.0.0/24 192.168.0.1" route_net2="-net 192.168.1.0/24 192.168.1.1"

24.2.6. 路由传播

我们已经讨论了如何定义通向外界的路由,但未谈及外界是如何找到我们的。

我们已经知道可以设置路由表,这样任何指向特定地址空间(在我们的例子中是一个C类子网)的数据都会被送往网络上特定的主机,然后由这台主机向地址空间内部转发数据。

当你得到一个分配给你的网络的地址空间时,ISP(网络服务商)会设置它们的路由表,这样指向你子网的数据就会通过PPP连接下传到你的网络。但是其它跨越国界的网络是如何知道将数据传给你的ISP的呢?

有一个系统(很像分布式DNS信息系统),它一直跟踪被分配的地址空间,并说明它们连接到互联网骨干(Internet backbone)的点。``骨干(Backbone)'' 指的是负责全世界和跨国的传输的主要干线。每一台骨干主机(backbone machine)有一份主要表集的拷贝,它将发送给特定网络的数据导向相应的骨干载体上(backbone carrier),从结点往下遍历服务提供商链,直到数据到达你的网络。

服务提供商的任务是向骨干网络广播他们就是到到达你的网点的连接结点(以及进入的路径)。这就是路由传播。

24.2.7. 问题解答

有时候,路由传播会有一个问题,一些网络无法与你连接。或许能帮你找出路由是在哪里中断的最有用的命令就是traceroute(8)了。当你无法与远程主机连接时,这个命令一样有用(例如 ping(8) 失败)。

traceroute(8)命令将以你想连接的主机的名字作为参数执行。不管是到达了目标,还是因为没有连接而终止,它都会显示所经过的所有网关主机。

想了解更多的信息,查看traceroute(8)的手册。

24.2.8. 多播路由

FreeBSD一开始就支持多播应用软件和多播路由选择。多播程序并不要求FreeBSD的任何特殊的配置,就可以工作得很好。多播路由需要支持被编译入内核:

options MROUTING

另外,多播路由守护进程——mrouted(8) 必须通过/etc/mrouted.conf配置来开启通道和DVMRP。更多关于多播路由配置的信息可以在mrouted(8)的手册里找到。

Michael's Blog :: Just Do IT -- manuals