iptables實用知識 ,一文學會配置linux防火牆
- 2020 年 9 月 8 日
- 筆記
iptables實用知識 ,一文學會配置linux防火牆, 以自己實際使用情況來總結了iptables常用知識點
iptables 官方man文檔: //linux.die.net/man/8/iptables
iptables中文指南: //www.frozentux.net/iptables-tutorial/cn/iptables-tutorial-cn-1.1.19.html
(比較詳細,講了一些技術的實現原理, 版本舊,和centos7有點差異,我知道的是NAT時指定IP範圍,centos7不再支持自動循環使用指定的IP範圍,猜測只會使用第一個IP,沒做實驗)
說明:
本文測試基於系統環境: centOS 7
本文以實用的角度理解防火牆,不是官方文檔的知識點羅列。
1.防火牆的概念
計算機領域中防火牆一般指的是網絡(特指TCP/IP網絡)防火牆,根據TCP/IP網絡模型,防火牆可以處在不同的層,主要兩種:普通的網絡層防火牆,上層的應用防火牆,如WAF。
linux和windows操作系統中的防火牆,我們叫網絡層防火牆,準確的說應該是傳輸層的,因為會處理TCP, UDP端口號,而不僅僅是IP。
網絡層防火牆的作用: 包過濾,根據源IP,端口,目標IP端口,過濾數據包,允許通行或者禁止通行。
2. linux防火牆
linux防火牆由內核netfiter實現,用戶不能直接操作內核,提供了防火牆配置工具iptables和現在centos 7版本開始的firewalld工具,這兩個工具只是防火牆的配置接口,內核都是netfiter。
iptables配置命令複雜,原始,難度較大,但支持配置全部的功能。
而firewalld做了更高級的封裝,配置命令簡單,但無法實現複雜的配置,要實現複雜的配置需要用rich-rule(富規則),以及更高級的direct命令(和iptables命令幾乎一模一樣了)。
iptables的功能:
-
iptables是網絡層防火牆,必然支持基於ip和端口的過濾規則;
-
默認包過濾是沒有狀態的,即每個進出的數據包均視為一個獨立的數據包。
-
支持擴展模塊,通過擴展模塊可以實現許多高級的功能 ,常用如下:
- 支持基於狀態的,
- 連續ip
- 一條命令匹配多端口
- 連接數
- 速率限制
- 基於時間的規則
- 應用層數據過濾 ( 只的簡單的字符串匹配)
-
iptables防火牆的功能上還增加了修改數據包的功能,修改數據包最廣泛的應用應該是NAT了, iptables支持DNAT, SNAT , 如果同時使用DNAT, SNAT可以實現端口轉發的功能(後面有實例說明)。
iptables 的NAT是有狀態的NAT ,只需要配置發起請求時的轉換規則,而返回的數據會自動對應轉換回來。
-
其它更高級的修改數據包的應用沒研究過。
3.linux數據包處理流程
任何一個網絡主機處理數據必須有以下流程:
1.接收到數據:網卡接收到數據–> 路由判斷數據是否是本機->1,本機:轉給相應的上層應用 ->2, 目標不是本機, 再路由判斷通過哪個網卡轉發出去–>發出去
如果不允許數據轉發,數據目標不是本機則直接丟棄。
2.本機上層應用要發送數據出去: 應用數據轉給內核–> 路由判斷從哪個網口發送出去–>發出去
3.1 linux 防火牆將以上流程,固定區分為5個流程節點
- prerouting: 網卡收到數據
- input : 轉發數據給本機上層應用
- forward: 目標非本機數據進入轉發流程
- output: 本機應用發出的數據
- postrouting: 數據從網卡流出
3.2 數據流程
- 接收到目標為本機的數據: prerouting–> input
- 接收到目標不是本機的數據 ,prerouting–> forward –> postrouting
- 本機發出的數據:output –> postrouting
4 linux防火牆的實現機制
實現原理:在不同數據流程節點掛勾子函數,過濾數據, 符合的放回數據包流中,不符合條件的數據包從流程移除。
4.1 iptables五鏈
iptables將數據轉發的5個流程節點勾子依次對應為5個鏈,全部為大寫字母:
- PREROUTING
- INPUT
- FORWARD
- OUTPUT
- POSTROUTING
4.2 iptables四表
iptables將功能分為4類,即為iptables四表 :
實際有5個表,而不是我們常說的4表,還有一個表是security,本文不討論這個表。
- filter : 包過濾防火牆
- nat : 地址和端口轉換
- mangle : 數據包修改
- raw : 不帶連接狀態的nat
4.3 iptables 4表5鏈的關係
不同的表可以應用到不同的鏈上,
-
filter: INPUT 、FORWARD 、OUTPUT
-
過濾目標或本地為源的數據:接收-INPUT 、發出-OUTPUT
-
過濾經本機轉發的數據: FORWARD
-
-
nat : PREROUTING 、INPUT 、OUTPUT 、 POSTROUTING
- 修改本機上層應用發出去的數據: OUTPUT
2.1 SNAT: INPUT、 POSTROUTING
必須先路由, 所以不能在PREROUTING 做,在從本機發出前的最後一步再修改源IP為本機出接口IP,如果在路由前即剛接收到數據就修改源端口為出接口的IP是不合理的:
- 主機自己出接口IP的數據,從另一個網口接收到,網絡環路才會出現這種情況;
- 源IP變為出接口的IP,之後的處理流程看不到真實的源端口IP, 防火牆策略無法設置;
- 之後的流程,比如forward 看到源端口是自身的接口 ,按照內核數據轉發流程,本機應用發出的數據不應該進入forward流程。
2.2 DNAT: OUTPUT 、 PREROUTING
必須在路由前做DNAT, 這個好理解,只有DNAT修改數據報為真實的目標IP ,後面的路由才能正確選擇,因為源IP端口沒有修改,也不會影響之後流程處理。
2.3 總結: 一般 SNAT在POSTROUTING做,SNAT在PREROUTING 做 , OUTPUT是本機發出的數據,沒怎麼見過需要用到NAT的場景。
2.4 同時進行SNAT和DNAT
-
mangle : 5鏈均適用, 沒用過,不討論
-
raw :PREROUTING 、 OUTPUT,沒用過,不討論
4.4 表的優先級
同一鏈上,如果有多個表的配置規則,優先處理次序依次為raw –> mangle –> nat –> filter
5. iptables 命令
iptables 【-t 表名 】 操作 鏈名 【規則編號】 匹配規則 -j 處理動作
5.1 表 名
可選,不配置默認是 filter,
- filter
- nat
- mangle
- raw
5.2 操作
- -A 鏈中末尾添加規則
- -I 鏈名【規則編號】 如果沒有規則編號,插入到第一條的位置,有規則編號,插入到指定編號位置,原編號及之後的規則依次下移
- -R 鏈名 規則編號 必須輸入規則編號,替換該編號的規則
- -D 鏈名 規則編號 必須輸入規則編號,刪除該編號的規則
5.3 鏈名
不同表只能使用允許的鏈名
- PREROUTING
- INPUT
- FORWARD
- OUTPUT
- POSTROUTING
5.4 匹配條件
iptables命令最複雜的部分就在匹配條件這部分
一級條件參數形式 -option , 一級參數可能包含二級參數, 二級參數必須緊跟在主參數後寫, 形式為 –option 兩個 「–」
-
TCP/IP匹配條件,IP 和端口號
-
-s 源IP IP可以是單個IP , 也加掩碼 配置網段 如192.168.1.1/24, 但不能是連續ip, 如
192.168.1.1-192.168.1.20(連續ip需要擴展模塊) -
-d 目標IP IP可以是單個IP , 也加掩碼 配置網段 如192.168.1.1/24, 但不能是連續ip, 如
192.168.1.1-192.168.1.20
-
-
-i 網卡名 數據進入的網卡
-
-0 網卡名 數據流出的網卡
-
-p [!]協議名 tcp 、udp、icmp 等等, 指定協議名後才能進一步指定端口號,其實-p 會自動加載相應協議的擴展模塊,指定端口號是擴展模塊的功能。
-
–dport 源端口號 [!]port[:port] ,–source-port 的簡寫,可以是端口範圍
-
–sport 目標端口號 port[:port] –destination-port的簡寫, 可以是端口範圍
-
–tcp-flags [!] mask comp
-
mask comp 例 SYN,ACK,FIN,RST SYN 匹配 SYN標誌必須為1, ACK,FIN,RST必須為0, 其它標誌不檢查的數據包。
-
-
-m 擴展模塊
-
state 基於狀態的匹配規則, 與特定的協議沒有關係,可以是TCP, UDP , 狀態也不是指TCP協議連接狀態。
**對於TCP來說,第一個連接請求SYN包狀態為 NEW , 之後的全部為 ESTABLISHED 。 這個簡單的規則是非常有用的,用於區分連接發起的方向,是從內到外還是從外到內,而其它的匹配規則都無法識別連接的發起方向 **
這個模塊我認為是最有用的,關於內核如何跟蹤、標識各個協議的鏈接狀態,這個地址里有詳細的介紹://www.frozentux.net/iptables-tutorial/cn/iptables-tutorial-cn-1.1.19.html
- –state 狀態
- NEW 新發起的連接請求,第一次講求的數據報為NEW狀態
- ESTABLISHED 同一連接第一次請求之後的數據報均是該狀態
- RELATED 第一請求,但是該請求是由已建立的其它連接發起的,典型應用 FTP的數據傳輸,數據傳輸連接是由已建立的FTP控制連接發起的新連接,使用這個需要加載
- INVALID 無效數據包,數據包不合法
- –state 狀態
-
connlimit 連接數據限制,可以限制匹配規則的連接數量,比如限制SSH連接數據只能為3
- –connlimit-upto n 連接數小於等於n
- –connlimit-above n 連接數大於等於n
-
multiport 端口使用集合指定 ,最多15個,
- –sports port,port,port 或者 port:port 連續範圍的port
- –dports port,port,port 或者 port:port 連續範圍的port
-
iprange 指定ip地址範圍
- –src-range ip1-ip2
- –dst-range ip1-ip2
-
time 時間匹配
- –timestart 開始日期 yyyy-mm-ddThh:mm:ss 例 1990-01-01T11:30:00 注意J日期和時間中間有個大寫T,默認 1970-01-01T00:00:00
- –timestop 結束日期 yyyy-mm-ddThh:mm:ss 例 1990-01-01T11:30:00 注意J日期和時間中間有個大寫T,默認 2038-01-19T04:17:07
- –datestart 結束時間 hh:mm:ss 例 11:30:00, 默認00:00:00
- –datestop 結束時間 hh:mm:ss 例 11:30:00, 默認23:59:59
- –monthdays 日期 1-31, 可以是集合,如 1,2,5,9
- –weekdays 星期,1-7 , 可以是集合,如 1,3,5 1是星期一
-
limit 速率匹配 ,
使用令牌桶的算法,每個要轉發的數據包要獲取一個令牌才能轉發,沒有獲取令牌的包,不匹配該規則,會轉由下一條匹配,如果限速,緊跟後面要有一條規則丟棄數據。
- –limit rate n[/second|/minute/hour/day] 速率限制 , 單位時間允許生成的令牌數據,也即允許轉發的數據報數量, 注意: 不是帶寬,不是帶寬,當然通過限制包的數據也會間接限制了帶寬速率,包大小*包數=帶寬數。 默認3/hour
- –limit-burst n 初始令牌數據, 即初始允許不受限制發送的數據量,初始令牌用完,後面要等–limit 指定的單位時間生成的新令牌填充。
-
string 匹配應用層數據中的字符串, 只是簡單以字符串形式匹配應用層數據,不會識別應用協議,如果是加密的也不會解密,只能是應該層協議沒有加密時有用,比如http
–string pattern
-
5.5 處理動作 -j
處理動作全部用大寫字母
5.5.1 filter表動作
- ACCEPT 允許
- DROP 直接丟棄
- REJECT 拒絕 ,丟棄同時返回ICMP消息
- LOG 日誌記錄 , 不會終止規則匹配,也就是說該動作只記錄日誌,至於數據包是否被轉發,會繼續匹配後續規則
5.5.2 NAT 表動作
-
SNAT 源地址轉換
-
–to-source [ipaddr[-ipaddr]][:port[-port]][:port][-port] 可以指定端口範圍,如果不指定,默認儘可能不變更端口,但如果端口已經被其它鏈接佔用,會選用另一個端口替換,默認的端口轉換遵守以下規則:
- 1 . 512以內的端口,會轉換成512以內的端口,保證不會大於512
- 2 . 512-1023以內的端口,轉換為512-1024 ,保證不會大於1024
- 3 . 1024以上的端口,轉換為1024以上的端口
TCP/UDP 端口作用為了0-511, 512-1024,1024以上這三個段,以上規則與之對應,不會出現源端口佔用標準服務端口的情況:
比如,訪問外部http服務,把源端口轉換成了21 , 佔用了FTP的端口,導致端口混亂(雖然技術上說也能通)
-
-
DNAT 目標地址轉換
- –to-destination [ipaddr[-ipaddr]][:port[-port] 可以指定端口範圍,如果不指定,不變更端口,如果不指定IP, IP不會變更
- –random 端口轉換會隨機進行
Later Kernels (>= 2.6.11-rc1) 不再支持IP範圍內的輪訓轉換,這個功能常做負載均衡用,也就是說centos7 開始不支持這一功能了, 不知道什麼原因。
5.6 保存,恢復iptables配置
默認iptables配置規則只能當前生效,重啟就沒有了,需要用命令把規則放保存到文件,然後設置開機啟動腳本加載配置文件
- 保存 iptables-save > 文件名.rules
- 恢復 iptables-restore <文件名.rules
5.7 iptables 命令實例
-
查看當前規則
- -vL 詳細信息,可以-vvL 更詳細的信息
- –line-number 顯示規則編號
[root@localhost ~]# iptables -vL --line-number Chain INPUT (policy ACCEPT 9639 packets, 806K bytes) num pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 5388 packets, 2808K bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 8262 packets, 1684K bytes) num pkts bytes target prot opt in out source destination [root@localhost ~]#
-
查看nat表 , 沒有指定-t 默認filter表
[root@localhost ~]# iptables -t nat -vL --line-number Chain PREROUTING (policy ACCEPT 1281 packets, 105K bytes) num pkts bytes target prot opt in out source destination 1 6 312 DNAT tcp -- any any anywhere localhost.localdomain tcp dpt:rtsps to:192.168.31.12:22 Chain INPUT (policy ACCEPT 629 packets, 56218 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 296 packets, 22480 bytes) num pkts bytes target prot opt in out source destination Chain POSTROUTING (policy ACCEPT 296 packets, 22480 bytes) num pkts bytes target prot opt in out source destination 1 1 52 SNAT tcp -- any any 10.100.90.200 192.168.31.12 tcp dpt:ssh to:192.168.31.1:1023 2 686 50843 SNAT all -- any any 192.168.31.0/24 anywhere to:10.100.93.202
-
清空規則
- -F 清空規則
[root@localhost ~]# iptables -t nat -F [root@localhost ~]# iptables -t nat -vL --line-number Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination [root@localhost ~]#
-
開放本地端口80
沒有用 -A 是因為表中已有其它規則,一般最後一條是默認規則,實際中往往是插入到第一條比較常見
-
插入到第2條
iptables -t filter -I INPUT 1 -p tcp --dport 80 -j ACCEPT
-
插入到第2條
iptables -t filter -I INPUT 2 -p tcp --dport 80 -j ACCEPT
-
替換第2條
iptables -t filter -R INPUT 2 -p tcp --dport 80 -j ACCEPT
-
只允許指定源IP訪問
iptables -t filter -R INPUT 2 -s 192.168.1.1 -p tcp --dport 80 -j ACCEPT
-
-
通過狀態匹配防火牆
-
禁止本機主動發起的出站連接 (服務器上可以這麼設置,因為服務器是讓別人訪問自身 ,而自己本身不需要發起對外的連接,可以防止反彈木馬)
iptables -t filter -I OUTPUT -m multiport -m state --state NEW -j DROP
-
允許(非本機主動發起的)外部主機主動發起的對本機的連接
iptables -t filter -I OUTPUT -m multiport -m state --state ESTABLISHED,RELATED -j DROP
-
-
SNAT 代理上網, 允許源地址192.168.1.0/24 經本機上網 10.100.93.202為連通公網的IP
iptables -t nat -I POSTROUTING -s 192.168.1.0/24 -j SNAT --to-source 10.100.93.202
-
DNAT 將目標為本機IP 10.100.93.202 ,目標端口為 80 的數據轉發到後端真實服務器 192.168.1.10的8000端口去
iptables -t nat -I PREROUTING -d 192.168.1.0/24 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.0:8000
-
接合 SNAT和DNAT實現端口轉發
SNAT在數據發出時轉換IP為本機出接口,DNAT在接收到數據時轉換目標IP為後端真實服務器IP ,組合這兩個特性,可以實現端口轉發的功能。
假如有如下場景:
在外網的用戶能訪問到防火牆外網IP 10.100.0.20
防火牆內網IP和內網服務器可以互通,同時內網服務器與外網隔離,不能通信
用戶要想直接訪問內網服務器的一個端口。
解決方法:
-
此場景不能只用DNAT, 因為內網服務器與外網不通,返回給user的數據是無法出內網的。
-
user只能與防火牆能,數據包的源地址必須是防火牆的,所以還需要SNAT, 在從防火牆內網口發出時轉換源地址為192.168.0.20 , 內網服務器返回數據,自然目標地址也就是192.168.0.20。
-
iptables nat是有鏈接狀態的,返回的數據會自動反向轉換,返回的數據經由以下過程:
-
防火牆內網口192.168.0.20 收到數據時,返向轉換目標IP為真實的USER , 經路由後,由公網口
-
10.100.0.20發出時,反向轉換源端口為防火牆自身端口 10.100.0.20.
-
通信完成。
此過程即為端口轉發,當然有很多開源軟件可以實現端口轉發,但linux防火牆全部是在內核完成這些操作的,而使用其它軟件自然數據是要經過用戶空間,而且需要在公網端口建立tcp/udp監聽才可以。
配置:
內網服務器端口22, 防火牆用端口 13322轉發:
# DNAT
iptables -t nat -I PREROUTING -d 10.100.0.20 -p tcp --dport 13222 -j DNAT --to-destination 192.168.0.10:22
# SNAT
iptables -t nat -I POSTROUTING -d 192.168.0.10 --dport 22 -j SNAT --to-source 192.168.0.20
5.8 iptables防火牆配置最佳實踐
-
防火牆建議用白名單機制,即默認禁止所有,只明確放行需要放行的流量,
- 不推薦 使用iptables 的 -P DROP 操作設置為默認禁止,
- 推薦在鏈的最後一條規則設置為禁止所有
原因:使用-P 設置為默認禁止,那麼調試規則時不小心清空了防火牆,自己豈不是被關在了門外, 排查連接問題時,有時需要臨時清空規則,放行所有流量,來判斷是否因為防火牆阻止了連接。
-
被流量匹配到的頻率和可能性越大,規則越要往前面放,這樣能提高效率,防火牆的機制是從上向下順序匹配,配置到一條規則時,不再繼續向下匹配(此處說的是常規流量處理動作,如ACCEPT, DROP, REJECT, SNAT,DNAT, 像LOG還是會繼續向下匹配的)
-
建議使用擴展模塊state設置有狀態的防火牆,安全性更高(因為能認識是誰主動發起的連接),配置規則更簡化。
- 默認允許所有ESTABLISHED、RELATED、狀態連接,
- 禁止所有INVALID 無效的數據包
- 通過狀態NEW 控制數據發起的方向和IP,端口等。