Linux上的IPv6路由

Mahendra M

Coordinator, Bangalore Linux User Group

( http://linux-bangalore.org )

Email : mahmk@symonds.net

 

摘要

隨著Internet驚人的成長,IPv6變得越來越重要。IPv6路由成為另一個重要的研究領域。Linux支援IPv6是最令人高興的一件事。因此Linux平台在IPv6的實作裡面變得越來越重要。這份文件的目的在於闡明Linux的路由架構與Linux如何應用在IPv6的路由上。

 

序論

Linux已成為主流作業系統之一。他低廉的價格,穩定以及對IPv6良好的支援讓他成為實作IPv6相當好的平台。至於路由,Linux有一個很棒的架構稱為iproute2,他可以讓使用者在路由方面實作出很棒的東西,甚至是IPv6的路由。
在這份文件中,我們將看看Linux的路由以及Linux IPv6路由器的設定,一些特性的簡述、可用的工具以及動態路由的daemons等等。我們會以一些簡單的狀況以及範例來說明他的設定。

 

IPv6Linux中的歷史

在我們開始進入“Linux上的IPv6路由”的細節之前,最好是先來了解一下IPv6Linux中的歷史。
早在199611IPv6程式碼便附加在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功能。

 

目前的狀態

目前IPv6Linux中的狀態是“實驗性的”,但Linux會很快為IPv6做好準備。不管是核心、函式庫或者應用程式,各個層面對IPv6的支援與日俱增。現在大部分應用程式都已經支援IPv6,此外的許多都已在進行轉換。

 

預先的必備條件

在你能建立一個Linux IPv6路由器之前,你的系統必須能支援IPv6。意即核心以及大部分的網路設定工具都要支援IPv6。如果你用最新的Linux套件,大部分的工具都會支援IPv6,否則你就得手動升級這些工具。你將會需要net-toolsiproute2這兩個套件。Net-tools包含了些基本的網路工具,像是netstatifconfig以及route等等,而iproute2裡面有ipifcfg以及rtmon等用於使用Linux核心中進階網路功能的工具。
要讓核心支援IPv6,你需要啟用IPv6, EUI-64, GRE Tunneling選項來重新編譯核心,然後用新的核心開機。
接下來我們都會假設你的系統已經有支援IPv6的核心以及net-tools工具套件。

 

IPv6位址設定

我們不用深入的探討LinuxIPv6位址設定的細節。你可以用像是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_forwardIPv6的設定在/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, maindefault。我們來看看規則是如何讓他們結合的:

# 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路由器的設定

兩個最常用的工具routeip可以用來設定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上路由設定的狀況

狀況1:新增一個通過閘道器的IPv6路由

 

 

 

在你的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 daemonRouter 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位址給這個裝置,而最後一行是新增一個通過tunnel3ffe::/15(整個6bone)的路由。

動態路由

在大型的網路裡面我們需要一些工具來動態的導引資料。動態路由有兩個標準協定,分別是OSPF以及BGP。路由daemons是支援這些協定的daemons並且維護路由表。即使是IPv6網路,這些也可以用底下所提到的daemons來完成。

支援IPv6的路由Daemons

底下的路由daemons可以用在Linux上(免費軟體)

l          mrtd        -       http://www.mrtd.net
Multi-threaded Routing Toolkit –
這個工具包含了多協定IPv4/IPv6路由daemons以及路由分析/模擬工具。支援的協定有:BGP4+/BGP/RIPng/RIP2路由軟體(現在包含DVMRP以及PIM-DM

l          zebra       -       http://www.zebra.org
GNU Zebra
支援 BGP4, BGP4+, OSPFv3, RIPv1, RIPv2以及RIPng。支援RFCs 2373, 2460, 2463 & 2464IPv6支援)。具有一個強大的新結構。

l          bird          -       http://bird.network.cz
BIRD
代表 BIRD Internet Routing Daemon(另一個遞迴縮寫)。支援IPv4以及IPv6協定,多重路由表,BGP, RIP, 以及OSPF。非常易於使用及設定。同時也有一個強大的路由篩選語言。

議題

雖然有許多的改善,在LinuxIPv6的支援上仍然有許多的議題。主要的問題有

l          不相容於RFCs(這個很快就會解決)

l          因核心與libc被分別開發,他們有不相容的問題

TAHI計劃在Linux(核心2.2.15)上做了一系列的IPv6相容性測試。雖然在大多數的測試裡Linux達到>90%的成功率(多數是100%),不過在有些項目遠遠的落後。包含了:

Neighbor Discovery

34% success rate

IPv6 MTU Discovery

50% success rate

IPv6 Stateless Address Autoconfiguration

04% success rate

Linux達到100%的成功率在robustness, IPv6-over-IPv4 tunneling & ICMPv6IPv6規格的測試。

改正這些問題的工作正在進行中。即使有這些問題,我對Linux社群在完成與提供出色的IPv6支援的能力還是相當有信心。


總結

在這份文件中我們只看了一些設定Linux IPv6路由器的簡單步驟。iproute2架構讓我們有更多有趣與更有挑戰的設定。這份文件嘗試指引你一個方向。

進階閱讀

Advanced Routing HOWTO -
http://www.ibiblio.org/pub/Linux/docs/HOWTO/Adv-Routing-HOWTO

Packet Filtering HOWTO – Rusty Russel -
http://netfilter.samba.rog/documentation/HOWTO/packet-filtering-HOWTO.txt

Advance Routing Mini HOWTO -
http://snafu.freedom.org/linux2.2/docs/advanced-routing/

6.2 有用的連結

USAGI Project – http://www.linux-ipv6.org

TAHI Project – http://www.tahi.org

Linux-IPv6-HOWTO – http://www.bieringer.de/linux/IPv6

Current Linux+IPv6 stats - http://www.bieringer.de/linux/IPv6

RADVD Home page – http://v6web.litech.org/radvd