新版linux核心對nat的修改

2021-07-05 21:35:56 字數 1821 閱讀 7104

linux的nat是基於match的,即在滿足一系列條件的前提下執行snat或者dnat,因此要求也就比較寬鬆,唯一的約束就是路由,即路由動作發生的時候,必須是基於最終的目標ip位址,因此dnat必須發生在路由之前(對於本機發出的資料報,則在路由之後,然後重新路由),如下圖所示

netfilter

linux的協議棧僅僅實現了基本的協議操作,對應tcp/ip標準,linux的協議棧僅僅實現了乙個最小集。其餘的所有擴充套件幾乎(並非所有!還有一部分由net schedule實現)均由netfilter來實現,包括:ip firewall,ip nat,ipsec,ipvs等。

ip_conntrack  

ip_conntrack是nat實現的重中之重,linux的nat完全依賴ip_conntrack,依附於ip_conntrack之上。

基本資料結構:

值得注意的是,兩個方向的五元組節點在confirm之後統一處在乙個雜湊表中,並不區別對待,只要使用乙個五元組作為鍵查詢到不管哪個方向的五元組節點,都可以找到ip_conntrack結構體本身。五元組節點除了包含五元組資訊之外,還包含方向資訊。

nat如何依附於ip_conntrack之上的呢?如上圖所示,nat修改了ip_conntrack中的反方向的五元組,對正方向的五元組並沒有影響,正是這個特點使得在linux實現nat的時候可以使用一種非常巧妙的方法。

nat的流程如下所示:

注意:由於僅僅乙個流的第乙個包會建立ip_conntrack結構體,因此也是第乙個包會去匹配你用ipptables配置的nat規則,這是個侷限性

在2.6的早期核心中,nat的資料,包括要轉換到的ip位址等資料都是儲存在ct的extension中的,叫做ip_nat_info,而該info可以從ct中取出來,在到達nf_nat_fn的時候執行nat的時候使用裡面的ip_nat_info_manip來做nat的依據。但是在後期的版本中,使用了一種更加高效得方式,需要轉換到的ip位址不再儲存在ip_nat_info中,而是直接使用上述流程圖中的計算方法得到,即獲取反向五元組,取逆,按結果執行。這麼做是有依據的,因為在nat規則匹配成功後,會直接修改掉反方向五元組的tuple,因為nat規則匹配成功肯定是針對正方向五元組的,畢竟只有第乙個包才會去匹配nat規則,無來怎能有回呢?所以根據nat規則修改的既然是反方向五元組,那麼標準取逆後得到就是nat後的正方向五元組了,在這個過程中,正方向的五元組一直儲存不變!對於反方向回來的包,它的反向就是正方向,由於正方向從來沒有被改過,取逆後即成為原始的反方向的五元組,返回包的五元組得以還原!正因為如此,linux nat對方向才如此敏感:匹配規則的正方向的資料報,修改的是反方向的五元組!注意正向,正方向以及反向,反方向並不是同乙個意思,正向和反向是針對當前的方向來講的,正方向和反方向是針對資料流的發起方到接收方的方向來講的。

可以從這個實現看出linux核心的發展,在2.6的早期版本中,實際上在nat規則匹配成功後也是去修改反方向五元組,但是那時怎麼就不是通過反向五元組取逆來作為位址轉換依據的呢?實際上那時一定可以這麼做!事實證明,linux核心中布滿的逐步逐步被認識被發現的技巧。這也正體現了網路社群開發的「90%特性」,即甚至90%的可用性即可,不要求100%的完美。

對linux做NAT的解釋

我對linux做nat的解釋 一台安裝了linux8.0的機器上配置兩塊網絡卡,第一塊為eth1,ip位址為218.11.11.11,用來連線外網。第二塊為eth0,ip位址為192.168.0.1,用來連線內網,並做內網的閘道器。iptables的配置如下 1 modprobe ip tables...

新版Linux核心新增系統呼叫的方法

在linux 3.2.11 kernel下建立mysyscall.c檔案,內容如下 include asmlinkage long sys mysyscall void 在linux 3.2.11 kernel makefile中加入 obj y mysyscall.o 在linux 3.2.11 ...

新版Linux核心新增系統呼叫的方法

在linux 3.2.11 kernel下建立mysyscall.c檔案,內容如下 include asmlinkage long sys mysyscall void 在linux 3.2.11 kernel makefile中加入 obj y mysyscall.o 在linux 3.2.11 ...