Skip to content

Instantly share code, notes, and snippets.

@huilapman
Last active January 25, 2018 06:42
Show Gist options
  • Save huilapman/51f1c62bfef94fce8b4e909d3634fede to your computer and use it in GitHub Desktop.
Save huilapman/51f1c62bfef94fce8b4e909d3634fede to your computer and use it in GitHub Desktop.

IPTables

在玩 IPTables 以前我們必須先了解一下,您所下的 iptables 防火牆規則對封包進行過濾、封包處理、封包狀態變更、NAT、封包 Qos...等,這些工作其實是核心 (kernel) 層級 Netfilter 在處理的,而 iptables 只是一個使用者端的工具讓您方便對 Netfilter 操作而以,以下是對於玩 iptables 時必須先了解的名詞及相關常用指令。

Netfilter 五種封包處理規則

必須注意的是 INPUT 及 Forward 處理封包的路徑是不同的,也就是說 Forward 處理的封包會略過 INPUT 及 OUTPUT 規則

INPUT:經網卡進入的封包 OUTPUT:經網卡出去的封包 FORWARD:經網卡進入 / 出去轉送的封包
PREROUTING:改變經網卡進入的封包狀態 ( DNAT / REDIRECT ) 
POSTROUTING:改變經網卡出去的封包狀態( SNAT / MASQUERADE )

Netfilter 三種過瀘規則鏈(chain)

filter:可以處理 INPUT、OUTPUT、FORWARD 封包狀態 (Default)
nat:可以處理 OUTPUT、PREROUTING、POSTROUTING 封包狀態
mangle:可以處理 INPUT、OUTPUT、FORWRD、PREROUTING、POSTROUTING 封包狀態

Netfilter 四種封包狀態

NEW:一個新的連線封包 (建立新連線後的第一個封包)
ESTABLISHED:成功建立的連線,即建立追蹤連線後所有封包狀態 (跟在 NEW 封包後面的所有封包)
RELATED:新建連線,由 ESTABLISHED session 所建立的新獨立連線 (ex. ftp-data 連線)
INVALID:非法連線狀態的封包 (DROP 封包)
UNKOWN:不明連線狀態的封包
IPTables 封包處理政策 (Policy) 及 目標 (Target)
ACCEPT:允許封包移動至目的地或另一個 chain
DROP:丟棄封包、不回應要求、不傳送失敗訊息
REJECT:拒絕封包、回應要求、傳送失敗訊息
SNAT:修改 Source Socket
DNAT:修改 Destination Socket
MASQUERADE:動態修改 Source Socket (無法指定 IP,取當時網卡的 IP),較方便但效率較差
REDIRECT:將連線導至本機行程 (Local Process)
RETURN:結束自行定義的 Chain 然後返回原來的 Chain 繼續跑規則 (rules)
QUEUE:封包排隊等待處理
LOG:記錄指定的規則封包 (/etc/syslog.conf , default /var/log/messges)

IPTables 指令參數

處理 iptables 規則時常用到如下參數

-h:help information
-V:顯示 iptables 版本
-I:將規則插入至最前面 or 加上號碼插入指定處
-A:將規則插入至最後面
-R:取代指定的規則 (加上規則號碼)
-D:刪除指定的規則 (加上規則號碼)
-F:刪除所有的規則

處理 iptables 規則鏈(chain)時常用到如下參數

-N:建立新的規則鏈(chain)
-X:刪除指定的規則鏈(chain)
-E:更改指定的規則鏈(chain)名稱
-P:變更指定規則鏈(chain)的政策 (ex. policy for DROP、REJECT、ACCEPT)
-Z:將 iptables 計數器歸零

查看目前 iptables 規則時常用到如下參數

-L:列出目前 iptables 規則 (會執行 DNS 位址解析)
-n:不使用 DNS 解析直接以 IP 位址顯示
-v:顯示目前 iptables 規則處理的封包數
-x:顯示完整封包數 (ex.顯示 1151519,而不是 12M)

實作環境

CentOS 5.1 (Linux 2.6.18-53.1.4.el5)
iptables v1.3.5

安裝及設定

步驟1.修改 iptables 設定檔

iptables 主要設定檔位於 /etc/sysconfig/iptables 當系統重開機且設定開機自動啟動時,系統便會讀取此檔案並套用設定的防火牆規則,你可以把預設的防火牆規則拿來該改即可,你可以手動下 iptables 規則然後在 save 我個人的習慣是直接把規則寫在 /etc/sysconfig/iptables 內。

規則語法如下

 [-io 網路介面] [-p 協定] [-m 模組] [-s 來源] [-d 目的地] [-j 政策]

-i 網路介面:-i 為 in 網路介面就填 eth0... (用於 PREROUTING、INPUT、FORWARD)
-o 網路介面:-o 為 out 網路介面就填 eth0... (用於 POSTROUTING、OUTPUT、FORWARD)
-m 模組:state、mac、limit、owner、multiport...
-p 協定:tcp、upd、icmp...
-s 來源:可為 IP Address、IP 網段、網域名稱
--sport:指定封包來源 Port、Port Range (配合 -p tcp、-p udp)
-d 目的地:可為 IP、IP 網段、網域名稱
--dport:指定封包目的地 Port、Port Range (配合 -p tcp、-p udp)
-j 政策 / 目標:ACCEPT、DROP、REJECT、SNAT、DNAT、MASQUERADE、REDIRECT、RETURN...

以下為一個很簡單的防火牆規則範例,只允許 SSH Service 可連接該主機

 *filter
 :INPUT DROP [0:0]
 :FORWARD DROP [0:0]
 :OUTPUT ACCEPT [0:0]
 -A INPUT -i lo -j ACCEPT                                     //pass Loopback
 -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT      //keep state
 -A INPUT -p icmp -m icmp --icmp-type any -j ACCEPT           //pass icmp protocol
 -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT                 //pass ssh
 COMMIT

步驟2.設定開機自動啟動 iptables 服務 確定 iptables 服務是否開機會自動啟動 (ntsysv or setup)

 #chkconfig --list |grep iptables
 iptables        0:off   1:off   2:on    3:on    4:on    5:on    6:off

常用的 iptables 服務參數

 /etc/rc.d/init.d/iptables start           //啟動 iptables 服務
                           stop            //停止 iptables 服務
                           restart         //重新啟動 iptables 服務
                           status          //查看目前 iptables 規則
                           save            //將目前規則存入 iptables 設定檔

重新啟動 iptables 服務

 #/etc/rc.d/init.d/iptables restart
 Flushing firewall rules:                                   [  OK  ]
 Setting chains to policy ACCEPT: filter                    [  OK  ]
 Unloading iptables modules:                                [  OK  ]
 Applying iptables firewall rules:                          [  OK  ]
 Loading additional iptables modules: ip_conntrack_netbios_n[  OK  ]

查看我們剛才設定的規則

 #/etc/rc.d/init.d/iptables status
 Table: filter
 Chain INPUT (policy DROP)
 num  target     prot opt source               destination
 1    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
 2    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
 3    ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0           icmp type 255
 4    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22
 Chain FORWARD (policy DROP)
 num  target     prot opt source               destination
 Chain OUTPUT (policy ACCEPT)
 num  target     prot opt source               destination

補充:Web Server 防火牆規則設定 一個 Web Server 的基本 iptables 設定內容如下 (Service SSH、HTTP),我將 INPUT Policy 定義為 DROP 也就是說 eth0 網卡預設行為是丟棄封包、不回應要求、不傳送失敗訊息除新定義的 -j ACCEPT 之外。

 #cat /etc/sysconfig/iptables
 *filter                                                      //定義使用的 chain
 :INPUT DROP [0:0]                                            //定義 INPUT Policy
 :FORWARD DROP [0:0]                                          //定義 FORWARD Policy
 :OUTPUT ACCEPT [0:0]                                         //定義 OUTPUT Policy
 -A INPUT -i lo -j ACCEPT                                     //pass Loopback
 -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT      //keep state
 -A INPUT -p icmp -m icmp --icmp-type any -j ACCEPT           //pass icmp protocol
 -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT                 //pass ssh
 -A INPUT -i eth0 -p tcp --dport 80 -j ACCEPT                 //pass http
 COMMIT

IPtables中SNAT和MASQUERADE的區別

IPtables中可以靈活的做各種網絡地址轉換(NAT)
網絡地址轉換主要有兩種:SNAT和DNAT
SNAT是source network address translation的縮寫
即源地址目標轉換

比如,多個PC機使用ADSL路由器共享上網
每個PC機都配置了內網IP
PC機訪問外部網絡的時候,路由器將數據包的報頭中的源地址替換成路由器的ip
當外部網絡的服務器比如網站web服務器接到訪問請求的時候
他的日誌記錄下來的是路由器的ip地址,而不是pc機的內網ip
這是因為,這個服務器收到的數據包的報頭裡邊的「源地址」,已經被替換了
所以叫做SNAT,基於源地址的地址轉換
DNAT是destination network address translation的縮寫
即目標網絡地址轉換

典型的應用是,有個web服務器放在內網配置內網ip,前端有個防火牆配置公網ip
互聯網上的訪問者使用公網ip來訪問這個網站
當訪問的時候,客戶端發出一個數據包
這個數據包的報頭裡邊,目標地址寫的是防火牆的公網ip
防火牆會把這個數據包的報頭改寫一次,將目標地址改寫成web服務器的內網ip
然後再把這個數據包發送到內網的web服務器上
這樣,數據包就穿透了防火牆,並從公網ip變成了一個對內網地址的訪問了
即DNAT,

基於目標的網絡地址轉換
MASQUERADE,地址偽裝,在iptables中有著和SNAT相近的效果,但也有一些區別
但使用SNAT的時候,出口ip的地址範圍可以是一個,也可以是多個,例如:
如下命令表示把所有10.8.0.0網段的數據包SNAT成192.168.5.3的ip然後發出去
iptables -t nat -A POSTROUTING -s 10.8.0.0/255.255.255.0 -o eth0 -j SNAT --to-source 192.168.5.3
如下命令表示把所有10.8.0.0網段的數據包SNAT成192.168.5.3/192.168.5.4/192.168.5.5等幾個ip然後發出去
iptables -t nat -A POSTROUTING -s 10.8.0.0/255.255.255.0 -o eth0 -j SNAT --to-source 192.168.5.3-192.168.5.5
這就是SNAT的使用方法,即可以NAT成一個地址,也可以NAT成多個地址
但是,對於SNAT,不管是幾個地址,必須明確的指定要SNAT的ip
假如當前系統用的是ADSL動態撥號方式,那麼每次撥號,出口ip192.168.5.3都會改變
而且改變的幅度很大,不一定是192.168.5.3到192.168.5.5範圍內的地址
這個時候如果按照現在的方式來配置iptables就會出現問題了
因為每次撥號後,服務器地址都會變化,而iptables規則內的ip是不會隨著自動變化的
每次地址變化後都必須手工修改一次iptables,把規則裡邊的固定ip改成新的ip
這樣是非常不好用的
MASQUERADE就是針對這種場景而設計的,他的作用是,從服務器的網卡上,自動獲取當前ip地址來做NAT
比如下邊的命令:
iptables -t nat -A POSTROUTING -s 10.8.0.0/255.255.255.0 -o eth0 -j MASQUERADE
如此配置的話,不用指定SNAT的目標ip了
不管現在eth0的出口獲得了怎樣的動態ip,MASQUERADE會自動讀取eth0現在的ip地址然後做SNAT出去
這樣就實現了很好的動態SNAT地址轉換 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment