Linux中IP隧道的分析与建议( 三 )



一个目的地址为本机的封包到达后 , ip_rcv函数进行一些基本检查并除去IP头 , 然后

交由ipip_rcv解封 。

ipip_rcv所做的工作就是去掉封包头 , 还原数据包 , 然后把还原后的数据包放入相应的

接收队列(netif_rx()) 。



从以上IP;Tunnel实现的思想来看 , 思路十分清晰 , 但由于IP;Tunnel的特殊性 , 其

实现的层次并不单纯 。实际上 , 它的封装和解封部件不能简单地象上面所说的那样

分层 。tunl设备虽应算进链路层 , 但其发送程序中做了更多的工作 , 如制作IPIP头

及新的IP头(这些一般认为是传输层或网络层的工作) , 调用ip_forward转发新包

也不是一个网络设备应当做的事 。可以说 , tunl借网络设备之名 , 一把抓干了不少

工作 , 真是‘高效’ 。而解封部件宏观上看在网络层之上 , 解出IPIP头 , 恢复原数据包

是它分内的事 , 但在它解出数据包(即原完整的协议数据包)后 , 它把这个包

放入相应的协议接收队列 。这种事可不是一个上层协议干的 , 这是网络设备中断

接收程序的义务 。看到了 , 在这点上 , 它好象到了数据链路层 。

是不是有点乱 , 隧道机制就是这样 , 你有没有更好的办法?









三、

为实现VPN的扩展



实际上Linux只为实现隧道机制提供了一个框架 , 图二中的封包协议头在

Linux中被忽略了 , 也就是说 , 封包头只含封包IP头 , 其后紧跟原IP数据包 。

这样的结构用于传输公开数据没有关系 , 但对于一个VPN来说 , 安全保密是

不可缺少的重要功能 。我们希望通过隧道的数据可靠且不可窃取和冒充的 ,

那么 , 加密和认证就必不可少 。

为实现这一构想 , 设计以下封包协议头:



0;;;;4;;;;;8;;16;;;24;;31;

----- ----- ----------- ------------------------

|;ver;|type;|;;;hlen;;;;|;;;;;;OldPacketLen;;;;;;|

----------------------- ------------------------

|DeviceID;;;;;;;|;;;;;;;EncapID;;|

----------------------- ------------------------

|;Flags;|;;;;;;;CheckSum;|

------------------------------------------------

|;IPIP;Options(;If;any;);|

------------------------------------------------

.;;;;;;|;padding;|

..

------------------------------------------------



图三、;IPIP头设想图



ver:;;版本号 , 利于扩展

type: 用于建立不同目的的隧道(可能处理上有差别)

OldPacketLen:;;进入隧道的原数据包长度

DeviceID: 对数据包进行封装的设备标识

EncapID: 此封包的ID号

Flags:;标志位 , 共16位 , 初步定义如下:

0 保留

1 有否加密

2 有否做摘要

3 有否签名

4 保留

5 有否传送消息密钥

6 消息密钥有否加密

7 消息密钥是否需保留

8-15 保留



CheckSum: 头校验

IPIP;Options:;;用来传送一些必要的数据 , 比如消息密钥、签名等

格式:; -------------------------------------

|;类型;|;长度;|;数据;...;;;;;;|

-------------------------------------



好了 , 有了这个东西 , 我们就可以扩展Linux;IP;Tunnel为我们的VPN服务了 。

首先 , 改写new_tunnel.c和ipip.c两个文件 , 加入对IPIP头的处理 。



接着 , 我们要实现一种密钥的管理和传送机制 。

当然 , 对称密钥是必需的 , 而对IP数据包加密要使用序列密码 。从全体考虑 ,

我们可以提出建立VPN的逻辑步骤;

1、准备工作:建网安装系统完成配置等等

推荐阅读