作者
Wing
摘要:由於網絡的日益普及
網絡的安全成為目前的熱門話題
本文對隧道技術的分析
就側重安全領域
對利用隧道技術實現虛擬專網提出建議
作者的話
作者信箱: x 歡迎來信!!
**********************************************************************
由於網絡的日益普及
網絡的安全成為目前的熱門話題
本文對隧道技術的分析
就側重安全領域
對利用隧道技術實現虛擬專網提出建議
為什麼需要IP隧道?沒有接觸過這個概念的人自然提出這樣的疑問
實際上概念最初的提出很簡單
為了在TCP/IP網絡中傳輸其他協議的數據包
設想IPX協議或 X
封裝的數據包如何通過Internet網進行傳輸
在已經使用多年的橋接技術中是通過在源協議數據包上再套上一個IP協議頭來實現
形成的IP數據包通過Internet後卸去IP頭
還原成源協議數據包
傳送給目的站點
對源協議數據來說
就如被IP帶著過了一條隧道
這種技術在業余無線網絡(Amateur Packet Radio network
應該怎麼翻
請告訴我)得到了最廣泛的應用
利用IP隧道來傳送的協議包也包括IP數據包
本文主要分析的IPIP封包就是如此
從字面來理解IPIP就對了
就是把一個IP數據包又套在一個IP包裡
為什麼要這麼做呢?多此一舉嘛
其實不然
見過一些應用就會明白
移動IP(Mobile
IP)和IP多點廣播IP
Multicast)是兩個通常的例子
目前
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_tunnel
c和ipip
c同時Linux定義了一種新的協議類型
IPIP(IPPROTO_IPIP)
與上面所說封包類型類似
基本思路
在Linux中IP Tunnel的實現也分為兩個部件
封裝部件和解封部件
分別司職發送和接收
但這兩個部分是在不同的層次以不同的方式實現的
封裝部件是在數據鏈路層以虛設備的方式實現
所有源代碼見
/usr/src/linux/drivers/net/new_tunnel
c
為實現封裝
Linux實現一個稱為tunl的網絡設備(類似loopback設備)
此設備具有其他網絡設備共有的特征
對於使用此設備的上層應用來說
對這些網絡設備 不加區分
調用及處理方法當然也完全一樣
tunnel_init()和tunnel_xmit()是new_tunnel
c中的兩個主要過程
tunnel_init()初始化與設備tunl相關的device結構
而tunnel_xmit()在從tunl設備發送數據時被調用
tunl設備作為實現IP隧道技術的封裝部分
在此過程中完成對相應的數據報進行封裝所需的全部操作
形成IPIP類型的IP包
並重新轉發此數據包(ip_forward())
解封部件在IP的上層實現
系統把它作為一個虛的傳輸層(實際上與傳輸層毫無關系)
具體處理見文件
/usr/src/linux/net/ipv
/ipip
c
我們知道
每一個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頭
恢復原
數據包是它分內的事
From:http://tw.wingwit.com/Article/program/Oracle/201311/18700.html