用Iproute2配置隧道(轉)

post0發表於2007-08-11
用Iproute2配置隧道(轉)[@more@]

用Iproute2配置隧道

Simone Piunno 著 wqch 翻譯

1、Iproute2簡介

Iproute2是一個在Linux下的高階網路管理工具軟體。實際上,它是透過rtnetlink sockets方式動態配置核心的一些小工具組成的,從Linux2.2核心開始,Alexey Kuznetsov 實現了透過rtnetlink sockets用來配置網路協議棧,它是一個現代的強大的介面。

Iproute2最吸引人的特色就是它用完整而有機制的簡單命令替代了之前以下命令的功能,如ifconfig,arp,route,iptunnel,而且還新增了其它不少的功能。

如今,Iproute2已經在很多主要的發行版裡被預設安裝,即使他們的初始化指令碼命令被嵌入在一些老的網路工具包裡,如ifconfig,以及少用的iptunnel。如果你的發行版沒有包含這個重要的工具包,你也可以從網上下載並自己編譯。下載地址ftp: //ftp.inr.ac.ru/ip-routing/。

在寫這篇文章的時候,Iproute2最大的缺點就是缺乏相關的說明文件,然而,它的IP命令語法的簡單而且還很象英語,這在很大程度上對說明文件做了相應的補償。相信習慣於ifconfig和route命令的人不願意在用ip的時候遇到任何困難,而且他們會覺得自己象在家裡用一樣。本文假設讀者已經有一定的網路基礎,並且已經在Linux中用過ifconfig和route命令。

2、隧道簡介

我們想像一下在二個網路節點間要進行資料通訊的問題,如果這二個節點在不同於IPv4的協議上傳輸,或者用非全球可用IP地址直接傳送到一個私有區域網LAN中。為了解決這類問題,典型的是在兩個節點間用虛擬的點對點連線,我們稱之為隧道結構。

你可以把在網路上傳輸的每個資料包想像為一個信封,它裡面有幾個位元組,外面還寫上了傳送者和接收者的地址。隧道把這個信封簡單的隱藏在另一個不同的傳送者和接收者的信封裡面,有效的進行資料包的傳送。當資料包到達外部接收者(寫在最外面的信封上的接收者)的時候,就把這個外部信封去掉並扔了,所以這個時候的信封(資料包)可以繼續被傳送到它的真正目的地。

封裝和拆分附加信封的節點被叫做端點,它們需要一個全球可用的IPv4地址。這就是為什麼當經過網路地址轉換(NAT)時隧道就不能用了。而且,如果構建一個透過防火牆的隧道,那麼防火牆就必須特殊配置來允許隧道傳輸。

一個典型的隧道應用就是透過一個純IPv4網路來連線二個IPv6節點。這二個節點可以透過構建一個偽裝的點到點IPv6連線的IPv6-in- IPv4隧道,這種方式可以把二個IPv6島連線在一起(6bone就是透過這樣一種網路隧道的方式工作的)。IPv6-over-IPv4傳輸隧道有二種方式:自動配置(詳見RFC2373)和人工配置,本文將討論的是後者——人工配置。

3、建立隧道

用Iproute2構建隧道是很容易的事情。首先,你需要為隧道命一個名,如果你把隧道名字選擇用foo,此時,你可以用如下命令來建立SIT模式的隧道:

ip tunnel add foo mode sit remote 192.168.1.42

以這種方式,將IPv4地址為192.168.1.42的遠端端點也建一個SIT模式的IPv6-in-IPv4隧道。注意,我們還沒有指定那個IP地址來用這個本地隧道,以及那個介面等等,這些結果可以透過命令ip tunnel show 來看到:

[root@abulafia root]# ip tunnel show

sit0: ipv6/ip remote any local any ttl 64 nopmtudisc

foo: ipv6/ip remote 192.168.1.42 local any ttl inherit

我們建立的隧道在第二行。現在需要看看所有可用介面的列表,不管他們是真正的網路介面卡還是模擬的:

[root@abulafia root]# ip link show

1: lo: mtu 16436 qdisc noqueue

link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

2: eth0: mtu 1500 qdisc pfifo_fast qlen 100

link/ether 00:48:54:1b:25:30 brd ff:ff:ff:ff:ff:ff

4: sit0@none: mtu 1480 qdisc noop

link/sit 0.0.0.0 brd 0.0.0.0

6: foo@none: mtu 1480 qdisc noop

link/sit 0.0.0.0 peer 192.168.1.42

事實上需要注意的是lo和eth0是被標誌為up,說明是已經啟用,而隧道沒有。為了再次檢查,用ifconfig檢視:

[root@abulafia root]# ifconfig

eth0 link encap:ethernet hwaddr 00:48:54:1b:25:30

inet addr:192.168.0.1 bcast:192.168.0.255 mask:255.255.255.0

inet6 addr: fe80::248:54ff:fe1b:2530/10 scope:link

up broadcast running multicast mtu:1500 metric:1

rx packets:0 errors:0 dropped:0 overruns:0 frame:0

tx packets:8 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:100

rx bytes:0 (0.0 b) tx bytes:528 (528.0 b)

interrupt:9 base address:0x5000

lo link encap:local loopback

inet addr:127.0.0.1 mask:255.0.0.0

inet6 addr: ::1/128 scope:host

up loopback running mtu:16436 metric:1

rx packets:35402 errors:0 dropped:0 overruns:0 frame:0

tx packets:35402 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:0

rx bytes:3433996 (3.2 mb) tx bytes:3433996 (3.2 mb)

顯然,不顯示沒有被啟用的介面,所以必須記住,ip連線命令顯示所有可用介面,不管他們是否被啟用。為了啟用foo,用命令:

ip link set foo up

解除它用:

ip link set foo down

徹底的刪掉隧道用:

ip tunnel del foo

4、特殊隧道

在之前的段落中,介紹了怎樣構建一個IPv6-in-IPv4隧道,現在來看看幾個不同的情況。

4.1、GRE隧道

如果你不需要IPv6,但是假如你想透過一個不同協議的傳輸網路來傳遞普通IPv4資料包,那麼最好用GRE模式代替SIT模式。例如:

[root@abulafia root]# ip tunnel add foo4 mode gre remote 192.168.1.42

[root@abulafia root]# ip tunnel show

gre0: gre/ip remote any local any ttl inherit nopmtudisc

foo4: gre/ip remote 192.168.1.42 local any ttl inherit

[root@abulafia root]# ip link show

1: lo: mtu 16436 qdisc noqueue

link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

2: eth0: mtu 1500 qdisc pfifo_fast qlen 100

link/ether 00:48:54:1b:25:30 brd ff:ff:ff:ff:ff:ff

7: gre0@none: mtu 1476 qdisc noop

link/gre 0.0.0.0 brd 0.0.0.0

9: foo4@none: mtu 1476 qdisc noop

link/gre 0.0.0.0 peer 192.168.1.42

GRE模式是一個特殊的隧道傳輸,它被Cisco路由器支援,Cisco路由器可以在IPv4上實現不同協議之間資料包的傳送。還有另外一種被 Linux實現的隧道:ipip,它同樣可以實現IPv4-in-IPv4的封裝,但是它只被Linux實現,而且只有單播的IP over IP(所以你不能傳送IPX或者廣播資料包)。總的來說,GRE模式更好。

4.2 直接本地端點

即使核心很聰明的可以為你做隧道選擇,最好還是很清楚的說明將要用做隧道的IPv4地址和介面標誌。用命令帶本地和裝置引數來實現:

[root@abulafia root]# ip tunnel add foo mode sit local 192.168.0.1 remote 192.168.1.42 dev eth0

[root@abulafia root]# ip tunnel show

sit0: ipv6/ip remote any local any ttl 64 nopmtudisc

foo: ipv6/ip remote 192.168.1.42 local 192.168.0.1 dev eth0 ttl inherit

[root@abulafia root]# ip link show

1: lo: mtu 16436 qdisc noqueue

link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

2: eth0: mtu 1500 qdisc pfifo_fast qlen 100

link/ether 00:48:54:1b:25:30 brd ff:ff:ff:ff:ff:ff

4: sit0@none: mtu 1480 qdisc noop

link/sit 0.0.0.0 brd 0.0.0.0

11: foo@eth0: mtu 1480 qdisc noop

link/sit 192.168.0.1 peer 192.168.1.42

Please notice that now the interface is labeled as foo@eth0, to remind us where the tunnel has been explicitly connected.

請注意介面被標誌為foo@eth0,這樣可更清楚的提示我們隧道在哪兒被連線。

4.3 生存時間

使用隧道時,建一個附加的環回網路介面是很容易的。為了限制這個問題,基本原則是生成一個較底TTL值的資料包。初始的TTL可以用命令ip tunnel add來指定TTL值,預設值是從關聯的隧道網路介面繼承下來的。IANA建議TTL的值是64。

5、為介面指派IP地址

像其它網路介面一樣,隧道也可以被指派一個或者多個地址。

5.1、主地址

直接指派主地址:

ip addr add 3ffe:9001:210:3::42/64 dev foo

ip addr add 192.168.0.2/24 dev foo4

ip addr add 10.20.30.40/8 dev eth0

The number immediately following the slash is to suggest to the kernel the network prefix we prefer, useful to automatically compute broadcast address and netmask on IPv4 LANs (this is called CIDR notation). However, tunnels are point-to-point interfaces and this number is then ignored.

緊跟在地址後面的數字是網路字首,用來在IPv4區域網中自動計算廣播地址和網路掩碼(叫做CIDR)。然而,隧道是點到點介面,這些數字是被忽略的。

注意:為了給介面指派一個IP地址,首先你需要用ip link 來把該介面啟用。

要從一個介面去掉一個地址,可以直接用del代替之前新增地址所用的add:

ip addr del 3ffe:9001:210:3::42/64 dev foo

ip addr del 192.168.0.2/24 dev foo4

列出在自己伺服器上可用的IP地址:

[root@abulafia root]# ip addr show

1: lo: mtu 16436 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

inet6 ::1/128 scope host

2: eth0: mtu 1500 qdisc pfifo_fast qlen 100

link/ether 00:48:54:1b:25:30 brd ff:ff:ff:ff:ff:ff

inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0

inet6 fe80::248:54ff:fe1b:2530/10 scope link

4: sit0@NONE: mtu 1480 qdisc noop

link/sit 0.0.0.0 brd 0.0.0.0

5: foo@NONE: mtu 1480 qdisc noop

link/sit 0.0.0.0 peer 192.168.1.42

inet6 3ffe:9001:210:3::42/64 scope global

inet6 fe80::c0a8:1/10 scope link

5.2、別名

當在一個介面上用多個地址時,習慣於用ifconfig的人會對ip addr add命令在新增多個IP後,卻不產生像eth0:1,eth0:2等這樣的虛擬介面而吃驚。這個是從2.0核心繼承下來的一個命名機制,直到今天也沒有改變。例如:

[root@abulafia root]# ip addr add 192.168.0.11/24 dev eth0

[root@abulafia root]# ip addr show eth0

2: eth0: mtu 1500 qdisc pfifo_fast qlen 100

link/ether 00:48:54:1b:25:30 brd ff:ff:ff:ff:ff:ff

inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0

inet 192.168.0.11/24 scope global secondary eth0

inet6 fe80::248:54ff:fe1b:2530/10 scope link

[root@abulafia root]# ifconfig

eth0 Link encap:Ethernet HWaddr 00:48:54:1B:25:30

inet addr:192.168.0.1 Bcast:192.168.0.255 Mask:255.255.255.0

inet6 addr: fe80::248:54ff:fe1b:2530/10 Scope:Link

UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

RX packets:0 errors:0 dropped:0 overruns:0 frame:0

TX packets:8 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:100

RX bytes:0 (0.0 b) TX bytes:528 (528.0 b)

Interrupt:9 Base address:0x5000

lo Link encap:Local Loopback

inet addr:127.0.0.1 Mask:255.0.0.0

inet6 addr: ::1/128 Scope:Host

UP LOOPBACK RUNNING MTU:16436 Metric:1

RX packets:34732 errors:0 dropped:0 overruns:0 frame:0

TX packets:34732 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:0

RX bytes:3386912 (3.2 Mb) TX bytes:3386912 (3.2 Mb)

foo Link encap:IPv6-in-IPv4

inet6 addr: 3ffe:9001:210:3::42/64 Scope:Global

inet6 addr: fe80::c0a8:1/10 Scope:Link

UP POINTOPOINT RUNNING NOARP MTU:1480 Metric:1

RX packets:0 errors:0 dropped:0 overruns:0 frame:0

TX packets:0 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:0

RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)

新增的IP地址已經工作,並用ip addr show可以顯示,但是ifconfig甚至看不見它的存在。為了解決這個問題,加上一個標籤引數:

[root@abulafia root]# ip addr add 192.168.0.11/24 label eth0:1 dev eth0

[root@abulafia root]# ip addr show eth0

2: eth0: mtu 1500 qdisc pfifo_fast qlen 100

link/ether 00:48:54:1b:25:30 brd ff:ff:ff:ff:ff:ff

inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0

inet 192.168.0.11/24 scope global secondary eth0:1

inet6 fe80::248:54ff:fe1b:2530/10 scope link

[root@abulafia root]# ifconfig

eth0 Link encap:Ethernet HWaddr 00:48:54:1B:25:30

inet addr:192.168.0.1 Bcast:192.168.0.255 Mask:255.255.255.0

inet6 addr: fe80::248:54ff:fe1b:2530/10 Scope:Link

UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

RX packets:0 errors:0 dropped:0 overruns:0 frame:0

TX packets:8 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:100

RX bytes:0 (0.0 b) TX bytes:528 (528.0 b)

Interrupt:9 Base address:0x5000

eth0:1 Link encap:Ethernet HWaddr 00:48:54:1B:25:30

inet addr:192.168.0.11 Bcast:0.0.0.0 Mask:255.255.255.0

UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

Interrupt:9 Base address:0x5000

注意:我們可以選擇任意的字串作介面標籤,沒有強迫使用2.0核心的命名機制;如果要用ifconfig實現向後相容,就必須依照此命名機制。

5.3、隧道IP地址

當我們的計算機是一個獨立主機或者不是一個提供到整個區域網IPv6連線的路由器時,為本地端節點隧道選擇一個全球/公用IP地址是最好的事,分別是一個SIT/IPv6-in-IPv4隧道的IPv6地址和一個GRE/IPv4-in-IPv4隧道的IPv4地址。

取而代之,若配置一個路由器,最好讓SIT/IPv6-in-IPv4隧道用一個鏈路本地地址(IPv6的鏈路本地地址可以透過無狀態地址自動配置或者人工配置)和GRE/IPv4-in-IPv4隧道用一個私有地址(IPv4沒有鏈路本地地址)。有效的地址只能用在eth0上(或者在區域網那邊的介面上)。注意在配置的時候需要啟用轉發介面,用命令:

sysctl -w net.ipv4.conf.all.forwarding=1 # for GRE (IPv4-in-IPv4)

sysctl -w net.ipv6.conf.all.forwarding=1 # for SIT (IPv6-in-IPv4)

甚至可以決定開啟在一對間轉發,這種情況下,用如下命令:

sysctl -w net.ipv6.conf.eth0.forwarding=1

sysctl -w net.ipv6.conf.pippo.forwarding=1

6、路由

既然隧道已經被配置好了,現在需要指定哪些資料運輸將被定向透過它。IPv6的一般命令格式如下:

ip route add 2000::/3 dev foo

這樣,在目的地址前3位是001的地址(即全球IPv6單播地址空間)將被定向到foo介面,這只是IPv6地址空間的八分之一,但要保證所有可能的遠端主機都是在這個範圍內。

在IPv4路由表中:

[root@abulafia root]# ip route

192.168.0.0/24 dev eth0 scope link

127.0.0.0/8 dev lo scope link

而IPv6路由表:

[root@abulafia root]# ip -6 route

2000::/3 dev foo proto kernel metric 256 mtu 1480 advmss 1420

fe80::/10 dev eth0 proto kernel metric 256 mtu 1500 advmss 1440

fe80::/10 dev foo proto kernel metric 256 mtu 1480 advmss 1420

ff00::/8 dev eth0 proto kernel metric 256 mtu 1500 advmss 1440

ff00::/8 dev foo proto kernel metric 256 mtu 1480 advmss 1420

default dev eth0 proto kernel metric 256 mtu 1500 advmss 1440

unreachable default dev lo metric -1 error -101

如果想指定一個閘道器(不是給隧道的),可以用via引數,例如:

ip route add 192.168.1.0/24 via 192.168.0.254 dev eth0

去掉路由可以用ip route del命令,但是要小心的是如果這樣寫ip route del default將移除預設的IPv4路由,並不是IPv6的路由。要移除IPv6預設的目的地址需要用命令ip -6 route del default。

7、一個完整的例子

一個典型的6bone的IPv6隧道:

ip tunnel add $TUNNEL mode sit local any remote $V4_REMOTEADDR ttl 64

ip link set $TUNNEL up

ip addr add $V6_LOCALADDR dev $TUNNEL

ip route add 2000::/3 dev $TUNNEL

$TUNNEL是一個任意的指定隧道的名稱,$V4_REMOTEADDR是隧道另一端的IPv4地址,$V6_LOCALADDR是分配給本地主機的IPv6本地地址。為本地端節點地址用一個任意值,因為這樣可以處理一個動態IPv4地址(如透過撥號連線到ISP)。顯然,當我們的地址改變時,需要通知隧道代理,但是這個已經不是本文所設計的範圍,而且也沒有一個標準的處理程式。

關閉隧道:

ip tunnel del $TUNNEL

也可以自動的移除路由介面和地址。

原文:

[/url

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8225414/viewspace-945560/,如需轉載,請註明出處,否則將追究法律責任。

相關文章