Iptables教程
iptables
是一個配置 Linux 內核 防火牆 的命令行工具。
初學者剛看到iptables,會感到很複雜,原因是 iptables 功能實在是太強大了。本文會從基本概念、使用上做介紹,讀者看完後再去看 iptables 命令就能理解其含義了。
本文環境:
PC: Ubuntu18
iptables操作均在docker上進行。docker上的系統為centos6.9。
更新時間:2020.6.26
工作原理
基本組成
想要掌握 iptables ,需要了解其原理。
iptables 組成:
Tables -> Chains -> Rules
表 (tables):
filter
nat
mangle
raw
每個 tables 有多個鏈 (Chains):
(圖片來自: //phoenixnap.com/)
其中鏈是可以自定義新建的,後文會介紹。
最終我們會對某個鏈添加 規則(rules) 。下面是一條由具體的指令,包含了 tables、chains、rules:
# 禁止172.18.0.3訪問
iptables -t filter -A INPUT -s "172.18.0.3" -j DROP
注:
-t filter
指的是指定對filter
表操作,可以省略,默認就是filter
表。本條指令看不懂也沒有關係,後文還會出現。
功能介紹
下面介紹各個表、鏈的基本功能。我們實際使用最多的是Filter表、NAT表,所以本文主要也是介紹這2個表。
Filter表
Filter表示iptables的默認表,如果沒有自定義表,那麼就默認使用filter表,它具有以下三種內建鏈:
- INPUT鏈 – 處理來自外部的數據。
- OUTPUT鏈 – 處理向外發送的數據。
- FORWARD鏈 – 將數據轉發到本機的其他網卡設備上。
NAT表
NAT表有三種內建鏈:
- PREROUTING鏈 – 處理剛到達本機並在路由轉發前的數據包。它會轉換數據包中的目標IP地址(destination ip address),通常用於DNAT(destination NAT)。
- POSTROUTING鏈 – 處理即將離開本機的數據包。它會轉換數據包中的源IP地址(source ip address),通常用於SNAT(source NAT)。
- OUTPUT鏈 – 處理本機產生的數據包。
Mangle表
Mangle表用於指定如何處理數據包。它能改變TCP頭中的QoS位。Mangle表具有5個內建鏈:
- PREROUTING
- OUTPUT
- FORWARD
- INPUT
- POSTROUTING
Raw表
Raw表用於處理異常,它具有2個內建鏈:
- PREROUTING chain
- OUTPUT chain
數據包流向
下圖簡要描述了網路數據包通過 iptables 的過程:
(來自//wiki.archlinux.org/)
1、數據經由互聯網到達 nat 表的 PREROUTING;
2、數據到達 filter表的INPUT;
3、數據到達 本機;
4、數據經由 filter表的OUTPUT;
5、數據經由 nat 表的 POSTROUTING;
6、數據到達互聯網。
7、我們也可以在數據到達 nat 表的 PREROUTING後,使用 filter表的FORWARD進行轉發。
理解數據包流向很重要,這樣我們就能很清楚的知道在哪個表哪個鏈增加對應的規則。
安裝iptables
iptables在大多數Linux系統上默認安裝,可以在命令行輸入iptables --version
查看:
iptables --version
iptables v1.6.1
如果沒有該命令,可以自行安裝:
# ubuntu
sudo apt-get install iptables
sudo apt-get install iptables-persistent
# centos6
sudo yum –y install iptables-services
# centos7
# 在CentOS 7中,iptables替換為firewalld。
# 要安裝iptables,首先您需要停止firewalld。輸入以下命令:
sudo systemctl stop firewalld
sudo systemctl disable firewalld
sudo systemctl mask firewalld
# 接下來,安裝並啟用iptables。首先,使用以下命令安裝iptables服務軟體包:
sudo yum –y install iptables-services
sudo systemctl enable iptables
sudo systemctl start iptables
如果需要在 docker 上體驗 iptables :
# pull
docker pull daocloud.io/library/centos:centos6.9
docker tag daocloud.io/library/centos:centos6.9 centos6.9
# 啟動需要加上 -privileged
docker run -it --privileged --name centos-1 centos6.9 /bin/bash
# 安裝iptables
yum install initscripts
配置命令
iptables命令參數非常多。我們分為:配置命令、匹配條件、動作選項、模組選項,這樣便於記憶。
-
配置命令 指的
ACDIF
等命令,都是大寫開頭的簡稱,且一般不可省略,例如-A
新增規則、-D
刪除規則。 -
匹配條件 一般是小寫,例如
-t
指定table,-i
指定網卡介面,這些條件一般是可選的。 -
動作選項 指的是
-j
指定的動作,可選值有:DROP、ACCEPT等。 -
模組選項 指的是
-m
指定的參數。
本節主要介紹配置命令。
iptables配置命令如下所示:
iptables [option] CHAIN_rule [-j target]
以下是一些常用iptables選項的列表:
–A, ––append
將規則添加到鏈中(最後)。–I, ––insert
將規則添加到給定位置的鏈中。–C, ––check
尋找符合鏈條要求的規則。–D, ––delete
從鏈中刪除指定的規則。–F, ––flush
刪除對應表的所有規則,慎重使用。–L, ––list
連鎖顯示所有規則。–v, ––verbose
使用列表選項時顯示更多資訊。-P, --policy
設置鏈的默認策略(policy)-N, --new
創建用戶自定義鏈-X, --delete-chain
刪除用戶自定義鏈-E, --rename-chain
重命名用戶自定義鏈
iptables區分大小寫,因此請確保使用正確的選項。更多參數可以輸入iptables --help
查看。
查看規則(-L)
# 查看filter表的規則
iptables –L
# 同iptables –L
# -t條件指定table
iptables -t filter –L
上述命令執行後,系統顯示鏈條的狀態。輸出將列出三個鏈:
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP all -- 172.18.0.4 anywhere
DROP all -- 172.18.0.5 anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
FORWARD、OUTPUT為空,沒有定義規則;INPUT有三條規則:禁止來自 172.18.0.4 -172.18.0.5 任何協議的請求,相當於加了黑名單。
# 更詳細的輸出
# -n 以數字的形式展示地址和埠
# -v 啰嗦模式
# --line-numbers 列印鏈的序號,後面刪除需要用到該序號。最先添加的規則序號最小
iptables -vnL --line-numbers
輸出示例:
Chain INPUT (policy ACCEPT 9 packets, 621 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 DROP all -- eth0 * 172.18.0.4 0.0.0.0/0
2 0 0 DROP all -- eth0 * 172.18.0.5 0.0.0.0/0
...
新增規則(-A)
-A <鏈名>
APPEND,追加一條規則(放到最後)
示例:
# -i條件指定網卡介面
# -s條件指定數據包的源地址
# -j指定動作選項為DROP,丟棄數據
iptables -A INPUT -i eth0 -s 172.18.0.3 -j DROP
上面的命令會在 filter 表的 INPUT 鏈里追加一條規則:對於來自172.18.0.3
經由 eth0
介面的數據,直接丟棄。
我們可以在另一台機器 172.18.0.3
訪問當前機器:
$ ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
...
發現訪問被拒絕了。
# 將eth0的數據路由到eht1
iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT
刪除規則(-D)
可以按規則號或者規則內容匹配。默認filter
表。
-D <鏈名> <規則號碼 | 具體規則內容>
DELETE,刪除一條規則
先查看規則:
$ iptables -L --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 172.18.0.4 anywhere
2 DROP all -- 172.18.0.5 anywhere
3 DROP all -- 172.18.0.6 anywhere
4 DROP all -- 172.18.0.3 anywhere
...
1、按規則號(num)刪除規則3:
將刪除 filter 表 INPUT 鏈中的第三條規則(不管它的內容是什麼)
$ iptables -D INPUT 3
$ iptables -L --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 172.18.0.4 anywhere
2 DROP all -- 172.18.0.5 anywhere
3 DROP all -- 172.18.0.3 anywhere
...
2、按內容匹配刪除:
刪除 filter 表 INPUT 鏈中內容為-s 172.18.0.5 -i eth0 -j DROP
的規則 (不管其位置在哪裡)
$ iptables -D INPUT -s 172.18.0.5 -i eth0 -j DROP
$ iptables -L --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 172.18.0.4 anywhere
2 DROP all -- 172.18.0.3 anywhere
...
建議還是指定規則號刪除,以免誤刪。
插入規則(-I)
最終也是實現規則的新增。需要指定規則號,默認的規則號是1,也就是插入到第1條。默認filter
表。
-I <鏈名> [規則號碼]
INSERT,插入一條規則
$ iptables -I INPUT 3 -s 172.18.0.6 -j DROP
$ iptables -L --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 172.18.0.4 anywhere
2 DROP all -- 172.18.0.3 anywhere
3 DROP all -- 172.18.0.6 anywhere
...
注意:
- 規則號碼必須緊跟著
-I INPUT
。 - 規則號碼如果預設,那麼就是1,插入的規則成為第1條規則。
- 規則號碼最大值是已有規則數+1。
小結:-A
是在所有的規則的最後面增加規則,而-I
可以在任意位置增加規則。
替換規則(-R)
-R <鏈名> <規則號碼> <具體規則內容>
REPLACE,替換一條規則
命令格式和-I
類似。
$ iptables -R INPUT 3 -s 172.18.0.6 -j ACCEPT
$ iptables -L --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 172.18.0.4 anywhere
2 DROP all -- 172.18.0.3 anywhere
3 ACCEPT all -- 172.18.0.6 anywhere
...
設置默認規則(-P)
用於某個鏈的默認規則。當數據包沒有被規則列表裡的任何規則匹配到時,按此默認規則處理。可選值: DROP、ACCEPT。
-P <鏈名> <動作>
POLICY,設置某個鏈的默認規則
兩種默認策略導致的不同結果:
- 默認策略DROP,需要逐條允許。一般伺服器上都是這麼設置的,僅開放部分埠或者白名單,其他全部拒絕。
- 默認策略ACCEPT,需要逐條拒絕。
配置默認鏈策略為拒絕:
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP
如果防火牆之前沒有任何配置,當上面的命令執行後,如果你當前是使用ssh
連接的伺服器,你會發現你被踢出來了,然後連不上了。。。
所以:遠程設置時不要一開始就寫這幾句默認策略,會把自己踢出伺服器,應該最後設定。
清除規則(-F)
清除所有規則。可以指定表、鏈。默認filter
表。
iptables -F
將清除fliter
錶鏈中所有規則,但並不影響 -P
設置的默認規則。其它示例:
# 清空 filter 表 INPUT 鏈中的所有規則
iptables -t filter -F INPUT
-P
設置了DROP
後,使用-F
一定要小心。因為相當於把所有ACCEPT的都清除了,會導致ssh連接不上。- 如果不寫鏈名,默認清空某表裡所有鏈里的所有規則。
保存規則
用iptables命令寫的規則都是立即生效的,但只是臨時的。
我們可以使用iptables-save
查看系統現在有哪些規則。該命令不同於iptables -L
,可以列印出所有的規則,而且與我們輸入的是一樣的:
$ iptables-save
# Generated by iptables-save v1.4.7 on Thu Jun 25 10:53:55 2020
*nat
:PREROUTING ACCEPT [3817:370531]
:INPUT ACCEPT [2:168]
:OUTPUT ACCEPT [56:3864]
:POSTROUTING ACCEPT [112:7728]
:DOCKER_OUTPUT - [0:0]
:DOCKER_POSTROUTING - [0:0]
-A PREROUTING -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.18.0.3:80
-A PREROUTING -p tcp -m tcp --dport 81 -j DNAT --to-destination 172.18.0.3:80
...
*filter
:INPUT ACCEPT [3278:275037]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [3278:275037]
...
該命令執行後並不會保存,我們可以直觀的看到各表有哪些鏈、哪些規則。需要注意的是列印出的規則省略了iptables -t xxx
命令。
CentOS6.9可以使用service iptables save
命令保存臨時防火牆規則:
$ service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[ OK ]
該命令保存的內容就是我們使用iptables-save
列印出來的內容。
如果系統使用的systemd,上述的操作可能無效。
其他系統參考:
匹配條件選項
-p 協議類型 (–protocol)
用於指定規則的協議,如tcp, udp, icmp等,可以使用all
來指定所有協議。如果不指定-p
參數,則默認是all
值。
也可以使用協議名(如tcp),或者是協議值(比如6代表tcp)來指定協議。映射關係請查看/etc/protocols
。
# 禁止目標IP的ping協議
iptables -A INPUT -s 172.18.0.3 -p icmp -j DROP
注意:因為禁用了從172.18.0.3(簡稱B機器)來的icmp協議,那麼當前機器也不能ping通機器B,原因是收不到響應數據。但是機器B確實能收到請求,可以在機器B上執行抓包
tcpdump -i eth0 icmp
。
-s 源地址 (–source)
用於指定數據包的源地址。參數可以使IP地址、網路地址、主機名。例如:
-s 192.168.0.1
匹配來自 192.168.0.1 的數據包-s 192.168.1.0/24
匹配來自 192.168.1.0/24 網路的數據包-s 192.168.0.0/16
匹配來自 192.168.0.0/16 網路的數據包! -s 192.168.1.101
除這個IP外
如果不指定-s
參數,就代表所有地址。
192.168.1.10/24
代表192.168.1.0-192.168.1.255網段,24表示網路號佔用24位二進位,剩餘8位二進位可以表示 2^8位主機。可以使用//www.sojson.com/convert/subnetmask.html 工具計算網段。
-d 目的地址 (–destination)
用於指定目的地址。參數和-s
相同。
例如:
-d 202.106.0.20
匹配去往 202.106.0.20 的數據包-d 202.106.0.0/16
匹配去往 202.106.0.0/16 網路的數據包-d www.abc.com
匹配去往域名 www.abc.com 的數據包
-j 執行目標 (–jump)
用於指定target。可能的值是ACCEPT, DROP, QUEUE, RETURN。也可以指定鏈(Chain)作為目標。後文會細講。
-i 輸入介面 (–in-interface)
用於指定要處理來自哪個介面的數據包,這些數據包即將進入INPUT, FORWARD, PREROUTE鏈。
例如:
-i eth0
指定了要處理經由eth0
進入的數據包。- 如果不指定
-i
參數,那麼將處理進入所有介面的數據包。 - 如果出現
! -i eth0
,那麼將處理所有經由eth0
以外的介面進入的數據包。 - 如果出現
-i eth +
,那麼將處理所有經由eth
開頭的介面進入的數據包。
-o 輸出 (–out-interface)
用於指定數據包由哪個介面輸出,這些數據包即將進入FORWARD, OUTPUT, POSTROUTING鏈。
- 如果不指定
-o
選項,那麼系統上的所有介面都可以作為輸出介面。 - 如果出現
! -o eth0
,那麼將從eth0
以外的介面輸出。 - 如果出現
-i eth +
,那麼將僅從eth
開頭的介面輸出。
–sport 源埠 (–source-port)
針對-p tcp
或者 -p udp
,不可單獨使用。
可以指定埠號或者埠名稱,例如–sport 22
與–sport ssh
,/etc/services
文件描述了上述映射關係。但從性能上講,使用埠號更好。
使用冒號可以匹配埠範圍,如–sport 22:100
。
例如:
--sport 1000 匹配源埠是 1000 的數據包
--sport 1000:3000 匹配源埠是 1000-3000 的數據包(含1000、3000)
--sport :3000 匹配源埠是 3000 以下的數據包(含 3000)
--sport 1000: 匹配源埠是 1000 以上的數據包(含 1000)
# 允許外部的來自80埠的數據訪問本地伺服器
iptables -A INPUT -p tcp --sport 80 -j ACCEPT
–dport 目的埠 (–destination-port)
針對-p tcp
或者 -p udp
。參數和–sport
類似。
# 允許外部數據訪問本地伺服器80埠
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
–tcp-flags TCP標誌
針對-p tcp
。可以指定由逗號分隔的多個參數。有效值可以是:SYN, ACK, FIN, RST, URG, PSH。可以使用ALL
或者NONE
。
-–icmp-type ICMP類型
針對-p icmp
。
–icmp-type 0
表示 pong–icmp-type 8
表示 ping
動作選項
-j
參數支援下列動作選項:
- ACCEPT
- DROP
- DNAT
- SNAT
- MASQUERADE
- RETURN
ACCEPT
允許數據包通過本鏈而不攔截它。
例如:
# 允許來源地址為 172.18.0.3 的數據包進入本機
iptables -A INPUT -s 172.18.0.3 -j ACCEPT
DROP
阻止數據包通過本鏈,直接丟棄它。
例如:
# 阻止來源地址為 172.18.0.3 的數據包通過本機
iptables -A INPUT -s 172.18.0.3 -j DROP
DNAT
目的地址轉換。
1、原理:在路由前(PREROUTING)將來自外網訪問網關公網ip及對應埠的目的ip及埠修改為內部伺服器的ip及埠,實現發布內部伺服器。
2、應用場景:發布內部主機服務。
3、設置DNAT:網關主機上設置。
DNAT 支援轉換為單 IP,也支援轉換到 IP 地址池(一組連續的 IP 地址)。
編寫防火牆規則:
-j DNAT --to-destination 內網服務ip:埠
--to-destination
等同於--to
。
例如:
# 把流入eth0 要訪問 TCP/80 的數據包目的地址轉發到 172.18.0.3
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to 172.18.0.3
# 把從 eth0 進來的要訪問 TCP/81 的數據包目的地址改為 172.18.0.3:80
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 81 -j DNAT --to 172.18.0.3:80
# 把從 eth0 進來的要訪問 TCP/80 的數據包目的地址改為地址池 172.18.0.3-172.18.0.10
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to 172.18.0.3-172.18.0.10
DNAT
作用於PREROUTING
鏈,如果寫POSTOUTING
,會報錯。
SNAT
源地址轉換。
1、原理:在路由器後(POSTROUTING)將內網的ip地址修改為外網網卡的ip地址。
2、應用場景:共享內部主機上網。
3、設置SNAT:網關主機進行設置。
源地址轉換即內網地址向外訪問時,發起訪問的內網ip地址轉換為指定的ip地址(可指定具體的服務以及相應的埠或埠範圍),這可以使內網中使用保留ip地址的主機訪問外部網路,即內網的多部主機可以通過一個有效的公網ip地址訪問外部網路。
SNAT 支援轉換為單 IP,也支援轉換到 IP 地址池(一組連續的 IP 地址)。
-j SNAT --to IP[-IP][:埠-埠](nat 表的 POSTROUTING 鏈)
例如:
# 將 172.18.0.3 的原地址修改為 172.18.0.2
iptables -t nat -A POSTROUTING -p tcp --dport 80 -d 172.18.0.3 -j SNAT --to 172.18.0.2
iptables -t nat -A POSTROUTING -p tcp --dport 80 -d 172.18.0.3 -j MASQUERADE
# 將內網 172.18.0.1/24 的原地址修改為 1.1.1.1
iptables -t nat -A POSTROUTING -d 172.18.0.1/24 -j SNAT --to 1.1.1.1
# 同上,只不過修改成一個地址池裡的 IP
iptables -t nat -A POSTROUTING -d 172.18.0.1/24 -j SNAT --to 1.1.1.1-1.1.1.10
MASQUERADE
動態源地址轉換(動態 IP 的情況下使用)。
上面的小節里,配置SNAT的時候:
iptables -t nat -A POSTROUTING -p tcp --dport 80 -d 172.18.0.3 -j SNAT --to 172.18.0.2
需要指定映射的目標地址-to 172.18.0.2
。也可以使用MASQUERADE
動態獲取:
iptables -t nat -A POSTROUTING -p tcp --dport 80 -d 172.18.0.3 -j MASQUERADE
如果IP地址不是固定的,使用這種方式會比較方便。
RETURN
返回主鏈繼續匹配。
比如:
# 如果請求的目標地址是本機的地址, 那麼將請求轉到 DOCKER 鏈處理
iptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
# 由 docker0 設備傳入的請求 DOCKER 鏈會返回上一層處理
iptables -t nat -A DOCKER -i docker0 -j RETURN
這兩條規則將改變原有的數據包流向,會在 PREROUTING 前增加一個 DOCKER 鏈:
模組選項
-m
參數支援模組選項。
- state: 按包狀態匹配
- mac: 按來源 MAC 匹配
- limit: 按包速率匹配
- multiport: 多埠匹配
- iprange: 按IP範圍匹配
- string 按字元串限定
state
按包狀態匹配。
格式:
-m state --state 狀態
狀態:NEW、RELATED、ESTABLISHED、INVALID
- NEW:新建連接請求的數據包,且該數據包沒有和任何已有連接相關聯。
- ESTABLISHED:該連接是某NEW狀態連接的回包,也就是完成了連接的雙向關聯。
- RELATED:衍生態,與 conntrack 關聯。簡而言之,A連接已經是ESTABLISHED,而B連接如果與A連接相關,那麼B連接就是RELATED。
- INVALID:匹配那些無法識別或沒有任何狀態的數據包。這可能是由於系統記憶體不足或收到不屬於任何已知連接的ICMP錯誤消息,也就是垃圾包,一般情況下我們都會DROP此類狀態的包。
例如:
# 拒絕訪問防火牆的新數據包,但允許響應連接或與已有連接相關的數據包
iptables -A INPUT -p tcp -m state --state NEW -j DROP
iptables -A INPUT -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT
conntrack
按包狀態匹配。conntrack是state的擴展版本(內核版本>=2.5開始支援),包括狀態參數也是基本相同。
狀態:NEW、RELATED、ESTABLISHED、INVALID、UNTRACKED 。前面的幾個上一節介紹了,這裡說一下UNTRACKED。
- UNTRACKED : 這是一種特殊狀態,或者說並不是狀態。它是管理員在raw表中,為連接設置NOTRACK規則後的狀態。這樣做,便於提高包過濾效率以及降低負載。
-m conntrack --ctstate 狀態
示例:
# FORWARD 鏈的請求如果目標是 docker0 所在的網段, 而且已經建立的連接或者和已建立連接相關那麼接受請求
iptables -A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
mac
匹配某個 MAC 地址。
格式:
-m mac --mac-source MAC
例如:
# 阻斷來自某 MAC 地址的數據包通過本機
iptables -A FORWARD -m --mac-source xx:xx:xx:xx:xx:xx -j DROP
注意:MAC 地址不過路由,不要試圖去匹配路由後面的某個 MAC 地址。
limit
啟用limit擴展,限制速度。用一定速率去匹配數據包。
格式:
-m limit --limit 匹配速率 [--burst 緩衝數量]
-m limit --limit 25/minute: 允許最多每分鐘25個連接
-m limit --limit-burst 100: 當達到100個連接後,才啟用上述25/minute限制
例如:
iptables -A FORWARD -d 192.168.0.1 -m limit --limit 50/s -j ACCEPT
iptables -A FORWARD -d 192.168.0.1 -j DROP
注意:limit
僅僅是用一定的速率去匹配數據包,並非 限制
。
multiport
一次性匹配多個埠,可以區分源埠,目的埠或不指定埠。
格式:
-m multiport <--sports|--dports|--ports> 埠1[,埠2,..,埠n]
例如:
iptables -A INPUT -p tcp -m multiports --ports 21,22,25,80,110 -j ACCEPT
注意:必須與 -p
參數一起使用。
iprange
指定IP範圍。
格式:
-m iprange --src-range
-m iprange --dst-range
示例:
# 過濾源地址範圍
iptables -A INPUT -m iprange --src-range 192.168.1.2-192.168.1.7 -j DROP
# 過濾目標地址範圍
iptables -A INPUT -m iprange --dst-range 192.168.1.2-192.168.1.7 -j DROP
string
按字元串限定。格式:
-m string --string "STRING" --algo kmp 指定字元串本身
其中--algo
指定匹配演算法:bm或kmp。
addrtype
按地址類型匹配。格式:
-m addrtype --dst-type 地址類型
支援的地址類型:
- UNSPEC
- UNICAST
- LOCAL 匹配本機地址
- BROADCAST 匹配廣播地址
- ANYCAST
- MULTICAST
- BLACKHOLE
- UNREACHABLE
- PROHIBIT
- THROW
- NAT
- XRESOLVE
使用
iptables -m addrtype --help
可以查看類型列表。地址類型部落客也沒有完全明白都是什麼作用,後面遇到了再補。
示例:
# 如果請求的目標地址是本機的地址, 那麼將請求轉到 DOCKER 鏈處理
iptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
自定義鏈
iptables的默認鏈就已經能夠滿足我們了,為什麼還需要自定義鏈呢?原因如下:
當默認鏈中的規則非常多時,不方便我們管理。
例如,如果INPUT鏈中存放了幾十條規則,這幾十條規則有針對http服務的,有針對sshd服務的,有針對私網IP的,有針對公網IP的,假如,我們突然想要修改針對http服務的相關規則,難道我們還要從頭看一遍這幾十條規則,找出哪些規則是針對http的嗎?這顯然不合理。
所以,iptables中,可以自定義鏈,通過自定義鏈即可解決上述問題。
現在,我們自定義一個名為 WEB 的鏈,實現:
- 轉發當前機器80埠流量到172.18.0.3:80
- 80埠流量交由WEB管理;且禁止IP: 192.168.2.194 訪問80埠
為了實現上面的規則,需要分別在filter表和nat表增加 自定義鏈 WEB:
# *filter
# 新建WEB鏈
iptables -t filter -N WEB
# WEB鏈增加一條規則:禁止IP: 192.168.2.194 訪問80埠
iptables -t filter -A WEB -s 192.168.2.194 -j DROP
# 80埠流量使用WEB鏈規則處理
iptables -t filter -A INPUT -p tcp --dport 80 -j WEB
# *nat
# 新建WEB鏈
iptables -t nat -N WEB
# 埠轉發
iptables -t nat -A WEB -p tcp --dport 80 -j DNAT --to 172.18.0.3:80
# tcp:80埠PREROUTING、POSTROUTING流量交由WEB處理
iptables -t nat -A PREROUTING -p tcp --dport 80 -j WEB
iptables -t nat -A POSTROUTING -p tcp --dport 80 -j SNAT -d 172.18.0.3 --to 172.18.0.2
查看生成的規則:
$ iptables-save
*nat
:PREROUTING ACCEPT [1:73]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [1:72]
:POSTROUTING ACCEPT [1:72]
:WEB - [0:0]
-A PREROUTING -p tcp -m tcp --dport 80 -j WEB
-A POSTROUTING -d 172.18.0.3/32 -p tcp -m tcp --dport 80 -j SNAT --to-source 172.18.0.2
-A WEB -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.18.0.3:80
COMMIT
*filter
:INPUT ACCEPT [1:97]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1:72]
:WEB - [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j WEB
-A WEB -s 192.168.2.194/32 -j DROP
常見規則示例
啟用環迴流量
允許來自您自己的系統(本地主機)的流量:
iptables -A INPUT -i lo -j ACCEPT
此命令將防火牆配置為接受localhost(lo
)介面(-i
)的通訊。現在,源自系統的所有內容都將通過防火牆。需要設置此規則,以允許應用程式與localhost介面通訊。
簡易防火牆
該規則默認拒絕所有INPUT鏈,允許:
- loop迴環網卡流量
- 連接狀態為RELATED,ESTABLISHED的連接
- 80, 22, 21 埠
iptables -F
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -P INPUT DROP
註:如果設置了默認規則iptables -P OUTPUT DROP
,那麼對應的ACCEPT需要增加-A OUTPUT
的指令:
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT
iptables -P INPUT DROP
iptables -P OUTPUT DROP
IP黑名單
禁止172.18.0.3訪問。
iptables -A INPUT -i eth0 -s 172.18.0.3 -j DROP
埠轉發
172.18.0.2 機器80埠流量轉發到 172.18.0.3 機器80埠。這樣很簡單的實現了流量轉發。需要在
172.18.0.2 機器配置規則:
# iptables -t nat -F
# 流入當前機器80埠tcp流量轉發到172.18.0.3:80
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to 172.18.0.3:80
# 流出當前機器80埠tcp流量源地址修改為172.18.0.2
iptables -t nat -A POSTROUTING -p tcp --dport 80 -d 172.18.0.3 -j SNAT --to 172.18.0.2
# 或者使用下面的命令: 目標IP地址自動獲取
# iptables -t nat -A POSTROUTING -p tcp --dport 80 -d 172.18.0.3 -j MASQUERADE
docker防火牆配置
安裝docker後會在宿主機增加規則,實現埠映射、docker內部連接外網。
NAT 表改動的解析如下:
# DOCKER 鏈
:DOCKER - [0:0]
# 如果請求的目標地址是本機的地址, 那麼將請求轉到 DOCKER 鏈處理
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
# 如果請求的目標地址不匹配 127.0.0.0/8, 並且目標地址屬於本機地址, 那麼將請求跳轉到 DOCKER 鏈處理
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
# 對於來自於 172.17.0.0/16 的請求, 目標地址不是 docker0 所在的網段的地址, POSTROUTING 鏈將會將該請求偽裝成宿主機的請求轉發到外網
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
# 由 docker0 設備傳入的請求 DOCKER 鏈會返回上一層處理
-A DOCKER -i docker0 -j RETURN
FILTER 表改動的解析如下:
# DOCKER 鏈
:DOCKER - [0:0]
# DOCKER-ISOLATION-STAGE-1 鏈
:DOCKER-ISOLATION-STAGE-1 - [0:0]
# DOCKER-ISOLATION-STAGE-2 鏈
:DOCKER-ISOLATION-STAGE-2 - [0:0]
# DOCKER-USER 鏈
:DOCKER-USER - [0:0]
# FORWARD 鏈的請求跳轉到 DOCKER-USER 鏈處理
-A FORWARD -j DOCKER-USER
# FORWARD 鏈的請求跳轉到 DOCKER-ISOLATION-STAGE-1 鏈處理
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
# FORWARD 鏈的請求如果目標是 docker0 所在的網段, 而且已經建立的連接或者和已建立連接相關那麼接受請求
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# FORWARD 鏈請求目標是 docker0 所在的網段, 那麼跳轉到 DOCKER 鏈處理
-A FORWARD -o docker0 -j DOCKER
# FORWARD 鏈的請求來自於 docker0 所在網段, 而且目標網段不是 docker0 所在網段, 那麼接收請求.
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
# FORWARD 鏈的請求來自於 docker0 所在網段, 而且目標網段也是 docker0 所在網段, 那麼接收請求
-A FORWARD -i docker0 -o docker0 -j ACCEPT
# DOCKER-ISOLATION-STAGE-1 鏈的請求如果來自 docker0 所在網段, 而且目標網段不屬於 docker0 所在網段, 那麼跳轉到 DOCKER-ISOLATION-STAGE-2 處理
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
# DOCKER-ISOLATION-STAGE-1 鏈未處理的請求返回到上一層繼續處理
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
# DOCKER-ISOLATION-STAGE-2 鏈的請求如果目標的網段為 docker0 所在網段則丟棄請求
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
# DOCKER-ISOLATION-STAGE-2 鏈未處理的請求返回到上一層繼續處理
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
# DOCKER-USER 鏈未處理的請求返回到上一層繼續處理
-A DOCKER-USER -j RETURN
可以結合理解的 iptables 知識,對著注釋看一遍,,可加深理解。
安裝 Docker 後 Docker 添加了 DOCKER, DOCKER-USER, DOCKER-ISOLATION-STAGE-1, DOCKER-ISOLATION-STAGE-2 四條鏈,如圖:
本小節來源:理解 Docker 網路(一) — Docker 對 宿主機網路環境的影響,作者 若即,感謝作者的分享。
總結
一直都想整理 iptables ,但是每次都沒有靜下心研究。之前也看過這個,但是時間一長就忘記了。這次趁著假期把 iptables 相關的知識都整理了,也拓展了之前未曾接觸過的:例如模組選項、DNAT、SNAT等等,回頭再去看 25個iptables常用示例 ,不會再像看天書那樣了。
iptables 功能真是太強大了,實現了常用的IP屏蔽、數據包轉發、埠轉發等功能。docker就是基於iptables實現埠轉發的。
本文涉及知識點特別多,建議初學者先全文先看一遍,然後再細看,這樣可以加深理解。文中給了很多示例,讀者最好可以在電腦上實踐一下。
參考
1、iptables (簡體中文) – ArchWiki
//wiki.archlinux.org/index.php/Iptables_(簡體中文)
2、iptables詳細教程:基礎、架構、清空規則、追加規則、應用實例 – Lesca 技術宅
//lesca.me/archives/iptables-tutorial-structures-configuratios-examples.html
3、25個iptables常用示例 | 《Linux就該這麼學》
//www.linuxprobe.com/25-iptables-common-examples.html
4、兩小時玩轉iptables.ppt
5、看了那麼多iptables的教程,這篇教程還是比較全面易懂的 – 91雲(91yun.co)
//www.91yun.co/archives/1690
6、iptables詳解(10):iptables自定義鏈 – wanstack – 部落格園
//www.cnblogs.com/wanstack/p/8393282.html
7、同區域網下的 Iptables DNAT
//wsfdl.com/踩坑雜記/2017/01/12/iptables_snat.html
8、Linux通過iptables埠轉發訪問內網伺服器上的內網服務 – 看天部落格
//hi.ktsee.com/635.html
9、理解 Docker 網路(一) — Docker 對 宿主機網路環境的影響_若即的專欄-CSDN部落格_docker訪問宿主機網路
//blog.csdn.net/qq_17004327/article/details/88630194