|簡體中文

比思論壇

 找回密碼
 按這成為會員
搜索



查看: 711|回復: 1
打印 上一主題 下一主題

Linux的NAT实现浅谈

[複製鏈接]

989

主題

1

好友

5296

積分

教授

Rank: 8Rank: 8

  • TA的每日心情

    2024-11-3 15:50
  • 簽到天數: 1258 天

    [LV.10]以壇為家III

    推廣值
    2
    貢獻值
    378
    金錢
    1528
    威望
    5296
    主題
    989

    回文勇士 文明人 中學生 高中生 簽到勳章 簽到達人 男生勳章 大學生 文章勇士 附件高人 附件達人 文章達人 教授

    樓主
    發表於 2012-9-16 17:27:25
        NAT实际上就是一个代理,代理NAT内部的所有机器,NAT的分类就是按照“如何代理”来讲的,不管是基于连接的NAT实现,还是基于包的NAT实现,都要处理好一个映射关系,那就是转换后的包的返回包如何转换回原始的。
       
        Linux的NAT是对称NAT,而不是锥形NAT,虽然很多时候Linux的NAT看起来更像是一个锥形NAT.
       
        只需要明白Linux实现NAT的本质,即使不明白NAT的分类也无所谓。Linux实现NAT的原则很简单:
       
        用最小的代价保证一个tuple五元组在转换前的五元组和转换后的五元组中的唯一性。
       
        注意,这两个五元组是分开存放的,它们在hash链表层面并没有任何关联。实际上这是ip_conntrack的实质,ip_conntrack在存放连接的时候是按照“两个方向”分别存放的,因此需要一个五元组在两个方向的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的结果即可。
    重要聲明:本論壇是以即時上載留言的方式運作,比思論壇對所有留言的真實性、完整性及立場等,不負任何法律責任。而一切留言之言論只代表留言者個人意見,並非本網站之立場,讀者及用戶不應信賴內容,並應自行判斷內容之真實性。於有關情形下,讀者及用戶應尋求專業意見(如涉及醫療、法律或投資等問題)。 由於本論壇受到「即時上載留言」運作方式所規限,故不能完全監察所有留言,若讀者及用戶發現有留言出現問題,請聯絡我們比思論壇有權刪除任何留言及拒絕任何人士上載留言 (刪除前或不會作事先警告及通知 ),同時亦有不刪除留言的權利,如有任何爭議,管理員擁有最終的詮釋權。用戶切勿撰寫粗言穢語、誹謗、渲染色情暴力或人身攻擊的言論,敬請自律。本網站保留一切法律權利。

    手機版| 廣告聯繫

    GMT+8, 2024-11-16 11:55 , Processed in 0.041131 second(s), 26 queries , Gzip On.

    Powered by Discuz! X2.5

    © 2001-2012 Comsenz Inc.

    回頂部