DarkNode

Life, the Universe and Everything

内核隧道的介绍与校园网内的应用

本文发表于:
最后修改于:
分类:network
合计信息量:6.59kb

相关说明

服务器信息:

路由器信息:

隧道基础知识

Linux 内核支持的隧道主要有 IP 隧道、SIT 隧道、GRE 隧道三种,L2TPv3 隧道比较少见,本文将不做介绍。

IP 隧道是一种比较简单的隧道,其原理就是直接在原始的 IP 包之前加入一个新的 IP 报文头指向对端,将原有的整个 IP 包作为新的 IP 包的 Pay­load。对端收到这个 IP 包之后取出 Pay­load 部分进一步处理。

由于存在 IPv4 和 IPv6 两种协议,所以 IP 隧道也就对应地产生了四种类型:

SIT 隧道的功能与原理与 IP 隧道比较接近,这里就姑且把它们归类在一起。GRE 隧道可以视为对 IP 隧道的增强,加入了一些额外的字节以提供 GRE Key 等高级功能,对隧道内传输的报文没有限制,根据外层使用的包的类型可以分为两类:

建立这些隧道需要你拥有能够互相直接 Ping 通的 IP 地址,运营商做了 NAT,没有公网 IP 的用户就没有办法建立一个通往 VPS 的隧道了。由于这些隧道与 IP 地址是绑定的,所以通过 PP­POE 上网,没有固定 IP 的用户会比较麻烦,需要写脚本定时通知远端本次获得的 IP 是什么并创建隧道等等。

创建一个隧道

创建一个用 IPv4 进行封装的隧道需要使用如下命令:

$ ip tun­nel add tun0 mode 隧道类型 re­mote 远端 IPv4 地址 lo­cal 本地 IPv4 地址

比如:

$ ip tun­nel add tun0 mode ipip re­mote 1.2.3.4 lo­cal 6.7.8.9
$ ip tun­nel add tun0 mode sit re­mote 1.2.3.4 lo­cal 6.7.8.9
$ ip tun­nel add tun0 mode gre re­mote 1.2.3.4 lo­cal 6.7.8.9

创建一个用 IPv6 进行封装的隧道需要使用如下命令:

$ ip -6 tun­nel add tun0 mode 隧道类型 re­mote 远端 IPv6 地址 lo­cal 本地 IPv6 地址

比如:

$ ip tun­nel add tun0 mode ipip6 re­mote 2001::1 lo­cal 2400::1
$ ip tun­nel add tun0 mode ip6ip6 re­mote 2001::1 lo­cal 2400::1
$ ip tun­nel add tun0 mode ip6gre re­mote re­mote 2001::1 lo­cal 2400::1

创建隧道的命令需要在本地和远端分别执行,远端执行时注意要互换 IP 地址。

通过隧道互访

创建隧道接口 tun0 之后,我们需要为其分配 IP 地址,需要按照隧道类型分配对应类型的 IP。

实际上隧道不存在服务器和客户端的概念,为了方便讲解,我们约定远端的机器采取尾数为 1 的 IP 地址,本地的机器采取尾数为 2 的 IP 地址。

为内层是 IPv4 包的 ipip 隧道、ipip6 隧道分配 IPv4 地址可以在本地执行:

$ ip addr add 10.24.0.2 peer 10.24.0.1 dev tun0

在远端执行同样的命令,注意互换 IP 地址:

$ ip addr add 10.24.0.1 peer 10.24.0.2 dev tun0

内层 IPv4 使用 peer 选项可以节省添加路由表的步骤,而内层 IPv6 需要手动添加路由表。

为内层是 IPv6 包的 sit 隧道、ip6ip6 隧道分配 IPv6 地址可以在本地执行:

$ ip -6 addr add fe80:abcd::2/128 dev tun0
$ ip -6 route add fe80:abcd::1/128 via fe80:abcd::1/128

在远端执行同样的命令,注意互换 IP 地址:

$ ip -6 addr add fe80:abcd::1/128 dev tun0
$ ip -6 route add fe80:abcd::2/128 via fe80:abcd::1/128

正式建立连接

使用如下命令即可正式建立连接,所有隧道通用:

$ ip link set tun0 up

执行到这一步的时候,你应该可以从本地 Ping 或者 Ping6 远端了。

内层是 IPv4 包的 ipip 隧道、ipip6 隧道可以使用:

$ ping 10.24.0.1

内层是 IPv6 包的 sit 隧道、ip6ip6 隧道可以使用:

$ ping6 fe80:abcd::1

PKU 校内网络实例

为了搭建一个无需支付国际网关费用即可访问所有网站的网络环境,可以使用 IPIP6 隧道,利用学校提供的 IPv6 网络承载 IPv4 流量。

PKU 校内 静态 IPv6 地址 规则如下:

某楼的通过网线直连可以获得的 IPv4 地址为 162.105.105.xx,根据上述规则,该楼的用户可以随意选择 2001:da8:201:1105::开头的任意的某个 IP 作为自己的静态 IPv6 的 IP,注意不要与其他用户已有的 IP 冲突。而 IPv6 网关地址则是 2001:da8:201:1105::1

在本案例中,我选择 2001:da8:201:1105::2048 作为路由器的静态 IPv6 地址,eth0 插外网网线,eht1-4 组成 switch0,IP 段 192.168.1.1/24。另外假设 VPS 的 IPv6 地址是 2400:8500:1301::99

为路由器外网网口添加静态 IPv6 地址可以使用命令:

$ ip -6 addr add 2001:da8:201:1105::2048/64 dev eth0
$ ip -6 route add ::/0 via 2001:da8:201:1105::1

在路由器上创建 IPIP6 隧道并绑定 IP:

$ ip -6 tun­nel add tun0 mode ipip6 re­mote 2400:8500:1301::99 lo­cal 2001:da8:201:1105::2048
$ ip addr add 10.24.0.2 peer 10.24.0.1 dev tun0
$ ip link set tun0 up

在 VPS 上创建 IPIP6 隧道并绑定 IP:

$ ip -6 tun­nel add tun0 mode ipip6 re­mote 2001:da8:201:1105::2048 lo­cal 2400:8500:1301::99
$ ip addr add 10.24.0.1 peer 10.24.0.2 dev tun0
$ ip link set tun0 up

此时 10.24.0.1 与 10.24.0.2 之间已经可以互相 ping 通了。

接下来在路由器上添加路由规则,使路由器上的所有流量从 IPIP6 隧道出去:

$ ip route re­place 0.0.0.0/0 via 10.24.0.1

在 VPS 上添加路由规则,使路由器上的其他 IP 段在 192.168.1.1/24 的设备的数据包的回复通过 IPIP6 隧道回到路由器上:

$ ip route add 192.168.1.0/24 via 10.24.0.2

最后在 VPS 上修复 mss、mtu 等问题并设置 NAT:

$ ipt­a­bles -A FOR­WARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS  --clamp-mss-to-pmtu
$ ipt­a­bles -t nat -A POSTROUT­ING -o eth0 -s 10.24.0.2 -j MAS­QUER­ADE
$ ipt­a­bles -t nat -A POSTROUT­ING -o eth0 -s 192.168.1.0/24 -j MAS­QUER­ADE

至此,无需支付国际网关费用即可自由访问全部网站的网络环境就配置好了。

最后是网络结构拓扑图:

2001:da8:201:1105::2048      2400:8500:1301::99
        ┌────────┐                      ┌─────┐
        │ Router ◆──────────────────────◆ VPS │
        └────◆───┘10.24.0.2    10.24.0.1└─────┘
 192.168.1.1 │                                 
             │                                 
 192.168.1.2 │                                 
        ┌────◆────┐                            
        │ Mac­book │                            
        └─────────┘                            

在路由器上执行的全部命令:

$ ip -6 addr add 2001:da8:201:1105::2048/64 dev eth0
$ ip -6 route add ::/0 via 2001:da8:201:1105::1
$ ip -6 tun­nel add tun0 mode ipip6 re­mote 2400:8500:1301::99 lo­cal 2001:da8:201:1105::2048
$ ip addr add 10.24.0.2 peer 10.24.0.1 dev tun0
$ ip link set tun0 up
$ ip route re­place 0/0 via 10.24.0.1

在 VPS 上执行的全部命令:

$ ip -6 tun­nel add tun0 mode ipip6 re­mote 2001:da8:201:1105::2048 lo­cal 2400:8500:1301::99
$ ip addr add 10.24.0.1 peer 10.24.0.2 dev tun0
$ ip link set tun0 up
$ ip route add 192.168.1.0/24 via 10.24.0.2
$ ipt­a­bles -A FOR­WARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS  --clamp-mss-to-pmtu
$ ipt­a­bles -t nat -A POSTROUT­ING -o eth0 -s 10.24.0.2 -j MAS­QUER­ADE
$ ipt­a­bles -t nat -A POSTROUT­ING -o eth0 -s 192.168.1.0/24 -j MAS­QUER­ADE