随着Internet惊人的成长,IPv6变得越来越重要。IPv6路由成为另一个重要的研究领域。Linux支援IPv6是最令人高兴的一件事。因此Linux平台在IPv6的实作里面变得越来越重要。这份文件的目的在于阐明Linux的路由架构与Linux如何应用在IPv6的路由上。
序论
Linux已成为主流操作系统之一。他低廉的价格,稳定以及对IPv6良好的支持让他成为实作IPv6相当好的平台。至于路由,Linux有一个很棒的架构称为iproute2,他可以让使用者在路由方面实作出很棒的东西,甚至是IPv6的路由。
在这份文件中,我们将看看Linux的路由以及Linux IPv6路由器的设定,一些特性的简述、可用的工具以及动态路由的daemons等等。我们会以一些简单的状况以及范例来说明他的设定。
IPv6在Linux中的历史
在我们开始进入“Linux上的IPv6路由”的细节之前,最好是先来了解一下IPv6在Linux中的历史。
早在1996年11月IPv6程序代码便附加在Linux核心(版本2.1.18)中。由于缺乏实作IPv6的人力,所以没有办法跟上最新RFCs的标准。2000年十月在日本展开了USAGI ( UniverSAl playGround for IPv6 ) 计划,以实作出所有Linux中所缺乏的IPv6功能为目标。不过USAGE的修正档实在是很大,因为现今Linux核心中网络部分程序代码的维护者没有办法把他实作在现今的稳定版本2.4.x系列中。因此2.4.x系列缺乏了许多增订的部分,而且没有办法符合目前最新的RFCs标准。
(路由部分的程序代码也是如此)。
这看来是一个非常危险的局面,同时也成为Linux与其他操作系统兼容方面上的主要议题。幸运的,USAGI现在要以Linux的发展中版本2.5.x来实作所有的增订部分。稳定版本2.6.x系列就会拥有最新且完整的IPv6功能。
目前的状态
目前IPv6在Linux中的状态是“实验性的”,但Linux会很快为IPv6做好准备。不管是核心、函式库或者应用程序,各个层面对IPv6的支持与日俱增。现在大部分应用程序都已经支持IPv6,此外的许多都已在进行转换。
预先的必备条件
在你能建立一个Linux IPv6路由器之前,你的系统必须能支持IPv6。意即核心以及大部分的网络设定工具都要支持IPv6。如果你用最新的Linux套件,大部分的工具都会支持IPv6,否则你就得手动升级这些工具。你将会需要net-tools与iproute2这两个套件。Net-tools包含了些基本的网络工具,像是netstat,ifconfig以及route等等,而iproute2里面有ip,ifcfg以及rtmon等用于使用Linux核心中进阶网络功能的工具。
要让核心支持IPv6,你需要启用IPv6, EUI-64, GRE Tunneling选项来重新编译核心,然后用新的核心开机。
接下来我们都会假设你的系统已经有支持IPv6的核心以及net-tools工具套件。
IPv6地址设定
我们不用深入的探讨Linux中IPv6地址设定的细节。你可以用像是ifconfig, ip等工具,这儿有一个以ifconfig来设定的范例
# /sbin/ifconfig <interface> inet6 add <ipv6address/prefixlength>
一个建立的范例-指定一个IPv6地址3ffe:ffff:0:f101::1/64给你的eth0装置,你需要用root身份键入下列指令
# /sbin/ifconfig eth0 inet6 add 3ffe:ffff:0:f101::1/64
(上面的范例中,eth0是你的第一个以太网络装置。IPv6选项指定该地址是一个IPv6地址。add选项是用来新增一个IPv6地址到该界面上)
(以del取代add则可以从一个界面上移除一个IPv6地址)
Linux上的路由
一个封包的旅程
让我们来看看当一个封包到达Linux机器的时候发生了什么事
当一个IP封包到达路由器的界面上时,核心首先会套用一串输入防火墙炼在它身上。如果封包可以通过这些炼,而且封包转送是开启的(IPv4的设定在/proc/sys/net/ipv4/ip_forward,IPv6的设定在/proc/sys/net/ipv6/conf/all/forwarding其值不为零),它将会根据路由表以及转送防火墙炼送到其他界面去。如果它的目的地就在路由器的界面上,它就结束旅程。
(防火墙炼是一个规则列表。每一条规则表示“如果封包的标头看起来像这样,那么就对它作这个动作。”输入炼是套用在到达机器的封包,输出炼是套用在离开机器的封包而转送炼是套用在要被转送的封包上)
通常路由表包含了往所有IP目的地之路径的描述。通常他们都被汇集成一群-网络,每一个都单一的被描述,藉由网络地址(一群地址中的第一个)以及网络屏蔽(屏蔽长度)。路由表有两个主要字段:
目的地:如何到达那里
这里有一个图形化的表示法,说明一个封包如何在Linux机器里被处理
Linux不只有单一个这样的路由表,他可能有一群这样的表。这些表也被称做类别。
一个“类别”通常是一个完整的路由表,换言之,他是许多节点(destinaton prefix, tos, metric)组成的树,并且附加了网关,接口等信息在其上。在RFC1812 5.2.4.3之中有其定义。
目前类别的数量被限制在255个。(0是保留给“未指定类别”。)有三个类别是内建的:
RT_CLASS_LOCAL=255 – 本地接口地址,广播地址,nat地址。
RT_CLASS_MAIN=254 – 所有一般的路由预设的类别。
RT_CLASS_DEFAULT=253
每一个类别被套用在符合某些规则的封包上,这些规则使用ip工具的ip rule语法被设定。当路由表用ip route建立起来时,有三个内建的表(类别):local, main跟default。我们来看看规则是如何让他们结合的:
# ip rule
0: from all lookup local
32766: from all lookup from main
32767: from all lookup from default
依照他们的偏好值(冒号前面的数字)为序,规则被核心处理。在上面的那个设定中,任何到达的封包,往他目的地的路径首先会到local表查阅,如果没找到才往main表与default表查询。
当一个接口以ifconfig(或者ip link以及ip addr)设定好的时候,主机的ip与广播地址会出现在local表。往本地网络之路由会出现在main表。这些事情将自动的被完成。如果要检查N表里面有什么我们可以输入
# ip route list table N
设定与新增规则已经不在本文章的范围之内了。所以本文之中我们只会用到main表来做所有的路由设定。有关Linux路由规则与所使用的算法的部分,欲知详情请参阅 - /usr/src/linux[-2.4]/Documentation/networking/policy-routing.txt
IPv6的路由
在这一个部分我们会看一些Linux核心中与路由相关的功能以及三个路由器设定的范例。
核心中的功能
我们来看一些核心(2.4.x)之中可用的功能。
Node Discovery
Duplicate address detection | Working |
Neighbor discovery | Working |
Router discovery | Working |
Routing
Unicast routing | Working |
Multicast routing | Work in progress |
Anycast routing | Working |
Selections
Source address selection | Work in progress |
Default router selection | working |
Options
Hop-by-hop/ jumbo payload | Implemented |
Hop-by-hop/ router alert | Implemented |
Routing header | Implemented |
更多信息可以在文末所附的网站上找到
IPv6路由器的设定
两个最常用的工具route与ip可以用来设定IPv6路由器。你可以参考这两个工具的文件来获得更多细节。
范例:
显示已知的路由
# /sbin/ip –6 route show dev <device>
范例(与简单的输出)
# /sbin/ip –6 route show dev eth0
3ffe:ffff:0:f101::/64 proto kernel metric 256 mtu 1500 advmss 1440
fe80::/10 proto kernel metric 256 mtu 1500 advmss 1440
ff00::/8 proto kernel metric 256 mtu 1500 advmss 1440
default proto kernel metric 256 mtu 1500 advmss 1440
上面的指令显示设置在以太网络装置eth0上面的路由
或者
# /sbin/route –A inet6
Destination | Next Hop | Flags | Metric | Ref | Use | Iface |
3ffe:ffff:0:f101::/64 | :: | UA | 256 | 0 | 0 | eth0 |
fe80::/10 | :: | UA | 256 | 0 | 0 | eth0 |
ff00::/8 | :: | UA | 256 | 0 | 0 | eth0 |
::/0 | :: | UDA | 256 | 0 | 0 | eth0 |
“fe80::/10”的项目是本地连接接口地址的路由而“ff00::/8”的项目多播接口地址的路由。
“::/0”显示的是默认路由(由Flag字段里面的”D”得知)
设定IPv6的路由
让我们看看一些Linux上路由设定的状况
在你的Linux机器上,如果你想要透过一个IPv6的路由器连接到外部的IPv6网络,你需要如下设定你的系统。
语法:
# /sbin/route –A inet6 add <ipv6network>/<prefixlength> gw <ipv6address> [dev <device>]
范例:
要新增一个往 2000::/3 的路由经由网关 3ffe::ffff:0:f101::1 可使用下述指令
# /sbin/route –A inet6 add 2000::/3 gw 3ffe:ffff:0:f101::1
状况2:新增一个通过一个界面的IPv6路由
这个设定是导引往一个特定的网络的封包经由你的机器上特定的网络接口(专用的点对点联机需要这种类型的设定):
语法:
# /sbin/route –A inet6 add <network>/<prefixlength> dev <device>
范例:
拿上面的范例来导引往2000::/3的封包经过eth0界面
# /sbin/route –A inet6 add 2000::/3 dev eth0
状况3:设定你的机器成为一个网关
如果你希望你的Linux机器成为一个IPv6网关那么就照底下的做
# echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
你也可以依照你的需要启动radvd daemon(Router ADVertisement Daemon)来支持IPv6的自动设定功能。
# /usr/local/sbin/radvd
状况4:设定一个IPv6 Tunnel
让我们假设你有一个IPv4的地址172.20.30.1以及一个IPv6地址3ffe:406:5:1:5:a:2:1/96而且你希望连接到6bone。假设6bone路由器的IPv4地址是172.22.33.44
你需要这样做
# ip tunnel add sixbone mod sit remote 172.22.33.44 local 172.20.30.1 ttl 255
# ip link set sixbone up
# ip addr add 3ffe:406:5:1:5:a:2:1/96 dev sixbone
# ip route add 3ffe::/15 dev sixbone
第一行,我们以sit(使用在IPv6-in-IPv4 tunneling)模式建立一个tunnel叫做sixbone。我们设定tunnel从哪里来(本地)以及往哪里去(远程)。
第二行我们让这个装置启动(up)
第三行是新增一个IPv6地址给这个装置,而最后一行是新增一个通过tunnel往3ffe::/15(整个6bone)的路由。
动态路由
在大型的网络里面我们需要一些工具来动态的导引数据。动态路由有两个标准协议,分别是OSPF以及BGP。路由daemons是支持这些协议的daemons并且维护路由表。即使是IPv6网络,这些也可以用底下所提到的daemons来完成。