Linux 隧道
{Back to Index}
Table of Contents
1 隧道技术
所谓隧道就是把下一层(比如 IPv4 层)的包封装到上一层(比如 SSH, HTTP )或者同一层(比如 IPv6 层)的协议中进行传输,从而实现网络之间的穿透。 很明显,这种实现有个前提,那就是,发送端和接收端 必须各有一个解析这种包的程序或者内核模块才能实现正常通信。
由于发送端和接收端都需要知道对端的 IP 地址,如果在隧道的路径上有网络地址转换(NAT),那么隧道就不能正常的工作。
2 SIT (Simple Internet Transition) 1
SIT 是 IPv6 over IPv4 的隧道,可以为没有 IPv6 接入的机器提供 Tunnel Broker 服务。
ip tunnel add ${interface_name} mode sit \ local ${local_endpoint_address} \ remote ${remote_endpoint_address}
3 IPIP (IP in IP) 2
IPIP 是把 IP 层封装到 IP 层的一个 tunnel ,看起来似乎是浪费,实则不然。它的作用相当于一个基于 IP 层的网桥。 我们知道,普通的网桥是基于 mac 层的,不需要 IP ,而IPIP 则是通过两端的路由实现一个隧道,把两个本来不通的网络通过点对点的方式连接起来。
IPIP 是最简单的隧道,头部开销最小,但是只能封装 IPv4 单播数据,因此 不支持 OSPF,RIP 和广播。 同一对节点之间 只能建立一条 IPIP 隧道。GRE 和它类似,但功能更强大,支持广播, 因此可以取代 IPIP 。
3.1 实验
3.1.1 网络拓扑
Figure 1: 实验网络拓扑(ipip)
3.1.2 配置
Instance 1:
ip tunnel add ipiptun mode ipip local 172.31.13.79 remote 172.31.11.150 ip l set ipiptun up ip a add 192.168.1.80/24 dev ipiptun ip a add 192.168.1.79/24 dev eth1 ip r del 192.168.1.0/24 dev eth1
[root@ip-172-31-13-79 ec2-user]# ip r default via 172.31.0.1 dev eth0 169.254.169.254 dev eth0 172.31.0.0/20 dev eth0 proto kernel scope link src 172.31.13.79 172.31.0.0/20 dev eth1 proto kernel scope link src 172.31.9.218 192.168.1.0/24 dev ipiptun proto kernel scope link src 192.168.1.80
3.1.3 抓包分析
分别在 eth0
和 ipiptun
上抓取数据包(eth0.pcap, ipiptun.pcap)。
Figure 2: Echo Request (ipiptun)
Figure 3: Echo Request (eth0)
Figure 4: Echo Reply (ipiptun)
Figure 5: Echo Reply (eth0)
4 GRE 3 , 4
GRE 规定了如何用一种网络协议去封装另一种网络协议的方法。GRE 隧道由两端的源 IP 地址和目的 IP 地址来定义, 允许用户使用 IP 包封装 IP,IPX,AppleTalk 包,并支持全部的路由协议(如 RIP2,OSPF 等)。
不同于 IPIP ,同一对节点之间可以设置 64K 条隧道。5
4.1 实验
4.1.1 网络拓扑
Figure 6: 实验网络拓扑(GRE)
4.1.2 配置
在 instance 1 上创建隧道设备
ip tunnel add gretun mode gre local 172.31.6.121 ttl 64 remote 172.31.2.240 dev eth0
启用隧道设备
ip l set gretun up
配置 IP
ip addr add 192.168.1.122/24 dev gretun
添加路由
上一步默认会建立一条路由,如果没有则需手动添加
ip r add 192.168.1.0/24 dev gretun
路由信息:
[ec2-user@ip-172-31-6-121 ~]$ ip r default via 172.31.0.1 dev eth0 169.254.169.254 dev eth0 172.31.0.0/20 dev eth0 proto kernel scope link src 172.31.6.121 192.168.1.0/24 dev gretun proto kernel scope link src 192.168.1.122
在 instance 2 上进行对等的配置:
ip tunnel add gretun mode gre local 172.31.2.240 ttl 64 remote 172.31.6.121 dev eth0 ip l set gretun up ip addr add 192.168.1.0/24 dev gretun
4.1.3 抓包分析
在 instance 1 上 ping instance 2 ,分别在 eth0
和 gretun
上抓包:(eth0.pcap, gretun.pcap)
tcpdump -i eth0 -w eth0.pcap 'proto gre' tcpdump -i gretun -w gretun.pcap 'icmp'
Figure 7: Echo Request (gretun)
Figure 8: Echo Request (eth0)
Figure 9: Echo Reply (gretun)
Figure 10: Echo Reply (eth0)
4.1.3.1 内核的处理过程 6
可以看到,发送过程是很简单的,因为 instance 1 上配置了一条路由规则,凡是发往 192.168.1.0/24
网络的包都要经过 gretun
这个设备,
gretun
的驱动程序会在内核中对数据包构造一个新的头,并把对应的外部 IP 地址填进去,最后通过 local 对应的网卡(eth0)发送出去。
当 instance 2 收到从 instance 1 过来的数据包时,它暂时还不知道这个是 GRE 的包,
它首先会把它当作普通的 IP 包处理。因为外部的 IP 头的目的地址是该主机的地址,所以它会接收这个包,并交给上层。
到了 IP 层之后才发现这个包不是 TCP/UDP ,而是 GRE (因为 GRE 定义了一个新的 IP proto 即 IPPROTO_GRE
),
这时内核会把数据转交给 GRE 模块处理。
GRE 模块所做的工作是:剥去外层 IP 头,把“新包”重新交给 IP 栈去处理,像接收到普通 IP 包一样。 ”新包“处理和其它普通的 IP 包就没有什么两样了:根据 IP 头中目的地址转发给相应的网卡。