各种 tunnel

网络中有各种各样的 tunnel,让人眼花缭乱。这里简单分析一下各种 tunnel 的作用。

概括地讲,所谓 tunnel 就是把下一层(比如IPv4层)的包封装到上一层(比如 SSH,HTTP)或者同一层(比如IPv6层)的协议中进行传输,从而实现网络之间的穿透。很明显,这种实现有个前提,那就是,发送端和接收端必须各有一个解析这种包的程序或者内核模块才能实现正常通信。

看最简单的例子,SSH Tunnel,在贵国局域网中的大家都懂的。在本地你需要做端口映射,在中转的ssh 服务器上你需要做port forward。当然,把 HTTP 做到 SSH 之上,算是TCP over TCP了。不过还有更狠的,叫 PingTunnel,基于ICMP的。

这是应用层上的 tunnel,下面看重点,内核中的 tunnel。内核中的那几个 tunnel 可以通过 ip tunnel 命令看到:

% ip tunnel help
Usage: ip tunnel { add | change | del | show | prl | 6rd } [ NAME ]
          [ mode { ipip | gre | sit | isatap } ] [ remote ADDR ] [ local ADDR ]
          [ [i|o]seq ] [ [i|o]key KEY ] [ [i|o]csum ]
          [ prl-default ADDR ] [ prl-nodefault ADDR ] [ prl-delete ADDR ]
          [ 6rd-prefix ADDR ] [ 6rd-relay_prefix ADDR ] [ 6rd-reset ]
          [ ttl TTL ] [ tos TOS ] [ [no]pmtudisc ] [ dev PHYS_DEV ]
...

有四个:ipip、gre、sit、isatap。我们一个一个地看。

ipip 是把 IP 层封装到 IP 层的一个 tunnel,看起来似乎是浪费,实则不然。它的作用其实基本上就相当于一个基于IP层的网桥!我们知道,普通的网桥是基于mac层的,根本不需 IP,而这个 ipip 则是通过两端的路由做一个 tunnel,把两个本来不通的网络通过点对点连接起来。ipip 的源代码在内核 net/ipv4/ipip.c 中可以找到。

gre 和它类似,但它功能还要更强大一些,还支持广播,它可以取代 ipip。它的源代码在 net/ipv4/gre.c。更多介绍看这篇文章

sit 和 isatap 都是 IPv6 over IPv4 的 tunnel,它们的源代码在 net/ipv6/sit.c 中。它们之间也不同,和IPv6的地址有关,写在这里恐怕放不下了,故省略。

别慌,反过来的也有,叫 ip6_tunnel,IPv4 over IPv6。见源代码 net/ipv6/ip6_tunnel.c。

我在前面一篇文章中介绍的 tun 设备,从名字你也看得出来,它不就是 tunnel 的前三个字母嘛!vpnc 使用的就是这个 tunnel,建立一个点对点的通讯,在本地机器上有守候进程vpnc,在远端有vpn服务器。

IPSec 还用到一个叫 L2TP 的 tunnel,在内核源代码 net/l2tp 中,PPTP 是另外一个,在 drivers/net/pptp.c 中实现。这两个比较复杂,我也不熟悉。更多介绍请看内核文档 Documentation/networking/l2tp.txt