歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Linux的NAT實現淺談

Linux的NAT實現淺談

日期:2017/2/28 15:48:21   编辑:Linux教程

NAT實際上就是一個代理,代理NAT內部的所有機器,NAT的分類就是按照“如何代理”來講的,不管是基於連接的NAT實現,還是基於包的NAT實現,都要處理好一個映射關系,那就是轉換後的包的返回包如何轉換回原始的。

Linux的NAT是對稱NAT,而不是錐形NAT,雖然很多時候Linux的NAT看起來更像是一個錐形NAT。
只需要明白Linux實現NAT的本質,即使不明白NAT的分類也無所謂。Linux實現NAT的原則很簡單:
用最小的代價保證一個tuple五元組在轉換前的五元組和轉換後的五元組中的唯一性。
注意,這兩個五元組是分開存放的,它們在hash鏈表層面並沒有任何關聯。實際上這是ip_conntrack的實質,ip_conntrack在存放連接的時候是按照“兩個方向”分別存放的,www.linuxidc.com 因此需要一個五元組在兩個方向的hash表中是唯一的才可以。有人說Linux可以實現錐形NAT,然而這個錐形NAT實際上是很脆弱的,考慮以下的連接:
(PC:1234->SERVER:80)
因此NAT上會出現下面的tuple(五元組):
正方向:(PC1:1234->SERVER:80)
反方向:(SERVER:80->NAT:1234)
如果此時PC2同樣使用端口1234連接了SERVER2的80,那麼NAT上將會出現新的兩個tuple:
正方向:(PC2:1234->SERVER2:80)
反方向:(SERVER2:80->NAT:1234)
此時如果PC1也想用1234端口連接SERVER2的80,如下:
正方向:(PC1:1234->SERVER2:80)
反方向:
為何是一個“?”呢?如果Linux NAT是錐形的NAT,那麼根據錐形的含義,NAT需要將PC2的源組轉換為(NAT:1234->SERVER2:80),這樣的話,反方向的tuple就是(SERVER2:80->NAT:1234)了,和PC2的反方向tuple相沖突,這是不可以的,Linux自動將其源端口作了改變,轉換為(NAT:不是1234->SERVER2:80),進而反方向tuple成了(SERVER2:80->NAT:不是1234)了,因此解決了唯一性問題,在“第三者的幫助下”,Linux被動成了對稱NAT...
至於錐形NAT中的Port Restricted Cone,Restricted Cone,Full Cone這三類錐子,就不用討論了,這三類錐子的目的在於限制反向流量的穿透性,一種分類上的清晰化會使策略實現起來更加方便,之所以將NAT分為錐形和對稱的,並且錐形的又分為三個類別,這完全是為了實現RFC3489,而這個RFC是打洞技術的基石,也就是說,分類是為了描述打洞實現時更加方便簡潔。反過來,NAT之所以可以被穿越(成功打洞),正是在於描述NAT本身的RFC沒有規定其實現方式,也沒有規定“不讓穿越”,Linux只是按照RFC保證了NAT的結果,這也是實現之一而不是唯一的實現。
本文最開始談到,NAT需要解決一個映射問題,而一個包攜帶的所有識別信息的交集就是五元組,因此NAT可以起到連接限制的作用,NAT設備能開放的所有連接數量由它所持有的公網IP地址以及可用的端口數量決定,比如下面的規則:
iptables -t nat -A POSTROUTING -p --dport 80 -j SNAT --to-source X.X.X.X:80
那麼整個NAT後方,同時則只有一台機器的一個socket能連接到同一個目標的80端口,否則反方向的tuple就會沖突。可以通過/proc/net/stat/ip_conntrack文件的insert_failed那一列看到所有後續的連接反方向tuple由於和既有的反方向tuple相沖突而計數器遞增。

Linux不區分以上這些由RFC3489而引發的XX,甚至都不區分錐形NAT和對稱NAT,只保證NAT的結果即可。

Copyright © Linux教程網 All Rights Reserved