眾所周知,iptable的中包含了各種各樣的table和規則鏈條。這篇博文對規則鏈的執行順序做一個簡單的介紹。
Chain OUTPUT (policy ACCEPT)
target prot opt source destination DNAT tcp -- anywhere anywhere tcp dpt:5000 to:172.30.57.2:5000
正常來說,iptable會對一條報文逐條匹配某個表中的規則,如果匹配成功,那么就執行這條規則對應的TARGET。例如上面這條規則的作用是,如果報文滿足以下條件:
- tcp協議
- 源地址為任何地址
- 目的地址為任何地址
- 發送到本地5000端口的(dpt:5000)
那么就做Destination NAT,NAT至172.30.57.2:5000。如果報文匹配了該條規則,那么它會跳出OUTPUT,轉而執行下一個對應的規則鏈。
這個例子說明了當TARGET為DNAT時的情況。但是我們知道iptable中的TARGET有很多種,DNAT只是其中之一。不同的TARGET有不同的跳轉規則,有的TARGET在執行完成后就跳出當前的規則鏈跳往下一個規則鏈(例如在PREROUTING時從mangel表的PREROUTING鏈跳往nat表的POSTROUTING鏈). 而有的TARGET 在執行完成后會接着執行當前規則鏈中的下一個規則。
從網上抄了一個2007年的博文:
-------------------------------------------------------------------------
iptables 是采用規則堆棧的方式來進行過濾,當一個封包進入網卡,會先檢查 Prerouting,然后檢查目的 IP 判斷是否需要轉送出去,接着就會跳到 INPUT 或 Forward 進行過濾,如果封包需轉送處理則檢查 Postrouting,如果是來自本機封包,則檢查 OUTPUT 以及 Postrouting。過程中如果符合某條規則將會進行處理,處理動作除了 ACCEPT、REJECT、DROP、REDIRECT 和 MASQUERADE 以外,還多出 LOG、ULOG、DNAT、SNAT、MIRROR、QUEUE、RETURN、TOS、TTL、MARK 等,其中某些處理動作不會中斷過濾程序,某些處理動作則會中斷同一規則煉的過濾,並依照前述流程繼續進行下一個規則煉的過濾(注意:這一點與 ipchains 不同),一直到堆棧中的規則檢查完畢為止。透過這種機制所帶來的好處是,我們可以進行復雜、多重的封包過濾,簡單的說,iptables 可以進行縱橫交錯式的過濾(tables)而非煉狀過濾(chains)。
- ACCEPT 將封包放行,進行完此處理動作后,將不再比對其它規則,直接跳往下一個規則煉(nat:postrouting)。
- REJECT 攔阻該封包,並傳送封包通知對方,可以傳送的封包有幾個選擇:ICMP port-unreachable、ICMP echo-reply 或是 tcp-reset(這個封包會要求對方關閉聯機),進行完此處理動作后,將不再比對其它規則,直接 中斷過濾程序。 范例如下:iptables -A FORWARD -p TCP --dport 22 -j REJECT --reject-with tcp-reset
- DROP 丟棄封包不予處理,進行完此處理動作后,將不再比對其它規則,直接中斷過濾程序。
- REDIRECT 將封包重新導向到另一個端口(PNAT),進行完此處理動作后,將 會繼續比對其它規則。 這個功能可以用來實作通透式 porxy 或用來保護 web 服務器。例如:iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
- MASQUERADE 改寫封包來源 IP 為防火牆 NIC IP,可以指定 port 對應的范圍,進行完此處理動作后,直接跳往下一個規則煉(mangle:postrouting)。這個功能與 SNAT 略有不同,當進行 IP 偽裝時,不需指定要偽裝成哪個 IP,IP 會從網卡直接讀取,當使用撥接連線時,IP 通常是由 ISP 公司的 DHCP 服務器指派的,這個時候 MASQUERADE 特別有用。范例如下:
iptables -t nat -A POSTROUTING -p TCP -j MASQUERADE --to-ports 1024-31000 - LOG 將封包相關訊息紀錄在 /var/log 中,詳細位置請查閱 /etc/syslog.conf 組態檔,進行完此處理動作后,將會繼續比對其它規則。例如:
iptables -A INPUT -p tcp -j LOG --log-prefix "INPUT packets" - SNAT 改寫封包來源 IP 為某特定 IP 或 IP 范圍,可以指定 port 對應的范圍,進行完此處理動作后,將直接跳往下一個規則煉(mangle:postrouting)。范例如下:
iptables -t nat -A POSTROUTING -p tcp-o eth0 -j SNAT --to-source 194.236.50.155-194.236.50.160:1024-32000 - DNAT 改寫封包目的地 IP 為某特定 IP 或 IP 范圍,可以指定 port 對應的范圍,進行完此處理動作后,將會直接跳往下一個規則煉(filter:input 或 filter:forward)。范例如下:
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:80-100 - MIRROR 鏡射封包,也就是將來源 IP 與目的地 IP 對調后,將封包送回,進行完此處理動作后,將會中斷過濾程序。
- QUEUE 中斷過濾程序,將封包放入隊列,交給其它程序處理。透過自行開發的處理程序,可以進行其它應用,例如:計算聯機費用.......等。
- RETURN 結束在目前規則煉中的過濾程序,返回主規則煉繼續過濾,如果把自訂規則煉看成是一個子程序,那么這個動作,就相當於提早結束子程序並返回到主程序中。
- MARK 將封包標上某個代號,以便提供作為后續過濾的條件判斷依據,進行完此處理動作后,將會繼續比對其它規則。范例如下:iptables -t mangle -A PREROUTING -p tcp --dport 22 -j MARK --set-mark 2
------------------------------------------------------------------------------------
ref: http://bbs.chinaunix.net/thread-936284-1-1.html
還有一種情況這個帖子中沒有給出,那就是自定義的規則鏈。例如:
Chain POSTROUTING (policy ACCEPT) target prot opt source destination KUBE-POSTROUTING all -- anywhere anywhere /* kubernetes postrouting rules */ RETURN all -- 192.168.122.0/24 224.0.0.0/24 RETURN all -- 192.168.122.0/24 255.255.255.255 MASQUERADE tcp -- 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535 MASQUERADE udp -- 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535 MASQUERADE all -- 192.168.122.0/24 !192.168.122.0/24 RETURN all -- 172.30.0.0/16 172.30.0.0/16 MASQUERADE all -- 172.30.0.0/16 !224.0.0.0/4 RETURN all -- !172.30.0.0/16 172.30.57.0/24 MASQUERADE all -- !172.30.0.0/16 172.30.0.0/16 MASQUERADE tcp -- 172.30.57.2 172.30.57.2 tcp dpt:5000 Chain KUBE-POSTROUTING (1 references) target prot opt source destination MASQUERADE all -- anywhere anywhere /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000
在這個例子中,有兩個規則鏈,分別是iptable默認的POSTROUTTING鏈,還有一個是kube-proxy定義的KUBE-POSTROUTTING。當報文走到POSTROUTTING是,會匹配第一條。很顯然,這條規則會匹配所有的報文。
然后跳轉到KUBE-POSTROUTTING規則鏈,這個規則鏈只有一條規則,它的意思是如果報文帶有0x4000的標記,那么就執行target,也就是MASQUERADE。如果報文不攜帶0x4000標記,那么該報文就不會匹配這條規則,然后返回,接着匹配
POSTROUTTING中的下一條報文。
