歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> 使用iptables為何不能將外部進入的包NAT到127.0.0.1

使用iptables為何不能將外部進入的包NAT到127.0.0.1

日期:2017/2/28 15:47:41   编辑:Linux教程
如有下面的iptables規則:
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 127.0.0.1:1234
你覺得會成功嗎?試一下就知道,不會成功。這是為什麼呢?奇怪的是,不但沒有返回包,即使本地沒有1234這個端口在監聽,也不會發送reset,這說明數據包根本就沒有到達傳輸層,通過forward統計信息來看,它也沒有經過forward,那麼數據包到哪裡去了呢?執行conntrack -E,發現沒有任何新的conntrack生成的事件,並且/proc/net/ip_conntrack中也沒有任何甚至是轉化前的到達80端口的連接。 通過IP安全規則,得知實際上是不允許外部進來的包以loopback地址為目標的,否則攻擊就太容易了,比方說我在局域網上放一個目標地址為127.0.0.1的IP包,修改其MAC目標地址為全1,這樣所有的機器都將可以收到這樣的包,因此路由模塊負責丟棄這樣的數據包。從表象上上,數據包被丟棄了,如果從統計數據來看,執行rtstat命令,將會看到下面一列:
|rt_cache|
|in_marti|
| an_dst|
| 34|

這說明34個這樣的包被丟棄了,在哪裡被丟了呢?肯定在路由模塊,畢竟這是IP的策略,查看源碼,在ip_route_input_slow裡面發現:
  1. if (ipv4_is_lbcast(daddr) || ipv4_is_zeronet(daddr) ||
  2. ipv4_is_loopback(daddr))
  3. goto martian_destination;
  4. ...
  5. martian_destination:
  6. RT_CACHE_STAT_INC(in_martian_dst);
我們看到,這種情況的目的地址是一個“火星地址”,被丟棄了,同時還記錄了一條統計信息。這說明,環回地址只能通過本機來訪問,在本機出去的包經過ip_route_output後,其dst字段即路由結果已經被設置,如果是訪問127.0.0.1,那麼將不會再到ip_route_input,詳見ip_rcv_finish:
  1. if (skb_dst(skb) == NULL) {
  2. int err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
  3. skb->dev);
  4. ...
  5. }
理解了數據包在哪裡被丟棄了之後,對於出現的現象就很好理解了。為何當發起到80端口的訪問且途徑設置了前面iptables規則的機器時/proc/net/ip_conntrack中沒有任何關於端口80的連接呢?這是因為該連接的數據包既沒有被forward到網卡,也沒有被input到本地,因此該連接始終沒有被confirm,而我們知道ip_conntrack機制只有在confirm時才會將連接加入到hash鏈表中並且報告事件。
本文描述的是一個關於漏洞的問題,經典的《專家們公認的20個最危險的安全漏洞》一文中有下面的論述:
G5 – 沒有過濾地址不正確的包
G5.1描述
IP地址欺詐是黑客經常用來隱藏自己蹤跡的一種手段。例如常見的smurf攻擊就利用了路由的特性向數以千記的機器發出了一串數據包。每一個數據包都假冒了一個受害主機的IP地址作為源地址,於是上千台主機會同時向這個受害的主機返回數據包,導致該主機或網絡崩潰。對流進和流出你網絡的數據進行過濾可以提供一種高層的保護。過濾規則如下:
1. 任何進入你網絡的數據包不能把你網絡內部的地址作為源地址。
2. 任何進入你網絡的數據包必須把你網絡內部的地址作為目的地址。
3. 任何離開你網絡的數據包必須把你網絡內部的地址作為源地址。
4. 任何離開你網絡的數據包不能把你網絡內部的地址作為目的地址。
5. 任何進入或離開你網絡的數據包不能把一個私有地址(private address)或在RFC1918中
列出的屬於保留空間(包括10.x.x.x/8, 172.16.x.x/12 或192.168.x.x/16 和網絡回送地址
127.0.0.0/8.)的地址作為源或目的地址。
6. 阻塞任意源路由包或任何設置了IP選項的包。

可見,阻塞這種目標為環回地址的包是合理的,然而這件事到底應該有誰來做,這是一個問題,到底應該由防火牆軟件來做呢,還是操作系統協議棧本身來做?Linux是在IP路由模塊中做的,我認為這樣不是很合理,有時候我真的需要這個功能,總不能重新編譯一下內核吧,我覺得要麼做到Netfilter中,要麼就像rp_filter那樣,做成可以配置的開關。
Copyright © Linux教程網 All Rights Reserved