iptables
基本介紹以下紀錄自己學習
iptables
的筆記~
資料透過網路傳輸時,會被切割成一個一個的封包,封包裡面除了含有要傳送的 data,也含有這個封包的資訊,像是 souce address、protocol 等等資訊。
而說到 Linux 的防火牆,就會提到 iptables
。當封包進到 iptables
裡面,iptables
就會查看這個封包的資訊,並依據我們設定的防火牆規則對這個封包做處理。
以下簡單介紹 iptables
和它的指令~
netfilter
是運行在 kernel space 的,所以使用者沒辦法直接對他做操作;而 iptables
則是運行在 user space 的工具,使用者可以透過 iptables
對 netfilter
做設定。
從上面那張圖可以看到 iptables
其實是比較舊版的,且 iptables
是專門負責 IPv4 的 packet filtering 和 network address translation(NAT);IPv6 的部分則由 ip6tables
負責,另外還有 ebtables
和 arptables
分別負責 ethernet bridge frame table 和 address resolution protocol table。
而 Linux kernel 自 3.13 版開始,就改成使用 nftables
。一個 nftables
的功能就涵蓋了舊版的四個工具的功能。
而 OpenWRT 則是自 22.03 版以後,預設上改成使用 nftables
。
iptables
組成上圖是一個很簡單的示意圖,iptables
裡面會有一個一個的 tables,每個 table 則會由多個 chains 所組成,而這些 chains 則由多個 rules 所構成。
PREROUTING
chain)、或者是處理完 routing 之後(POSTROUTING
chain)。以 NAT table 為例,這個 table 的功能是對封包做 network address translation,那這個 table 有 PREROUTING
chain 和 POSTROUTING
chain,所以封包在 PREROUTING
和 POSTROUTING
階段會進入 NAT table 的 PREROUTING
chain 和 POSTROUTING
chain,並且依序比對這些 chain 裡面的 rule,
上圖是個簡單的示意圖說明若一個封包進到 iptables
的處理流程。
封包的處理流程主要依據不同的階段劃分,這裡簡單的用 Stage I、Stage II、以及 Stage III 作說明(後面會提到確切的流程)。
前面有提到,chain 的命名是依據封包處理的階段所命名,所以 stage I 會由某些 table 的 chain I 所組成,而 stage II 則由另一些 table 的 chain II 所組成,依此類推。
封包在每個 stage 會依序去執行不同 table 的 chain。一旦符合該 chain 的某個 rule,就執行該 rule 的 target。上圖列出了兩個最常見的 target:ACCEPT
和 DROP
。ACCEPT
就是讓這封包通過,DROP
則是丟掉這個封包。
所以在上面的示意圖可看到,一旦封包符合了 rule,且該 rule 的 target 是 ACCEPT
,那這個封包就會到下一個 chain,而不會繼續比對同一個 chain 後面的 rule。所以 rule 的順序在 iptables
是很重要的一件事!倘若 target 是 DROP
,就會丟棄該封包、不再對它做處理。
前面有提到,封包一旦進入一個 chain,就會依序去比對該 chain 的 rule,倘若符合某個 rule,就會執行該 rule 指定的 target。
所以再提醒一次~rule 的順序在 iptables
是很重要的~若順序錯誤,可能就達不到自己想要的效果!
此外,依據封包執行的結果,大致可將 target 分成兩類:terminating target 和 non-terminating target。
ACCEPT
和 DROP
。執行了這類的 target 後,封包就不會繼續比對同一個 chain 後續的 rule。例如,若是 ACCEPT
,那封包就會到下一個 chain。LOG
,顧名思義就是會記錄到 log。iptables
的 Tables 和 Chains目前 iptables
內有這五個 tables,但可能會因 kernel 的 configuration 不同而有些許差異:
filter
table
ACCEPT
(接受)封包,或 DROP
(丟掉)封包。nat
table
mangle
table
MARK
target 對封包做標記。raw
table
raw
table 的主要功能是將不需要做 connection tracking(連線追蹤)的封包做 NOTRACK
,這樣這些封包就不會被 connection tracking,而可以減少 netfilter
的負擔。NOTRACK
,就必須要在封包進到 iptables
時盡早對其做處理,所以在封包的 PREROUTING
和 OUTPUT
階段第一個經過的 table 就是 raw
table(後面會有張整個流程的示意圖)。security
table
SECMARK
或 CONNSECMARK
標示,後續再由像是 SELinux 決定是否允許此封包存取系統。filter
table 的 chain 比對完之後,就會馬上比對 security
table 的 chain。
如果是使用 OpenWRT 的話,OpenWRT 預設使用的 table 是 filter table、nat table、以及 mangle table。
若想要使用 raw table 的話,記得在編譯 kernel 前就要做好設定~
像是用 make menuconfig
:
Kernel modules
Netfilter Extensions
<*> kmod-ipt-raw
內建的 chain 總共有五個,分別代表封包處理的五個階段:
PREROUTING
INPUT
chain。FORWARD
chain。INPUT
PREROUTING
chain,且路由決策判斷其目的地是本機,就會進入 INPUT
chain,可以在這裡決定本機是否要接受此封包。FORWARD
FORWARD
chain 後會進入 POSTROUTING
。OUTPUT
iptables
的第一個階段就是 OUTPUT
chain。OUTPUT
chain 後會進入 POSTROUTING
chain。POSTROUTING
POSTROUTING
chain。SNAT
或 MASQUERADE
)。每個 table 所內建的 chain。
上圖是 iptables
的封包處理流程的簡單示意圖~
假如封包從某個 network interface 進來(incoming packet),且目的地是本機(local processing),那這個封包就會經過:
PREROUTING
chain
PREROUTING
chainPREROUTING
chain
PREROUTING
的 nat table 有可能會做 destination NAT、以變更目的地 addressINPUT
chain)、或者是要被轉發到某個 network interface(送往 FORWARD
chain)INPUT
chainINPUT
chain
INPUT
chain假如某個封包從 network interface 進來(incoming packet),但他的目的地不是本機、只是經過,最終會由某個 interface 出去(outgoing packet),那這個封包就會經過:
PREROUTING
chainPREROUTING
chainPREROUTING
chain
PREROUTING
的 nat table 有可能會做 destination NAT、以變更目的地 addressINPUT
chain)、或者是要被轉發到某個 network interface(送往 FORWARD
chain)FORWARD
chainFORWARD
chainFORWARD
chainPOSTROUTING
chainPOSTROUTING
chain
POSTROUTING
chain 的 nat table 可能會做 SNAT
或 MASQUERADE
以變更封包的 source address
SNAT
是將封包的 source address 修改成固定的 IP address。MASQUERADE
則是將封包的 source address 修改成他要出去的 network interface 的 IP address。假如某個封包是由本機產生(locally generated packet),然後經由 network interface 出去(outgoing packet),那這個封包就會經過:
OUTPUT
chainOUTPUT
chain
OUTPUT
chainOUTPUT
chain
OUTPUT
chain 的 nat table 有可能會做 destination nat,更改封包的目的地。OUTPUT
chainOUTPUT
chainOUTPUT
chain,準備進入 POSTROUTING
chain 之前,會先進行 re-route check,再重新計算一次路由
OUTPUT
chain 的 nat table 有可能會更改 destination address,所以才會需要再重新計算一次路由PS. 若封包是由 FORWARD
chain 到 POSTROUTING
chain,那就不會做 re-route check。
因為這樣子的封包,其流程是 PREROUTING
-> routing decision -> FORWARD
-> POSTROUTING
。
這樣的封包只有可能在 PREROUTING
chain 的 nat table 才有可能做 destination nat 更改目的地 address,當他結束 PREROUTING
chain 後就會做 routing decision,而 FORWARD
chain 裡面並沒有 nat table,不可能更改目的地 address,所以在進入 POSTROUTING
chain 前就不用做 re-route check。
POSTROUTING
chainPOSTROUTING
chain
POSTROUTING
chain 的 nat table 可能會做 SNAT
或 MASQUERADE
以變更封包的 source address
SNAT
是將封包的 source address 修改成固定的 IP address。MASQUERADE
則是將封包的 source address 修改成他要出去的 network interface 的 IP address。iptables
指令接下來簡單介紹一些比較常見的 iptables
指令~若要看更詳細的內容可以用 man iptables
指令查看。
上圖中第一類的指令是在指定的 table 中指定的 chain 做添加(A
ppend)、刪除(D
elete)、插入(I
nsert)規則的指令。
-A
:新添加的規則會放在指定的 table 的指定的 chain 的最後面。-D
:刪除某個規則,-I
:將新的規則插入指定的 table 的指定的 chain 的指定的位子,第二類的指令則可以新增(-N
)或刪除(-X
)使用者自訂義的 chain。
第三個指令則是可以設定指定的 table 的指定的 chain 的 policy。
最後一個則是可以列出指定的 table 的規則。
在設定 iptables
的時候都要有 root user 的權限,所以若是一般使用者的話記得指令前面都要加個 sudo
。
以上幾個指令,若沒有指定 table 的話,預設都會是對 filter table 做設定喔~
這張 slide 簡單介紹怎麼設定一個規則(後面會介紹幾個我自己有用過的規則~看例子應該會更好懂~)
首先~我們可以指定這條規則的參數,像是:
-p [!]protocol_name
:指定某個 protocol 的封包。若有加 !
則會變成指定「非」某某 protocol 的封包。-s [!]address[/mask]
:source address 是某某 address 的封包。-d [!]address[/mask]
:destination address 是某某 address 的封包。-j target
:符合這條規則的封包,要對他做的操作。-g chain
:符合這條規則的封包,跳到指定的 chain。-i [!]interface_name
:從某個 interface 進來的封包。-o [!]interface_name
:要從某個 interface 出去的封包。我們也要設定若某個封包符合規則,那要對這個封包做什麼操作(Target),像是:
ACCEPT
:讓這個封包通過DROP
:把這個封包丟掉,不處理它REJECT
:類似 DROP
,但還會送封包回去說這個封包被拒絕MASQUERADE
:將封包的 source address 改成他要出去的 interface 的 IP addressSNAT
:跟 MASQUERADE
一樣都會修改封包的 souce address,但 SNAT
是設定固定的 IP,MASQUERADE
則是依據指定的 network interface 的 IP 做設定。接下來介紹幾個自己有設定過的 iptables
指令~
這個指令的功能是:
nat
table 的 POSTROUTING
chain 的最後一個位子enp1s0
這個 network interface 出去的封包,都對他們做 MASQUERADE
,也就將他們的 source address 改成 enp1s0
network interface 的 IP address這個指令的功能是:
filter
table 的 INPUT
chain 的最後一個位子
filter
table 做操作喔這個指令的功能是:
filter
table 的 FORWARD
chain 的最後一個位子enx256e
這個 network interface 進來、且會從 enp1s0
這個 network interface 出去的封包,都讓他們通過這個指令的功能是:
filter
table 的 FORWARD
chain 的最後一個位子enp1s0
這個 network interface 進來、且會從 enx256e
這個 network interface 出去的封包,且若這些封包的狀態(state
)是已建立(ESTABLISHED
)連線的狀態,就讓這些封包通過前面用 iptables
指令所設定的規則,在每次重開機後都不會存在,若希望能保留每次設定的規則,可以用 iptables-persistent
這個工具。
安裝 iptables-persistent
:
每次設定完規則後就用以下指令儲存規則:
這樣的話規則就會被儲存在以下檔案,並且在每次開機時都將其載入:
此外,順便介紹另一個與 iptables -L -n
類似的指令,會將 iptables
的規則依序印出來:
iptables
設定接受/拒絕 ssh 連線若想簡單練習 iptables
的話,可以練習設定是否要接受/拒絕 ssh 連線~
若是 Ubuntu Desktop,需要先安裝 ssh server 這樣才能讓別人用 ssh 連進來,在 Ubuntu 的話主要都是安裝 openssh-server
:
用以下指令確認確認 openssh-server
是 active (running)
:
如果 Ubuntu 是虛擬機,且是 VirtualBox 虛擬機的話,記得要先對Ubuntu 虛擬機設定 Bridged Adaptor
,且 Name
選擇 MacBook 連到 Wi-Fi 的 interface en0
,這樣我的 Ubuntu 虛擬機就會跟我的 MacBook 在同一個 LAN 內:
首先,我的 MacBook 透過 Wi-Fi 介面被分配到的 IP 是 192.168.50.180:
Ubuntu 虛擬機被分配到的則是 192.168.50.241:
iptables
允許/拒絕 ssh 連線由於 ssh
通常都是用 Transmission Control Protocol (TCP),且 ssh server 是監聽 port 22。所以若要允許/拒絕別人用 ssh 連過來,就要對 iptables
的 filter
table 的 INPUT
chain 設定說,若有封包是用 TCP protocol、且該封包的 destination port 是 22,我們就接受/拒絕。
如果是要接受所有 ssh 連線,就做以下設定:
-t filter -A INPUT
:在 filter table 的 INPUT
chain 添加(A
ppend)新的規則-p tcp --dport 22 -j ACCEPT
:對於使用 tcp
protocol 且 destination port 是 22 的封包,允許這樣的封包通過若要拒絕所有 ssh 連線,可以做以下設定:
或
DROP
就是丟掉這封包不理他,發送 ssh 連線請求的 client 端會過一陣子得到 timed out 的訊息REJECT
則會發送一個拒絕的封包,讓發出 ssh 連線請求的 client 知道被拒絕了DROP
ssh 連線若用 iptables
將 ssh 連線請求的封包設定為 DROP
,並且用 tcpdump
查看是否有封包進來:
可以看到 MacBook 嘗試連過去時,並沒有收到被拒絕的訊息,而是過一段時間後出現 Operation timed out
的訊息,因為 Ubuntu 虛擬機的防火牆把這個封包丟掉而不處理它:
REJECT
ssh 連線若用 iptables
將 ssh 連線請求的封包設定為 REJECT
:
可以看到 MacBook 發送 ssh 連線請求後,會收到 Connection refused
的訊息:
接下來,在 LAN 裡面多加一個新的裝置,也就是我的 Marvell ESPRESSObin v7 開發板~他被分配到的 IP 是 192.168.50.141:
假設要設定只允許我的開發板的 IP 可以 ssh 連到 Ubuntu 虛擬機,不允許其他的 IP 來進來,就需要依序對 Ubuntu 虛擬機做以下設定:
這時候 rule 的順序就很重要!如果這兩條規則設定的順序反了,那封包一進到 INPUT
chain 的 filter table 就會先比對到「拒絕所有 ssh 連線請求的規則」,所以會連來自 192.168.50.141 的連線請求都一併拒絕喔~
以下是測試的結果~左上角的視窗是對 Ubuntu 虛擬機做 iptables
的設定,右下角的視窗則是開發板可以 ssh 連過去:
我的 MacBook 被拒絕,無法 ssh 連過去~
若將這兩條規則的順序設反了,那就會連開發板都沒辦法連過去喔:
iptables
相關設定