iptables實現網卡包的轉發


mips小板上有兩個網卡eth0、eth1,現在要實現的是將eth0接收到的數據從eth1中轉發出去。

 

iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp -s ! 10.0.0.1 -d 12.0.0.1 --dport 21 -j DNAT --to-destination 10.0.0.2:8888
iptables -t nat -A POSTROUTING -o eth0 -p tcp -m tcp -d 10.0.0.2 --dport 8888 -j SNAT --to-source 12.0.0.1
或者
iptables -t nat -A POSTROUTING -o eth0 -p tcp -m tcp -d 10.0.0.2 --dport 8888 -j MASQUERADE
IP_FORWARD已經打開

這兩條規則鏈轉發沒有問題
但是問題是  來源地址的IP被  POSTROUTING鏈給修改為了 12.0.0.1
有沒有什么辦法可以 讓IPTABLES只做包轉發   不改變 數據包的來源地址。
有哪位知道的話 告訴一下
謝謝!

-------------[   ip 18.0.10.1      ]-------------------[ 12.0.0.1:21]
                                                                          |
                                                                          |
                                                                          |
                                                                  [   10.0.0.1:8888  ]
描述 。IP180.0.10.1訪問  12.0.0.1:21端口
          12.0.0.1把來自21端口的訪問 重定向道公網的  10.0.0.1:8888
          10.0.0.1:8888看到的來源地址  需要時   18.0.10.1 而不是  12.0.0.1

 

 設我們有一台計算機,有兩塊網卡,eth0連外網,ip為1.2.3.4;eth1連內網,ip為192.168.0.1.現在需要把發往地址1.2.3.4的81端口的ip包轉發到ip地址192.168.0.2的8180端口,設置如下:

  1. iptables -t nat -A PREROUTING -d 1.2.3.4 -p tcp -m tcp --dport 81 -j DNAT --to-destination192.168.0.2:8180

  2. iptables -t nat -A POSTROUTING -s 192.168.0.0/255.255.0.0 -d 192.168.0.2 -p tcp -m tcp --dport 8180 -j SNAT --to-source 192.168.0.1

  真實的傳輸過程如下所示:

  假設某客戶機的ip地址為6.7.8.9,它使用本機的1080端口連接1.2.3.4的81端口,發出的ip包源地址為6.7.8.9,源端口為1080,目的地址為1.2.3.4,目的端口為81.

  主機1.2.3.4接收到這個包后,根據nat表的第一條規則,將該ip包的目的地址更該為192.168.0.2,目的端口更該為8180。同時在連接跟蹤表中創建一個條目,(可從/proc/net/ip_conntrack文件中看到),然后發送到路由模塊,通過查路由表,確定該ip包應發送到eth1接口。在向eth1接口發送該ip包之前,根據nat表的第二條規則,如果該ip包來自同一子網,則將該ip包的源地址更該為192.168.0.1,同時更新該連接跟蹤表中的相應條目,然后送0接口發出.

  此時連接跟蹤表中有一項:

  連接進入: src=6.7.8.9 dst=1.2.3.4 sport=1080 dport=81

  連接返回: src=192.168.0.2 dst=6.7.8.9 sport=8180 dport=1080

  是否使用: use=1

  而從192.168.0.2發回的ip包,源端口為8180,目的地址為6.7.8.9,目的端口為1080,主機1.2.3.4的TCP/IP棧接收到該ip包后,由核心查找連接跟蹤表中的連接返回欄目中是否有同樣源和目的地址和端口的匹配項,找到后,根據條目中的記錄將ip包的源地址由192.168.0.2更該為1.2.3.4, 源端口由8180更該為81,保持目的端口號1080不變.這樣服務器的返回包就可以正確的返回發起連接的客戶機,通訊就這樣開始.

  還有一點, 在filter表中還應該允許從eth0連接192.168.0.2地址的8180端口:

  iptables -A INPUT -d 192.168.0.2 -p tcp -m tcp --dport 8180 -i eth0 -j ACCEPT

 

 

什么是Iptables? 

iptables 是建立在 netfilter 架構基礎上的一個包過濾管理工具,最主要的作用是用來做防火牆或透明代理。Iptables 從 ipchains 發展而來,它的功能更為強大。Iptables 提供以下三種功能:包過濾、NAT(網絡地址轉換)和通用的 pre-route packet mangling。

包過濾:用來過濾包,但是不修改包的內容。Iptables 在包過濾方面相對於 ipchians 的主要優點是速度更快,使用更方便。

NAT:NAT 可以分為源地址 NAT 和目的地址 NAT。 

Iptables 可以追加、插入或刪除包過濾規則。實際上真正執行這些過慮規則的是 netfilter 及其相關模塊(如 iptables 模塊和 nat 模塊)。

Netfilter 是 Linux 核心中一個通用架構,它提供了一系列的 “表”(tables),每個表由若干 “鏈”(chains)組成,而每條鏈中可以有一條或數條 “規則”(rule)組成。 

iptables 可以操縱3 個表:filter 表,nat 表,mangle 表。 
NAT 和一般的 mangle 用 -t 參數指定要操作哪個表。filter 是默認的表,如果沒有 -t 參數,就默認對 filter 表操作。
 “filter”表中包含了 INPUT、FORWARD 和 OUTPUT 3 個鏈。 

每一條鏈中可以有一條或數條規則,每一條規則都是這樣定義的:如果數據包頭符合這樣的條件,就這樣處理這個數據包。當一個數據包到達一個鏈時,系統就會從第一條規則開始檢查,看是否符合該規則所定義的條件: 如果滿足,系統將根據該條規則所定義的方法處理該數據包;如果不滿足則繼續檢查下一條規則。最后,如果該數據包不符合該鏈中任一條規則的話,系統就會根據該鏈預先定義的策略來處理該數據包。 


 

 


規則:

Rule 規則:過濾規則,端口轉發規則等,例如:禁止任何機器 ping 我們的服務器,可以在服務器上設置一條規則: 

iptables -A INPUT -s ! 127.0.0.1 -p icmp -j DROP 

從 –s 開始即是一條規則,-j 前面是規則的條件,-j 開始是規則的行為(目的)。整條命令解釋為,在filter 表中的 INPUT 規則鏈中插入一條規則,所有源地址不為 127.0.0.1 的 icmp 包都被拋棄。 
(下面的一些例子可以此例子為參考)


Chain (規則鏈):由一系列規則組成,每個包順序經過 chain 中的每一條規則。chain 又分為系統 chain和用戶創建的 chain。下面先敘述系統 鏈。 

filter 表的系統 鏈: INPUT,FORWARD,OUTPUT 

nat 表的系統 鏈: PREROUTING,POSTROUTING,OUTPUT 

mangle 表的系統 鏈: PREROUTING,OUTPUT 

每條系統 chain 在確定的位置被檢查。比如在包過濾中,所有的目的地址為本地的包,則會進入INPUT 規則鏈,而從本地出去的包會進入 OUTPUT 規則鏈。 

所有的表(table) 和 鏈(chain) 開機時都為空,設置 iptables 的方法就是在合適的 table 和系統 chain 中添相應的規則。 
 

 



iptables:

表:   iptables從其使用的三個表(filter、nat、mangle)而得名, 對包過濾只使用 filter 表, filter還是默認表,無需顯示說4明. 

操作命令: 即添加、刪除、更新等。 

鏈:  對於包過濾可以針對filter表中的INPUT、OUTPUT、FORWARD鏈,也可以操作用戶自定義的鏈。 

規則匹配器: 可以指定各種規則匹配,如IP地址、端口、包類型等。 

目標動作: 當規則匹配一個包時,真正要執行的任務,常用的有: 

ACCEPT 允許包通過 

DROP 丟棄包 


 

一些擴展的目標還有: 

REJECT 拒絕包,丟棄包同時給發送者發送沒有接受的通知 

LOG 包有關信息記錄到日志 

TOS 改寫包的TOS值 

 




為使FORWARD規則能夠生效,可使用下面2種方法的某種: 

[root@rhlinux root]# vi /proc/sys/net/ipv4/ip_forward 
[root@rhlinux root]# echo "1" > /proc/sys/net/ipv4/ip_forward 

[root@rhlinux root]# vi /etc/sysconfig/network 
[root@rhlinux root]# echo "FORWARD_IPV4=true" > /etc/sysconfig/network 

 

 




iptables語法可以簡化為下面的形式: 

iptables [-t table] CMD [chain] [rule-matcher] [-j target] 

CMD  常用操作命令: 

-A 或 -append 在所選鏈尾加入一條或多條規則 


-D 或 -delete 在所選鏈尾部刪除一條或者多條規則 

-R 或 -replace 在所選鏈中替換一條匹配規則 

-I 或 -insert 以給出的規則號在所選鏈中插入一條或者多條規則. 如果規則號為1,即在鏈頭部. 

-L 或 -list 列出指定鏈中的所有規則,如果沒有指定鏈,將列出鏈中的所有規則. 

-F 或 -flush 清除指定鏈和表中的所由規則, 假如不指定鏈,那么所有鏈都將被清空. 

-N 或 -new-chain 以指定名創建一條新的用戶自定義鏈,不能與已有鏈名相同. 

-X 或 -delete-chain 刪除指定的用戶定義簾,必需保證鏈中的規則都不在使用時才能刪除,若沒有指定鏈,則刪除所有用戶鏈. 

-P 或 -policy 為永久簾指定默認規則(內置鏈策略),用戶定義簾沒有缺省規則,缺省規則也使規則鏈中的最后一條規則,用-L顯示時它在第一行顯示. 

-C 或 -check 檢查給定的包是否與指定鏈的規則相匹配. 

-Z 或 -zero 將指定簾中所由的規則包字節(BYTE)計數器清零. 

-h 顯示幫助信息. 

matcher  常用匹配規則器: 

-p , [!] protocol 指出要匹配的協議,可以是tcp, udp, icmp, all, 前綴!為邏輯非,表示除該協議外的所有協議. 

-s [!] address[/mask] 指定源地址或者地址范圍. 

-sport [!] port[:port] 指定源端口號或范圍,可以用端口號也可以用/ETC/SERVICES文件中的名子. 

-d [!] address[/mask] 指定目的地址或者地址范圍. 

-dport [!] port[:port] 指定目的端口號或范圍,可以用端口號也可以用/ETC/SERVICES文件中的名子. 

-icmp-type [!] typename 指定匹配規則的ICMP信息類型(可以使用 iptables -p icmp -h 查看有效的ICMP類型名) 

-i [!] interface name[+] 匹配單獨或某種類型的接口,此參數忽略時,默認符合所有接口,接口可以使用"!"來匹配捕食指定接口來的包.參數interface是接口名,如 eth0, eht1, ppp0等,指定一個目前不存在的接口是完全合法的,規則直到接口工作時才起作用,折中指定對於PPP等類似連接是非常有用的."+"表示匹配所有此類型接口.該選項只針對於INPUT,FORWARD和PREROUTING鏈是合法的. 

-o [!] interface name[+] 匹配規則的對外網絡接口,該選項只針對於OUTPUT,FORWARD,POSTROUTING鏈是合法的. 

[!] --syn 僅僅匹配設置了SYN位, 清除了ACK, FIN位的TCP包. 這些包表示請求初始化的TCP連接.阻止從接口來的這樣的包將會阻止外來的TCP連接請求.但輸出的TCP連接請求將不受影響.這個參數僅僅當協議類型設置為了TCP才能使用. 此參數可以使用"!"標志匹配已存在的返回包,一般用於限制網絡流量,即只允許已有的,向外發送的連接所返回的包. 

 -m module_name 使用擴展模塊來進行數據包的匹配。如: 

        -m tcp 的意思是使用 tcp 擴展模塊的功能 (tcp擴展模塊提供了 --dport, --tcp-flags, --sync等功能).

 

 


-j target :

 ACCEPT target

這個target沒有任何選項和參數,使用也很簡單,指定-j ACCEPT即可。一旦包滿足了指定的匹配條件,就會被ACCEPT,並且不會再去匹配當前鏈中的其他規則或同一個表內的其他規則,但它還要通過其他表中的鏈,而且在那兒可能會百DROP也說不准哦

 

DNAT target 

這個target是用來做目的網絡地址轉換的,就是重寫包的目的IP地址。如果一個包被匹配了,那么和它屬於同一個流的所有的包都會被自動轉換,然后就可以被路由到正確的主機或網絡。DNAT target是非常有用的。

比如,你的Web服務器在LAN內部,而且沒有可在Internet上使用的真實IP地址,那就可以使用這個 target讓防火牆把所有到它自己HTTP端口的包轉發給LAN內部真正的Web服務器。目的地址也可以是一個范圍,這樣的話,DNAT會為每一個流隨機分配一個地址。因此,我們可以用這個target做某種類型地負載平衡。

注意,DANT target只能用在nat表的PREROUTING和OUTPUT鏈中,或者是被這兩條鏈調用的鏈里。但還要注意的是,包含DANT target的鏈不能被除此之外的其他鏈調用,如POSTROUTING。

例:

 

Option

--to-destination

Example

iptables -t nat -A PREROUTING -p tcp -d 15.45.23.67 --dport 80 -j DNAT --to-destination 192.168.1.1-192.168.1.10 

解釋

指定要寫入IP頭的地址,這也是包要被轉發到的地方。上面的例子就是把所有發往地址15.45.23.67的包都轉發到一段LAN使用的私有地址中,即192.168.1.1到 192.168.1.10。如前所述,在這種情況下,每個流都會被隨機分配一個要轉發到的地址,但同一個流總是使用同一個地址。我們也可以只指定一個IP地址作為參數,這樣所有的包都被轉發到同一台機子。我們還可以在地址后指定一個或一個范圍的端口。比如:--to-destination 192.168.1.1:80或 --to-destination 192.168.1.1:80-100。SNAT的語法和這個target的一樣,只是目的不同罷了。要注意,只有先用--protocol指定了TCP或 UDP協議,才能使用端口。

 

 

因為DNAT要做很多工作,所以我要再羅嗦一點。我們通過一個例子來大致理解一下它是如何工作的。比如,我想通過Internet連接發布我們的網站,但是HTTP server在我們的內網里,而且我們對外只有一個合法的IP,就是防火牆那個對外的IP——$INET_IP。防火牆還有一個內網的IP——$LAN_IP,HTTP server的IP是$HTTP_IP (這當然是內網的了)。為了完成我們的設想,要做的第一件事就是把下面的這個簡單的規則加入到nat表的PREROUTING鏈中:

iptables -t nat -A PREROUTING --dst $INET_IP -p tcp --dport 80 -j DNAT \ --to-destination $HTTP_IP 

現在,所有從Internet來的、到防火牆的80端口去的包都會被轉發(或稱做被DNAT )到在內網的HTTP服務器上。如果你在Internet上試驗一下,一切正常吧。再從內網里試驗一下,完全不能用吧。這其實是路由的問題。下面我們來好好分析這個問題。為了容易閱讀,我們把在外網上訪問我們服務器的那台機子的IP地址記為$EXT_BOX。

 

DROP target

顧名思義,如果包符合條件,這個target就會把它丟掉,也就是說包的生命到此結束,不會再向前走一步,效果就是包被阻塞了。在某些情況下,這個target會引起意外的結果,因為它不會向發送者返回任何信息,也不會向路由器返回信息,這就可能會使連接的另一方的sockets因苦等回音而亡:) 解決這個問題的較好的辦法是使用REJECT target,(譯者注:因為它在丟棄包的同時還會向發送者返回一個錯誤信息,這樣另一方就能正常結束),尤其是在阻止端口掃描工具獲得更多的信息時,可以隱蔽被過濾掉的端口等等(譯者注:因為掃描工具掃描一個端口時,如果沒有返回信息,一般會認為端口未打開或被防火牆等設備過濾掉了)。還要注意如果包在子鏈中被DROP了,那么它在主鏈里也不會再繼續前進,不管是在當前的表還是在其他表里。總之,包死翹翹了。


 

 



如何制定永久規則集: 

/etc/sysconfig/iptables 文件是 iptables 守護進程調用的默認規則集文件. 

可以使用以下命令保存執行過的IPTABLES命令: 

/sbin/iptables-save > /etc/sysconfig/iptables 

要恢復原來的規則庫,可以使用: 

/sbin/iptables-restore < /etc/sysconfig/iptables 

iptables命令和route等命令一樣,重啟之后就會恢復,所以: 

[root@rhlinux root]# service iptables save 
將當前規則儲存到 /etc/sysconfig/iptables: [ 確定 ] 

令一種方法是 /etc/rc.d/init.d/iptables 是IPTABLES的啟動腳本,所以: 

[root@rhlinux root]# /etc/rc.d/init.d/iptables save 
將當前規則儲存到 /etc/sysconfig/iptables: [ 確定 ] 

以上幾種方法只使用某種即可. 

若要自定義腳本,可直接使用iptables命令編寫一個規則腳本,並在啟動時執行: 

例如若規則使用腳本文件名/etc/fw/rule, 則可以在/etc/rc.d/rc.local中加入以下代碼: 

if [-x /etc/fw/rule]; then /etc/fw/sule; fi; 

這樣每次啟動都執行該規則腳本,如果用這種方法,建議NTSYSV中停止IPTABLES. 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM