大部份的 Linux 发行厂商 ﹐以及多数 UNIX 系统﹐目前均沿用历史悠久的 'arp'﹑'ifconfig'﹑和 'route' 等命令。虽说这些工具都仍能使用﹐然而在 Linux 2.2 及以后的版本中﹐他们却会导致一些非预期的效果。例如﹐目前 GRE tunnel 已成路由中的密不可分的一部份﹐但却需要完全不一样的工具才做得到。
用 iproute2 的话﹐其自身的工具组里面就包含了 tunnels 了。
Linux 2.2 及以后的核心内含一个完全重新设计的网路子系统。此一全新的网路程序码(networking code) 让 Linux 在效率和功能上﹐较其它 OS 略胜一筹。事实上﹐新的路由过滤还有分类(classifying) 程序 ﹐比起一些专用路由器以及防火墙和流量管制产品﹐在功能上甚至有过之而无不及。
随著新网路概念的不断涌现﹐人们无不各显神通将之安插于现有 OS 的架构之上。然而﹐这些持续的堆积﹐却导致网路程序码变的无奇不有﹐有如我们人类的各式语言。在过去﹐Linux 模仿 SunOS 来处理这些事情﹐但终非良策。
此一新架构将可详尽阐释远非 Linux 所能及的功能行为。
Linux 本身有一个复杂异常的系统用于频宽界定﹐叫做 Traffic Control。此系统支持多种方法﹐以应付传入及传出交通的分类(classfying)﹑优先排序(prioritizing)﹑分享(sharing)﹑以及限制(limiting)﹐等处理。
下面﹐我们就让我们粗略溜灠一下 iproute2 的能耐吧。
首先﹐请确定必须的使用者工具已经安全妥当。在 RedHat 和 Debian 上﹐此套件都叫做 'iproute'﹐或是直接抓 ftp://ftp.inr.ac.ru/ip-routing/iproute2-2.2.4-now-ss??????.tar.gz"
也可以。
您也可以尝试到 这里 获得最新的版本。
iproute 中的某些部份还需要将特定的核心选项打开。另外﹐您还要知道﹐RedHat 6.2 之前的所有发行版本﹐其核心里面﹐大部份的流量控管功能都付诸阙如。
FIXME: 有谁可以帮忙确认一下 7.0 已经将所需核心编译进来了吗﹖
同时﹐您还要确认您有支持 netlink ﹐您或许需要打造自己的核心﹐因为 iproute2 需要这个功能。
给您一个惊喜﹐其实 iproute2 已经设定好了﹗当前命令如 ifconfig
和 route
﹐都已经使用进阶的 syscall﹐但通常都使用预设值。
其中 ip
这工具最为重要﹐下面用它将我们的界面列示出来。
ip
显示连线 (ip
shows us our links)
[ahu@home ahu]$ ip link list
1: lo: <LOOPBACK,UP> mtu 3924 qdisc noqueue
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: dummy: <BROADCAST,NOARP> mtu 1500 qdisc noop
link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
3: eth0: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1400 qdisc pfifo_fast qlen 100
link/ether 48:54:e8:2a:47:16 brd ff:ff:ff:ff:ff:ff
4: eth1: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast qlen 100
link/ether 00:e0:4c:39:24:78 brd ff:ff:ff:ff:ff:ff
3764: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP> mtu 1492 qdisc pfifo_fast qlen 10
link/ppp
您所读到的资料或许有所不同﹐这里所显示的是在我家里的 NAT router 上的资料。我下面只会解释输出结果的一部份而已﹐因为并非全部资料都是相关的。
让我们先看看 loopback 界面。有可能您的电脑并没装任何界面﹐但我建议您起码将它设定起来。其中的 MTU (Maximum Transfer Unit) 体积是 3924 octet﹐同时并没被伫列(queued) 起来。这是合理的﹐因为 loopback 界面是由核心虚构出来的。
现在而言﹐我暂时略过 dummy 界面不谈﹐而且它也未必出现在您的电脑上面。接下来是我的两张实体网路界面﹐一个连接我的 cable modem﹐另一个接到我的家中网路去。最后﹐我们也看到一个 ppp0 的界面。
注意﹐这里并没有 IP 位址。iproute 并没有将 'links' 和 'IP addresses' 这两概念连在一起。如果用 IP aliasing 的话﹐那么 IP 位址的概念就似乎变得不怎么贴切了。
不过﹐它会将 MAC 位址显示出来﹐也就是我们的 ethernet 界面的实体辨别位址啦。
ip
显示 IP 位址 (ip
shows us our IP addresses)
[ahu@home ahu]$ ip address show
1: lo: <LOOPBACK,UP> mtu 3924 qdisc noqueue
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
2: dummy: <BROADCAST,NOARP> mtu 1500 qdisc noop
link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
3: eth0: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1400 qdisc pfifo_fast qlen 100
link/ether 48:54:e8:2a:47:16 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.1/8 brd 10.255.255.255 scope global eth0
4: eth1: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast qlen 100
link/ether 00:e0:4c:39:24:78 brd ff:ff:ff:ff:ff:ff
3764: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP> mtu 1492 qdisc pfifo_fast qlen 10
link/ppp
inet 212.64.94.251 peer 212.64.94.1/32 scope global ppp0
这次包含的信息就比较多了。它将所有的位址﹐以及所属的网卡都显示出来。'inet' 代表 Internet (IPv4)。当然﹐还有许多其它的位址族群﹐不过目前来说﹐暂时与我们无关。
让我们仔细的看看 eth0 吧。它目前被分配的 inet 位址是 '10.0.0.1/8'。这是什么意思呢﹖先看 /8 好了﹐它所代表的是网路位址 bit 数目。因为一个 IP 位址有 32 bit﹐所以我们就剩下 24 bit 给我的网路(主机)使用了。10.0.0.1 的前面 8 个 bit 所对应的是 10.0.0.0﹐也就是我们的网路位址(Network Address)﹐这样我们的 netmask 是 255.0.0.0。
那剩下的 bits (所对应的位址)就直接连线到这个界面﹐拿例子来说明﹕可以直接在这个界面连上 10.250.3.13 ﹐和 10.0.0.1 一样。
至于 ppp0 呢﹐也是同样的原理啦﹐只是号码之别而已。它的位址是 212.64.94.251﹐并没有 subnet mask。这表示我们有一个 point-to-point 的连线﹐并且所有位址﹐除了这个 212.64.94.251 之外﹐都在硬件那边。除此之外﹐还有更多的信息﹐告诉我们在连线的另一端也同样只有一个位址﹕212.64.94.1。那个 /32 ﹐是告诉我们没有 'network bits' 的意思。
牢靠的掌握前述概念是至关重要的。假如您在理解上有困难﹐请参考本 HOWTO 前面所介绍的资料。
(译者按﹕关于 IP 和 netmask 的关系﹐主要是用来判断出?网路位址'和?主机位址'之用的。详细的判断规则﹐可以参考译者的网站﹕ http://www.study-area.org/network/network_ipadd.htm。)
同时﹐还请留意 'qdisc' 这个东东﹐它是 Queueing Discipline (伫列戒律﹖) 的意思。这个概念也至为重要。
ip
显示路由 (ip
shows us our routes)好了﹐我们已经晓得如何查找 10.x.y.z 这样的位址了﹐而且也能够连上 212.64.94.1。只是﹐光是这几路散手是不能出师的﹐所以我们还要教您如何杀出木人巷。我们可以透过 ppp 连线接上 internet﹐同时封包会以 212.64.94.1 这个位址丢到外面去﹐然后别人也是以这个位址将结果送回来。
[ahu@home ahu]$ ip route show
212.64.94.1 dev ppp0 proto kernel scope link src 212.64.94.251
10.0.0.0/8 dev eth0 proto kernel scope link src 10.0.0.1
127.0.0.0/8 dev lo scope link
default via 212.64.94.1 dev ppp0
输出结果本身就说得很清楚了。前面 4 行精确的描述出我们从 ip address show
所揭示的意义﹐而最后一行则告诉我们我们可以透过 212.64.94.1﹐也就是我们的预设网关(default gateway)﹐和外面的世界做连线。我们之所以将之视为网关﹐是因为我们将封包送给 212.64.94.1﹐然后它就会帮我们善后了。
为方便比较﹐如下是旧的 'route' 命令所显示的内容﹕
[ahu@home ahu]$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use
Iface
212.64.94.1 0.0.0.0 255.255.255.255 UH 0 0 0 ppp0
10.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 eth0
127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo
0.0.0.0 212.64.94.1 0.0.0.0 UG 0 0 0 ppp0
ARP 就是 Address Resolution Protocol﹐其定义可以参考 RFC 826。ARP 是用来查找同一本地网路上﹐其它主机之实体位址/位置用的。而在 Internet 上的机器﹐则通常用它的名称来判别﹐并用它查询出 IP 位址。这就是 foo.com 网路的机器﹐为何能与 bar.net 网路的机器进行沟通的原理。不过﹐光得到一个 IP 位址﹐是没办法告诉您该机器的实体位置在哪里。这时﹐ARP 就派得上用场了。
或许﹐我们找个例子来说说会比较好理解。假设我用几台机器组成一个网路。其中两台目前在我的网路上﹐一台叫 foo﹐其 IP 位址是 10.0.0.1﹔另一台叫 bar﹐其 IP 位址是 10.0.0.2。现在﹐foo 想要 ping 一下 bar﹐看看他是否在线上﹐然而头痛的是﹐foo 并不知道 bar 在哪里。这样﹐当 foo 决定要对 bar 做 ping 的时候﹐它需要先丢出一个 ARP 请求(request)。 这个 ARP 请求就好像 foo 在大声喊﹕“Bar(10.0.0.2)﹗您在哪里啊﹖”其结果是﹐在网路上的所有机器都听到这个呼叫﹐但却只有 bar (10.0.0.2) 会作出回应。然后 bar 会丢出一个 ARP 回应(reply) 直接送回给 foo ﹕“Foo(10.0.0.1)﹐我在 00:60:94:E9:08:12 这里啦。”用这个简单的交流来找出网路上的同伴之后﹐foo 就可以和 bar 沟通了﹐直到它(其 arp cache)忘记 bar 在何方为止。
现在就让我们看看这是如何工作的。您可以先检查机器目前的 arp table ﹐应该会有点像这样﹕
[root@espa041 /home/src/iputils]# ip neigh show
9.3.76.42 dev eth0 lladdr 00:60:08:3f:e9:f9 nud reachable
9.3.76.1 dev eth0 lladdr 00:06:29:21:73:c8 nud reachable
正如您所见到的﹐我的机器 espa041(9.3.76.41) 已知道如何找出 espa042(9.3.76.42)﹐还有 espagate(9.3.76.1)。然后让我们将另一台机器加入 arp cache 中。
[root@espa041 /home/paulsch/.gnome-desktop]# ping -c 1 espa043
PING espa043.austin.ibm.com (9.3.76.43) from 9.3.76.41 : 56(84) bytes of data.
64 bytes from 9.3.76.43: icmp_seq=0 ttl=255 time=0.9 ms
--- espa043.austin.ibm.com ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.9/0.9/0.9 ms
[root@espa041 /home/src/iputils]# ip neigh show
9.3.76.43 dev eth0 lladdr 00:06:29:21:80:20 nud reachable
9.3.76.42 dev eth0 lladdr 00:60:08:3f:e9:f9 nud reachable
9.3.76.1 dev eth0 lladdr 00:06:29:21:73:c8 nud reachable
结果如上﹐espa041 先尝试连接 espa043﹐然后 espa043 的实体位址也已被加进 arp cache 中。这样﹐除非 espa043 的记录逾时(例如他们之间再无沟通)﹐espa041 就知道到哪里找 espa043﹐而无需再送 ARP 请求了。﹐
现在﹐让我们将 espa043 从 arp cache 中删除看看﹕
[root@espa041 /home/src/iputils]# ip neigh delete 9.3.76.43 dev eth0
[root@espa041 /home/src/iputils]# ip neigh show
9.3.76.43 dev eth0 nud failed
9.3.76.42 dev eth0 lladdr 00:60:08:3f:e9:f9 nud reachable
9.3.76.1 dev eth0 lladdr 00:06:29:21:73:c8 nud stale
好了﹐现在 espa041 再次忘记到哪里找 espa043﹐而在下次要和 espa043 沟通的时候﹐就需要送出另外的 ARP 请求。同时﹐您还会从上面的输出结果中发现﹕ espagate(9.3.76.1) 已经变为 "stale" 状态。这是说﹐该显示位置仍然有效﹐但在第一次向该机器传送的时候﹐必须要先确认就是了。