Next Previous Contents

5. GRE 及其它通道技术 (GRE and other tunnels)

在 Linux 里面的 tunnel 共分三类﹐即 IP in IP tunneling﹑ GRE tunneling﹑以及核心以外的 tunnels (例如﹕PPTP)。

5.1 关于 tunnels 的几项注意 (A few general remarks about tunnels):

Tunnels 可以用来做一些非比寻常的酷玩意。不过﹐如果设定不慎﹐也会将事情弄得一塌糊涂。如果您并非 胸有成竹﹐那就千万不要将您的预设网关指向 tunnel 设备。还有﹐tunneling 也会增加额外的 overhead﹐因为它需要额外的 IP 标头(header)。一般而言﹐每一个封包大概 20 byte 左右﹐这样﹐一个正常的网路封包体积 (MTU) 会是 1500 bytes﹐但如封包果经 tunnel 传送﹐却只有 14800 byte 而已。这其实也不算是什么问题﹐但是当您有机会用 tunnels 来连接大型网路的时候﹐请务必检查 IP 封包的碎片和重组(fragmentation/reassembly)细节。当然啰﹐建立 tunnel 的话﹐最好是从 tunnel 的两端同时著手﹐双管齐下。

5.2 IP in IP tunneling

此类 tunneling 技术其实在 Linux 里已行之有年了。它需要两个核心模块﹕ipip.o 和 new_tunnel.o。

比方说﹐您有 3 个网路﹕A 和 B 皆为内部网路﹐而透过网路 C (或曰 Internet) 将两者连接起来。这样﹐我们的网路 A 会是如此﹕

network 10.0.1.0
netmask 255.255.255.0
router  10.0.1.1
接网路 C 的网关位址为 172.16.17.18。

而网路 B 则这般﹕

network 10.0.2.0
netmask 255.255.255.0
router  10.0.2.1
接网路 C 的网关位址为 172.19.20.21 。

对网路 C 而言﹐我们假设它能够双向的将网路 A 和 B 之间的封包送递对方。您甚至可以用 Internet 啦。

好了﹐然后您要做的事情是﹕

首先﹐确定所有模块都装好了﹕

insmod ipip.o
insmod new_tunnel.o
然后﹐在网路 A 的 router 上﹐这样做﹕
ifconfig tunl0 10.0.1.1 pointopoint 172.19.20.21
route add -net 10.0.2.0 netmask 255.255.255.0 dev tunl0
然后在网路 B 的 router 上﹕
ifconfig tunl0 10.0.2.1 pointopoint 172.16.17.18
route add -net 10.0.1.0 netmask 255.255.255.0 dev tunl0
完成后﹐将 tunnel 暂时关闭﹕
ifconfig tunl0 down
弹指间﹐就这样搞定了。然而﹐您不能透过 IP-in-iP tunnel 传送广播或 IPv6 信息。您刚才将两个本来不能相互沟通的 IPv4 网路连接起来了﹐然仅此而已。基于兼容考量﹐此程序码由来已久﹐因而逆溯至 1.3 版核心皆兼筹并顾。据我所知﹐ Linux 之 IP-in-IP tunneling 并不能在其它的作业系统或 router 上工作。然而它短小精悍﹐实属首选﹐除非您考虑用 GRE。

5.3 GRE tunneling

GRE 是一个原本由 Cisco 开发的 tunneling 协定﹐较于 IP-in-IP tunneling﹐它略为能耐一些。例如﹐您能够透过 GRE tunnel 传送 multicast 和 IPv6 信息。

在 Linux 里﹐您得借助 ip_gre.o 模块。

IPv4 Tunneling

不如先让我们将 IPv4 tunneling 做起来吧﹕

比方说﹐您有 3 个网路﹕A 和 B 皆为内部网路﹐而透过网路 C (或曰 Internet) 将两者连接起来。

关于网路 A ﹐如下﹕

network 10.0.1.0
netmask 255.255.255.0
router  10.0.1.1
在网路 C 上的 router 位址为 172.16.17.18。 然后让我们称这个网路为 neta (好了﹐万事起头难)。

然后﹐关于网路 B﹕

network 10.0.2.0
netmask 255.255.255.0
router  10.0.2.1
在网路 C 上的 router 位址为 172.19.20.21。 然后让我们称这网路为 netb 好了(革命尚未成功﹐同志仍需努力)。

对网路 C 而言﹐我们假设它能够双向的将网路 A 和 B 之间的封包送递对方。至于何以然及何所以然﹐则非我们所要操心的。

接下来﹐在网路 A 的 router 上﹐您如此做﹕

ip tunnel add netb mode gre remote 172.19.20.21 local 172.16.17.18 ttl 255
ip link set netb up
ip addr add 10.0.1.1 dev netb
ip route add 10.0.2.0/24 dev netb

这里﹐我们不妨研究一下。在第一行里面﹐我们新增了一个 tunnel 设备﹐称之为 netb (显而易见﹐因为这正是吾之所欲也)。再来﹐我们让它使用 GRE 协定(mode gre)﹐其硬件位址为 172.19.20.21 (于另一端的 router)﹐这样我们的 tunneling 封包将从 172.16.17.18 从出(您的 router 在网路 C 上可以具有好几个 IP 位址﹐并由您决定用哪一个来做 tunneling)﹐而且﹐封包的 TTL 栏位被设定为 255 (ttl 255)。

第 2 行我们将这个设备启动起来。

在第 3 行﹐我们为新增的界面 netb 设定一个位址为 10.0.1.1。用这个在小网路上也未尝不可﹐只是当您踏上采金旅程之际﹐您或需用其它 IP 范围来给 tunneling 界面就是了(例如在此范例中﹐您可以使用 10.0.3.0)。

在第 4 行﹐我们为网路 B 设定好 router。请留意﹐此处使用的 netmask 表示法并不一样。如果您不太了解其意所在﹐可以这样来理解﹕将 netmask 换算为二进位(binary)﹐然后数一数有多少个 1 就是了。如果您连这个也不会﹐万一又想知道﹐那就这样强记即可﹕255.0.0.0 是 /8﹑255.255.0.0 是 /16﹑还有 255.255.255.0 是 /24﹑而 255.255.253.0 则是 /23。

够了真是的﹐还是让我们看看网路 B 的 router 吧。

ip tunnel add neta mode gre remote 172.16.17.18 local 172.19.20.21 ttl 255
ip link set neta up
ip addr add 10.0.2.1 dev neta
ip route add 10.0.1.0/24 dev neta
假如您要拿掉 router A 上的 tunnel﹐则﹕
ip link set netb down
ip tunnel del netb
当然﹐您也可以替 router B 将 netb 换成 neta。

GRE tunnels 目前所选用的 tunneling 类型。它已成标准并且也被广泛的移植到 Linux 社群之外﹐诚是美事一桩。

5.4 Userland tunnels

在核心之外﹐还有成打形形色色的 tunneling 实作﹐绝非夸张之谈。其中表表者非 PPP 和 PPTP 莫属﹐然而其它的也为数众多 (有的为专属的﹐有的是保密的﹐有的甚至不是使用 IP)﹐不过﹐这些实在超过本 HOWTO 的范畴了。


Next Previous Contents