歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Unix知識 >> 關於Unix

Linux中IP隧道的分析與建議

**************************************************************** 作者的話: 本文系在閱讀Linux源碼及一些相關資料的基礎上寫成的。 歡迎就文章的各個方面提出建議和批評意見,作者希望更多的交流和探討。 歡迎在保留原文完整性的前提下在網上轉貼,需部 ****************************************************************

作者的話:

本文系在閱讀Linux源碼及一些相關資料的基礎上寫成的。

歡迎就文章的各個方面提出建議和批評意見,作者希望更多的交流和探討。

歡迎在保留原文完整性的前提下在網上轉貼,需部分引用請通知作者。

傳統媒體轉載和引用此文,請務必經過作者同意。

歡迎在實際的應用中使用此文提出的思想,希望同時知會作者。



作者信箱: [email protected]



歡迎來信!!
*****************************************************************

O、

由於網絡的日益普及,網絡的安全成為目前的熱門話題。本文對隧道技術的分析,

就側重安全領域,對利用隧道技術實現虛擬專網提出建議。



為什麼需要IP隧道?沒有接觸過這個概念的人自然提出這樣的疑問。實際上概念

最初的提出很簡單,為了在TCP/IP網絡中傳輸其他協議的數據包。設想IPX協議或

X.25封裝的數據包如何通過Inte.net網進行傳輸,在已經使用多年的橋接技術中是

通過在源協議數據包上再套上一個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中的實現



本人分析的版本是Linux2.0.34(RedHat5.2采用)。



在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/ipv4/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頭,恢復原數據包

是它分內的事,但在它解出數據包(即原完整的協議數據包)後,它把這個包

放入相應的協議接收隊列。這種事可不是一個上層協議干的,這是網絡設備中斷

接收程序的義務。看到了,在這點上,它好象到了數據鏈路層。

是不是有點亂,隧道機制就是這樣,你有沒有更好的辦法?









三、

為實現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、准備工作:建網安裝系統完成配置等等

2、隧道的兩端分別向對方發送自己的公開密碼和設備號

3、如有必要,產生序列密碼,後加密簽名傳給對方

4、正常通信,----放心,你的數據已經很保險了。



在一個VPN的隧道中,一個封包的格式應如圖四所示。



                    /  +-----------------+

                    |  |    封包IP頭     | 

           封包頭   |  +-----------------+

                    |  |   封包協議頭    |

                    \  +-----------------+

                    /  |                 |   

                    |  |    原協議頭     |

                    |  |       及        |

          封包數據  |  |   原協議數據    | 

                    |  .    (密文)     .

                    |  .                 .

                    |  |                 |

                    \  +-----------------+

            



                    圖四.      VPN封包結構







你的幾種使用方法。

事情往往不能兩全其美,你在安全強度和通信速度上必須作出選擇,

(不然你就需要在安全強度和Money的耗費中做選擇。)

使用這樣的協議,根據你的需求不同,你可有不同的使用方法,下面列舉

一些:

0、跨Internet的公司多個內部網之間進行通信,保密性並不重要

    直接使用原框架機制,無任何加密措施

    這樣速度快、效率高,公司也不用申請多個IP地址,方便可行

1、一般性的商業應用,具有保密要求

    利用事先產生的序列密碼,每次對原數據包加密

    安全度提高了,是一種十分實用的方法。只要強度足夠,一般很難破譯

    速度快

2、密碼不變的方式你認為不夠安全

    你可以自己實現一種密碼傳送方法,每隔一段時間更換一次密碼。

    其中一些握手關系需要完善,有興趣的歡迎探討。

    如果發展成熟,此法相信很有前途。

4、高度機密領域

    敬請使用一次一密,並進行每次簽名。

    每次產生新密鑰和簽名十分費時,在目前我國Internet網絡的速度下

    幾乎不可行。

    但相信有此需要的部門也能夠設法提高其網絡帶寬,讓網絡狀況適合

    這種應用。



另外,當然還可以就加密強度自身作出選擇,比如選擇128位,還是512位、1024位









四、

待完善



主要牽涉到隧道的管理,在封包的傳送過程中如果出現錯誤是十分正常的,

當一台路由器檢測到錯誤時,它會發送一個ICMP包給隧道的發送端,但遺憾的是

ICMP返回的數據除了IP頭外,只含8個字節的上層協議信息。只憑這個難以對

ICMP信息作出反應,因此,在隧道端保留一些狀態信息是必須的。這些信息

主要包括:

隧道的另一端的可達性

隧道的擁塞狀況

隧道的MTU

    同時所發送的封包信息也是需要保留的,舉例說,當一個路由不可達信息

到來時,封包的發送者要能夠找出所封裝的數據來自何方,並發送相應的ICMP包。



強調一點,MTU的更新對隧道來將很重要,因為一個靈活的隧道的下一級設備是

不定的,同時一些數據包本身也要求更改MTU。


所有這些,在Linux中的處理都不夠或根本沒有處理。大家努力呀!

Copyright © Linux教程網 All Rights Reserved