Linux對稱NAT的UDP穿越

來源:互聯網
上載者:User

 和同事討論UDP打洞技術,後做了一個簡單的實驗,由於Windows上設定NAT以及察看其原理太麻煩或者根本就不可能,於是還是使用Linux做了實驗,發現基於Linux ip_conntrack這種對稱NAT也能很簡單的實現UDP穿越,實驗很簡單,並且這種UDP穿越還不需要公網伺服器的協助(因為它們對於對稱NAT或者基於串連的NAT根本幫不上什麼忙),很實用。在展示實驗之前,首先要明白以下的知識點。
 1.Linux的NAT是基於ip_conntrack的  www.2cto.com  這一點說明僅僅針對五元組決定的一個串連的第一個資料包進行NAT規則的尋找和匹配並存入ip_conntrack結構體,後續的包自動應用ip_conntrack結構體中的NAT資訊進行NAT。由於五元組標示了一個串連,因此:1).即使是同一個內網主機發起串連,最終很大程度上也不一定能被轉換成同一個(IP地址,協議連接埠)對2).目的地址不同,就不是同一個串連,因此絕不可能做到像cone NAT那樣的偷梁換柱的效果
 2.Linux目前還沒有實現cone NAT的模組Linux的NAT是處於Netfilter模組中的,標準協議棧中沒有任何相關支援,那麼只要Netfilter不支援cone NAT,Linux NAT就別指望能被常規方式打洞。3.Linux的NAT儘力不改變串連的源連接埠Linux的NAT是通過iptables工具配置的,對於隱藏內網主機這種類型的NAT是iptables的SNAT實現的,如果你man iptables將會發現:
 --to-source [ipaddr[-ipaddr]][:port[-port]]    which can specify a single new source IP address, an inclusive range of IP addresses, and optionally, a port range (which is only  valid  if  the  rule  also specifies  -p tcp or -p udp).  If no port range is specified, then source ports below 512 will be mapped to other ports below 512: those between 512 and 1023 inclusive will be mapped to ports below 1024, and other ports will be mapped to 1024 or above. Where possible, no port alteration will occur.  www.2cto.com  
 注意最後一句,Linux儘力不改變串連的源連接埠,除非和另一個tuple相衝突,我們知道一個tuple就是一個五元組。        這一點正是給了我們一點啟示,那就是可以通過嘗試不同連接埠,直到找到沒有被改變源連接埠的那次串連。而印證這一點也很容易,那就是打洞成功。這也從反方面說明沒有必要存在外部伺服器了,因為它根本幫不上什麼忙。
 4.TCP很難穿越Linux這種對稱NAT這是為什麼呢?起初,我以為可以採用偽造ACK包的方式進行穿越,然而實驗沒有成功,後來看了源碼發現ip_conntrack對TCP的狀態機器,序號範圍進行了嚴格的審查,凡是不通過的...怎樣呢?ip_conntrack沒有權力丟棄它,而是直接return ACCEPT了,這下就根本別指望能購匹配到任何既有的conntrack了,比如以下的情境: A-類比公網主機10.16.0.1; N-類比NAT主機10.16.0.254; B-N後面的主機; 最終目標:A串連B 配置:A上丟棄到來的TCP 6667資料包 行為: 1).B綁定連接埠6667串連A的連接埠66672).串連順利通過N,在N上留下了:tcp      6 52 SYN_SENT src=172.16.0.35 dst=10.16.0.1 sport=6667 dport=6667 packets=3 bytes=180 [UNREPLIED] src=10.16.0.1 dst=10.16.0.254 sport=6667 dport=6667 packets=0 bytes=0 mark=0 secmark=0 use=1  www.2cto.com  一條UNREPLIED的conntrack3).此時B反客為主,停掉用戶端程式,啟動監聽同一連接埠的伺服器;4).A以連接埠6667串連N的66675).SYN資料包到達N,被N發回了reset,實驗失敗。
 這個原理很簡單,如果看一下ip_conntrack_in這個ip_conntrack的入口函數,將會發現一個下面的邏輯:[plain]ret = proto->packet(ct, *pskb, ctinfo);  if (ret < 0) {      /* Invalid: inverse of the return code tells       * the netfilter core what to do*/      nf_conntrack_put((*pskb)->nfct);      (*pskb)->nfct = NULL;      CONNTRACK_STAT_INC(invalid);      //如果發現狀態或者序號有問題,直接返回,跳出Netfilter的當前HOOK點      return -ret;  }  ...  if (set_reply)      set_bit(IPS_SEEN_REPLY_BIT, &ct->status);  packet回呼函數實際上就是tcp_packet函數,裡面有複雜的狀態機器檢查,序號檢查等邏輯,因此出錯後直接返回,進而即使找到了與之相匹配的/proc/net/ip_conntrack檔案中的串連,由於無法繼續運行下面的邏輯,所以始終不會將對應串連的UNREPLIED字眼抹去,資料包繼續進入協議棧的上層,最終發往N本地,由於N沒有監聽6667,因此reset。        Linux NAT的這種行為說明很難用常規的方式去穿越. 實驗簡述理解了上述的知識點之後,如何進行實驗就很簡單了,我們只需要3台機器來類比,拓撲情境和上述4中的一模一樣,只是將TCP換成了UDP,很容易就成功了,如果不成功怎麼辦呢?如果不成功一定是因為在NAT的時候源連接埠被改掉了,那麼我們只需要再多試幾個連接埠,直到找到那個不被修改掉的連接埠為止。對於TCP,由於還沒有找到什麼方法,只有放棄了...  www.2cto.com          如果希望驗證兩台同在NAT後面的機器的連通性,原理一樣,由於沒有那麼多機器,作罷了。
 註解:關於cone NATcone NAT實際上是一種主要以“節約IP地址”為目標的NAT裝置,它們並沒有維護各個串連的狀態,也不採取任何安全性原則,是雙向的,對於full cone裝置,一台內部主機會被映射為一個特定的地址,連接埠對,而不管它訪問什麼目標,從任何目標到達full cone NAT裝置的映射後連接埠的都能被該NAT裝置轉寄至內網。        也就是說,所謂的cone NAT正如其名字一樣,是一把錐子形狀的,從NAT裝置向遠方輻散開來,一個IP地址,連接埠對對應多個目標地址,連接埠對。很顯然,這種NAT肯定不是基於串連實現的,而是基於“每包”來實現的。為了提高安全性,還是需要使用對稱的NAT或者不管它是什麼類型的NAT,只要是基於串連來實現的就行,正如Linux的實現一樣,如果以地址,連接埠對來看,它確實有時是錐子形的,然而如果以串連session來看,它就是對稱的,這種NAT的穿越是很難的。
  作者 dog250

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.