作者 Wing
摘要:由于网络的日益普及网络的安全成为目前的热门话题本文对隧道技术的分析就侧重安全领域对利用隧道技术实现虚拟专网提出建议
作者的话
作者信箱: x 欢迎来信!!
**********************************************************************
由于网络的日益普及网络的安全成为目前的热门话题本文对隧道技术的分析就侧重安全领域对利用隧道技术实现虚拟专网提出建议
为什么需要IP隧道?没有接触过这个概念的人自然提出这样的疑问实际上概念最初的提出很简单为了在TCP/IP网络中传输其他协议的数据包设想IPX协议或 X封装的数据包如何通过Internet网进行传输在已经使用多年的桥接技术中是通过在源协议数据包上再套上一个IP协议头来实现形成的IP数据包通过Internet后卸去IP头还原成源协议数据包传送给目的站点对源协议数据来说就如被IP带着过了一条隧道这种技术在业余无线网络(Amateur Packet Radio network应该怎么翻请告诉我)得到了最广泛的应用
利用IP隧道来传送的协议包也包括IP数据包本文主要分析的IPIP封包就是如此从字面来理解IPIP就对了就是把一个IP数据包又套在一个IP包里为什么要这么做呢?多此一举嘛其实不然见过一些应用就会明白移动IP(MobileIP)和IP多点广播IPMulticast)是两个通常的例子目前IP隧道技术在构筑虚拟专网( Virtual Private Network)中也显示出极大的魅力本文也将对利用IP隧道技术构筑VPN做简单设想
背景隧道的多种理解和实现
Internet的研究者多年前就感到需要在网络中建立隧道最初的理解是在网络中建立一条固定的路径以绕过一些可能失效的网关可以说隧道就是一条特定的路径这样的隧道是通过IP报头中的源路由选项来实现的在目前看来这个方法的缺 陷十分明显要设置源路由选项就必须知道数据包要经过的确切路径而且目前多数路由实现中都不支持源路由
另一个实现隧道的机制是开发一种新的IP选项用来表明源数据包的信息原IP头可能成为此选项的一部分这种隧道的意义与我们所说的隧道已十分接近但它的不足在于要对目前IP选项的实现和处理做较大的修改也缺乏灵活性
最后常用的一种实现方法是开发一种新的IP封包协议仍然套用当前的IP头格通过IP封包不须指明网络路径封包就能透明地到达目的地也可以通过封包 空间把未直接连接的机器绑在一起从而创建虚拟网络这种方法易行可靠可扩展性强Linux采用了这一方法这也是目前我们所理解的隧道思想
一封包协议的结构和实现
封包协议的实现原理十分简单先看看通过隧道传送的数据报在网络中如何流动如图一
为了叙述简便我把在隧道中传送的IP数据包称为封包
/ 子网A / 子网C
/ /
| | | |
| & | | |
| + +++++ | | ***** |
| +++++ + | | * * |
| + | | ***** * |
+ / * * /
++> # * **>(#) * ***> # ++++
/ * * / +
| * * | | + |
| * * | | + |
| ***** * | | +++++++ |
| ***** | | V |
| | | & |
/ /
子网B / 子网D /
++++++ 原数据报
****** 封装后的数据包(封包)
# 封装/解封
& 用户主机
图一 封包协议实现模型
看图中的设备 #分别处于隧道的两端分别起打包(封装)和解包(解封)的作用在整个数据包的传送路径中除了隧道两端的 # 设备其他网关把数据包看成一个普通的IP包进行转发
设备 # 就是一个封包基于的两个实现部件封装部件和解封部件封装和解封部件(设备)都应当同时属于两个子网封装部件对接收到的数据报加上封包头 然后以解封部件地址作为目的地址转发出去而解封部件则在收到封包后还原原数据报转发到目的子网
隧道的源端(封装部件)对进入隧道的数据包进行封装形成封包一个完整的封包如图二所示
/ ++
| | 封包IP头 |
封包头 | ++
| | 封包协议头 |
++
/ | 原协议头 |
| ++
| | |
原数据报 | | 原协议数据 |
|
|
| | |
++
图二 封包结构
二Linux中的实现
本人分析的版本是Linux(RedHat采用)
在Linux中隧道的实现主要基于两个文件new_tunnelc和ipipc同时Linux定义了一种新的协议类型IPIP(IPPROTO_IPIP)与上面所说封包类型类似
基本思路
在Linux中IP Tunnel的实现也分为两个部件封装部件和解封部件分别司职发送和接收但这两个部分是在不同的层次以不同的方式实现的封装部件是在数据链路层以虚设备的方式实现所有源代码见
/usr/src/linux/drivers/net/new_tunnelc
为实现封装Linux实现一个称为tunl的网络设备(类似loopback设备)此设备具有其他网络设备共有的特征对于使用此设备的上层应用来说对这些网络设备 不加区分调用及处理方法当然也完全一样
tunnel_init()和tunnel_xmit()是new_tunnelc中的两个主要过程
tunnel_init()初始化与设备tunl相关的device结构
而tunnel_xmit()在从tunl设备发送数据时被调用tunl设备作为实现IP隧道技术的封装部分在此过程中完成对相应的数据报进行封装所需的全部操作形成IPIP类型的IP包并重新转发此数据包(ip_forward())
解封部件在IP的上层实现系统把它作为一个虚的传输层(实际上与传输层毫无关系)具体处理见文件
/usr/src/linux/net/ipv/ipipc
我们知道每一个IP数据包均交由ip_rcv函数处理在进行一些必要的判断后ip_rcv对于发送给本机的数据包将交给上层处理程序对于IPIP包来说其处理函数是ipip_rcv(就如TCP包的处理函数是tcp_rcv一样IP层不加区分)也就是说 当一个目的地址为本机的封包到达后ip_rcv函数进行一些基本检查并除去IP头然后交由ipip_rcv解封
ipip_rcv所做的工作就是去掉封包头还原数据包然后把还原后的数据包放入相应的接收队列(netif_rx())
从以上IP Tunnel实现的思想来看思路十分清晰但由于IP Tunnel的特殊性其实现的层次并不单纯实际上它的封装和解封部件不能简单地象上面所说的那样分层tunl设备虽应算进链路层但其发送程序中做了更多的工作如制作IPIP头及新的IP头(这些一般认为是传输层或网络层的工作)调用ip_forward转发新包也不是一个网络设备应当做的事可以说tunl借网络设备之名一把抓干了不少工作真是高效而解封部件宏观上看在网络层之上解出IPIP头恢复原
数据包是它分内的事