天天看點

又一個Linux的雙向stateless NAT

       如果按照上述的思路來實作nat route,根本不用policy routing,不需要配置ip rule,不需要配置兩條規則,它的流程圖如下,代碼也比較好修改:

又一個Linux的雙向stateless NAT

可以看出,這個實作使用了遞歸路由查詢這個Linux根本就沒有實作的東西。是以需要修改路由插入的部分代碼,而我使用了幾個flag來識别該條路由是做NAT用的,由于是stateless的雙向NAT,是以當你插入一條NAT路由的時候,另外一個方向的就必須自動生成,比如你插入了一條以下的路由:

ip route add dnat x via y 

訓示所有的目标是x的都要轉換成y,那麼以下的路由必須自動生成:

ip route add snat y via x

訓示所有源位址為y的都要轉換為x。當然以下的這一條不應該手工配置,應該用auto标号指名它是自動生成的。

       以上的需要說明是snat,原則上snat是在路由之後進行的,否則可能會做無用功,那流程圖為何在路由前snat呢?這是為了最小化查詢,否則也會做很多無用的查詢,将要對所有的資料包都進行是否需要snat的查詢,這裡用到的一個技巧就是路由查詢是基于最長字首比對的,如果有需要snat的,那麼肯定會有一條明細的32位字首的snat路由,如果沒有,那就說明沒有需要snat的。當然上面的流程圖還可以優化,因為我們認識到,由于是雙向的nat,那麼隻要有一個dnat,就會有一個snat,反過來也一樣,都是成對出現的,基于這點是否能做點優化呢?

       提到了遞歸查詢,不得不多說一點,既然已經引入了SNAT,DNAT标志,那麼能否再引入一個Recursion标志用于訓示正常的遞歸路由呢?我覺得是可以的,這樣實作的遞歸路由更加簡單了,一切都在插入時決定,由于NAT是遞歸的一種,那麼可以如下定義:

#define RTN_RECU  RTN_SNAT|RTN_DNAT|RTN_XXX

遞歸路由的插入算法流程如下:

又一個Linux的雙向stateless NAT

2.4核心還在的nat route如今不在了,想實作一個還要重新編譯核心,不過還好,還是實作了!這種nat route不需要Netfilter支援,不需要在核心中引入其它的map,在非路由查找層面不需要對每一個資料包進行比對,完全是一條路由表項,可以借助于核心中的各種路由查找算法來優化。不過Cisco的官方CCIE教程中說,使用遞歸路由查找需要權衡,并且明确指名,遞歸查詢無疑會消耗更多的CPU!

       然而這個基于遞歸路由查詢實作的NAT是多麼的簡單又多麼的對稱,雖然将NAT塞入路由表比較有争議,但是試試看之後,結果還是不錯的。Linux本來就是逐漸試出來的,根本就沒有什麼背後的哲學,和學院派的BSD相比,Linux的特點和優勢不就是不拘一格麼?

 本文轉自 dog250 51CTO部落格,原文連結:http://blog.51cto.com/dog250/1268862

繼續閱讀