iptables學習03端口轉發
2個網絡接口:Lan口:10.1.1.254/24 eth0,Wan口:60.1.1.1/24 eth1
Lan內web server: 10.1.1.1:80,Lan內ftp server: 10.1.1.2:21
目標:對內部 server進行端口轉發實現internet用戶訪問內網服務器
首先,確認你的linux的各項配置正常,能夠訪問內外網
[plain]
iptables -P FORWARD DROP
[plain]
iptables -A FORWARD -mstate --state ESTABLISHED,RELATED -j ACCEPT
也需要加入確認包和關聯包的允許通過
如果你要把訪問 60.1.1.1:80的數據包轉發到Lan內web server,用下面的命令
[plain]
iptables -t nat -A PREROUTING -d 60.1.1.1 -p tcp --dport 80 -j DNAT --to 10.1.1.1:80
ftp服務也同樣,命令如下:
[plain]
iptables -t nat -A PREROUTING -d 60.1.1.1 -p tcp --dport 21 -j DNAT --to 10.1.1.2:21
現在還不能訪問,為什麼呢?我下面詳細分析一下。對於iptables好像往外訪問的配置較容易,而對內的轉發似乎就有一些問題了
能引起這個配置失敗的原因有很多,我們一個個的來說:
第一,本例中,我們的 FORWARD策略是DROP,那麼也就是說,沒有符合規則的包將被丟棄,不管內到外還是外到內,我們在這裡依然不討論那個確認包和關聯包的問題,我們不用考慮他的問題,下面我會詳細說一下這個東西,那麼如何讓本例可以成功呢?加入下面的規則。
[plain]
iptables -A FORWARD -d 10.1.1.1 -p tcp --dport 80 -j ACCEPT
iptables -A FORWARD -d 10.1.1.2 -p tcp --dport 21 -j ACCEPT
有沒有覺得有一些暈?為什麼目的地址是10.xxx而不是60.xxx人家internet用戶不是訪問的60.xxx嗎?呵呵,回到上面看看那個圖吧, FORWARD鏈在什麼位置上,它是在PREROUTING之後,也就是說當這個包到達FORWARD鏈的時候,目的地址已經變成10.xxx了,假如 internet用戶的請求是這樣202.1.1.1:1333-->60.1.1.1:80,在經過了我們的PREROUTING鏈之後將變成 202.1.1.1:1333-->10.1.1.1:80,這個時候如果你設置一個目的地址為60.xxx的規則有用嗎?呵呵,這是問題一。這個時候應該可以完成端口轉發的訪問了,但是有一些時候還是不行?為什麼?看問題二。
第二,內網server的ip配置問題,這裡我們以web server為例說明一下(ftp情況有一些特殊,下面我們再詳細討論,說確認包和關聯包的時候討論這個問題),上面說到,有的時候可以訪問了,有的時候卻不行,就是這個web server的ip設置問題了,如果web server沒有指定默認的網關,那麼在作了上面的配置之後,web server會收到internet的請求,但是,他不知道往哪裡回啊,人家的本地路由表不知道你那個internet的ip,202.1.1.1該怎麼走。如果你使用截包工具在web server上面察看,你會發現server收到了來自 202.1.1.1:1333-->10.1.1.1:80的請求,由於你沒有給webserver配置默認網關,它不知道怎麼回去,所以就出現了不通的情況。怎麼辦呢?兩個解決方法:一就是給這個server配置一個默認網關,當然要指向這個配置端口轉發的linux,本例是 10.1.1.254,配置好了,就一定能訪問了。有一個疑問?難道不需要在FORWARD鏈上面設置一個允許 web server的ip地址訪問外網的規則嗎?它的包能出去?答案是肯定的,能出去。因為我們那一條允許確認包與關聯包的規則,否則它是出不去的。第二種方法,比較麻煩一些,但是對服務器來說這樣似乎更安全一些。方法就是對這個包再作一次SNAT,也就是在POSTROUTING鏈上添加規則。命令如下:
[plain]
iptables -t nat -A POSTROUTING -d 10.1.1.1 -p tcp --dport 80 -j SNAT --to 10.1.1.254
ftp的方法相同。這條命令不太好懂??其實很簡單,如果使用這條命令,那麼你的web server不需要再設置默認網關,就能收到這個請求,只要他和linux的 lan ip地址是能互訪的(也就是說web server和Linux的Lanip在一個廣播域),我們在根據上面的netfilter流程圖來分析這個包到底被我們怎麼樣了,首先一個請求202.1.1.1:1333--> 60.1.1.1:80被linux收到了,進入 PREROUTING,發現一個規則(iptables -t nat -APREROUTING -d 60.1.1.1 -p tcp --dport 80 -j DNAT --to 10.1.1.1:80)符合,好了,改你的目的地址,於是這個包變成了202.1.1.1:1333-->10.1.1.1:80,繼續往前走,進入FORWARD鏈,okay,也有一條規則允許通過 (iptables -AFORWARD -d 10.1.1.1 -p tcp --dport 80 -j ACCEPT),進入route box選路,找到合適的路徑了,繼續進入POSTROUTING鏈,耶?又發現一個符合的規則 (iptables -t nat -A POSTROUTING -d 10.1.1.1 -p tcp --dport 80 -jSNAT --to 10.1.1.254), 原來是一個SNAT,改你的源地址,於是這個包變成了10.1.1.254:xxxx-->10.1.1.1:80。為什麼用xxxx了,這裡的端口是隨機的,我也不知道會是什麼。而整個的兩次變化的過程都會記錄在linux的ip_conntrack中,當web server收到這個包的時候,發現,原來是一個內網自己兄弟來的請求阿,又在一個廣播域,不用找網關,把返回包直接扔給交換機了,linux在收到返回包之後,會根據他的 ip_conntrack中的條目進行兩次變換,返回真正的internet用戶,於是完成這一次的訪問。
看了上面的兩個例子,不知道大家是否清楚了iptables的轉發流程,希望對大家有所幫助,下面我們就說說我一直在上面提到的關於那個 ESTABLISHED,RELATED的規則是怎麼回事,到底有什麼用處。說這個東西就要簡單說一下網絡的數據通訊的方式,我們知道,網絡的訪問是雙向的,也就是說一個Client與Server之間完成數據交換需要雙方的發包與收包。在netfilter中,有幾種狀態,也就是 new,established,related,invalid。當一個客戶端,在本文例一中,內網的一台機器訪問外網,我們設置了規則允許他出去,但是沒有設置允許回來的規則阿,怎麼完成訪問呢?這就是netfilter的狀態機制,當一個lan用戶通過這個linux訪問外網的時候,它發送了一個請求包,這個包的狀態是new,當外網回包的時候他的狀態就是established,所以,linux知道,哦,這個包是我的內網的一台機器發出去的應答包,他就放行了。而外網試圖對內發起一個新的連接的時候,他的狀態是new,所以linux壓根不去理會它。這就是我們為什麼要加這一句的原因。還有那個 related,他是一個關聯狀態,什麼會用到呢?tftp,ftp都會用到,因為他們的傳輸機制決定了,它不像http訪問那樣,Client_IP:port-->server:80 然後server:80-->Client_IP:port,ftp使用 tcp21建立連接,使用20端口發送數據,其中又有兩種方式,一種主動 active mode,一種被動passive mode,主動模式下,client使用port命令告訴server我用哪一個端口接受數據,然後server主動發起對這個端口的請求。被動模式下, server使用 port命令告訴客戶端,它用那個端口監聽,然後客戶端發起對他的數據傳輸,所以這對於一個防火牆來說就是比較麻煩的事情,因為有可能會有new狀態的數據包,但是它又是合理的請求,這個時候就用到這個related狀態了,他就是一種關聯,在linux中,有個叫 ftp_conntrack的模塊,它能識別port命令,然後對相應的端口進行放行。
還有幾個在實際中比較實用(也比較受用:-))的命令參數,寫出來供大家參考
[plain]
iptables -L -n
這樣的列表會跳過 linux的domain lookup,有的時候使用iptables -L會比較慢,因為linux會嘗試解析ip的域名,真是羅嗦,如果你的 dns server比較不爽的話,iptables -L就會讓你很不爽,加一個-n參數就好了。列表刷的就出來。當然了,如果你的linux就是做防火牆,建議把nameserver去掉,在 /etc/resolve.conf裡面,因為有時候使用route命令也會比較慢列出來,很是不爽。
[plain]
iptables -L -v
這個命令會顯示鏈中規則的包和流量計數,嘿嘿,看看哪些小子用的流量那麼多,用tc限了他。
[plain]
cat /proc/net/ip_conntrack
查看目前的 conntrack,可能會比較多哦,最好加一個|grep "關鍵字",看看你感興趣的鏈接跟蹤
[plain]
wc -l /proc/net/ip_conntrack
看看總鏈接有多少條
[plain]
iptables-save >/etc/iptables
把當前的所有鏈備份一下,之所以放到/etc下面叫iptables,因為這樣重起機器的時候會自動加載所有的鏈,經常地備份一下吧,否則如果鏈多,萬一掉電重啟,你還是會比較痛苦。