概念簡介
名稱
Netfilter/iptables模塊有兩部分組成:
Netfilter框架以及iptables,iptables又分為iptables(內核空間)和iptables命令行工具(用戶空間);
Netfilter/iptables模塊 在一般使用者眼里簡稱為iptables,但其實在相關開發者眼里更傾向於叫作Netfilter,從項目官網地址也看得出來: https://netfilter.org/
作用
用於數據包處理,比如:報文的轉發、過濾、修改,網絡地址轉換等功能,是一種軟件防火牆。
iptables基本原理
基本工作流程
基本工作流程圖
數據包沿着鏈傳輸,iptables有5個鏈:PREROUTING, INPUT, FORWORD, OUTPUT, POSTROUTING,可以想象成5個關卡,每個關卡都有很多規則,也可能沒有規則。
工作流程如下:
1、當一個數據包進入網卡后,它會先進入PREROUTING,然后根據目的地址進行路由決策,如果目的地址是本機,則走INPUT,不是本機則走FORWARD,然后再走POSTROUTING轉出去。
2、進入INPUT的數據包會轉給本地進程,進程處理后,會發送新的數據包,走OUTPUT,然后經過POSTROUTING轉出去。
3、當然上面的過程每經過一個鏈,都要按照鏈中的規則順序來匹配鏈中的規則,只要遇到一個匹配的規則就按照這個規則進行處理,后面的規則對這個數據就不再起作用。
簡單的規則添加
只有本地socket是用戶態,其余都是內核處理。平時我們加iptables規則,就是加到各個鏈中的,我們創建一個容器進行測試,容器中我已經安裝好了iptables,直接使用iptables命令即可:
#首先啟動一個容器
[root@kube-master ~]# docker run -itd --name "cos8_test" --cap-add=NET_ADMIN centos:base /bin/bash
bd0c29186387b01ae64514050b3b4b804babc988f3dbc52c0cfe6eeac115d1b2
注:要修改容器網絡,容器啟動時需加上 --cap-add=NET_ADMIN,不然容器中執行iptables命令會報錯:
(nf_tables): Could not fetch rule set generation id: Permission denied (you must be root)
查看iptables規則,可以看到當前沒有任何策略
[root@kube-master ~]# docker ps | grep cos8
bd0c29186387 centos:base "/bin/bash" 21 hours ago Up 21 hours cos8_test
[root@kube-master ~]# docker exec -it bd0 bash
[root@bd0c29186387 /]#
[root@bd0c29186387 /]# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
創建一個規則:拒絕所有訪問80端口的tcp數據包。
[root@bd0c29186387 /]# iptables -A INPUT -p tcp --dport 80 -j DROP
[root@bd0c29186387 /]#
[root@bd0c29186387 /]# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
Chain FORWARD (policy ACCEPT)
target prot opt source destination
DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
這里有個小插曲:可以看到我只在INPUT鏈中添加了規則,但是怎么FORWARD和OUTPUT鏈中也有這條規則,隨后我手動刪了INPUT鏈中的規則,然后FORWARD和OUTPUT鏈中的規則也隨之消失了,此容器的OS版本和內核信息如下
[root@bd0c29186387 /]# cat /etc/redhat-release
CentOS Linux release 8.2.2004 (Core)
[root@bd0c29186387 /]#
[root@bd0c29186387 /]# uname -a
Linux bd0c29186387 3.10.0-1127.13.1.el7.x86_64 #1 SMP Tue Jun 23 15:46:38 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
之前沒用過centos8,考慮到可能是OS更新了netfilter模塊,於是換成了一個centos7.8.2003的容器測試了一下,發現添加規則是符合預期的,如下
[root@kube-master /]# docker run -itd --name "cos7" --cap-add=NET_ADMIN centos7:base /bin/bash
c951c0a9d34d8e43a56e43872294ab5ab6a1504b365721238178de134e8d3bde
[root@kube-master /]#
[root@kube-master /]# docker exec -it cos7 bash
[root@c951c0a9d34d /]#
[root@c951c0a9d34d /]# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
[root@c951c0a9d34d /]#
[root@c951c0a9d34d /]# iptables -A INPUT -p tcp --dport 80 -j DROP
[root@c951c0a9d34d /]#
[root@c951c0a9d34d /]# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
拒絕可以使用DROP,也可以使用REJECT關鍵字,DROP不會給客戶端返回任何信息,所以客戶端看到的情況就是連接超時,很難判斷是防火牆原因還是網絡設備故障等原因。
而REJECT則明確返回給客戶端一個拒絕的信息,客戶端會知道我是被防火牆拒絕了。
可根據場景使用,REJECT更適合調試,DROP抗攻擊上面更安全些。
后面使用centos7的容器作為測試,先不管centos8更新了啥。
四表五鏈
上面我添加的規則命令如下:
iptables -A INPUT -p tcp --dport 80 -j DROP
但這只是簡寫后的,稍微寫全些如下,其實還可以更全些,暫不說明。
iptables -t filter -A INPUT -s 0.0.0.0/0 -p tcp -d 0.0.0.0/0 --dport 80 -j DROP
-t : 指定表,這里是filter表,規則會添加到filter表中。
-s : 指定源地址,0.0.0.0/0是指所有IP。
-d : 指定目的地址。
--dport : 指定目的端口。
-j : 指定處理動作,這里是DROP,也就是丟棄。
表的概念
上面提到了filter表,那什么是表呢?
我們加規則,加到每個鏈中,每個鏈中的規則有很多,有一部分規則是相似的,比如,有一部分都是端口的過濾,有一部分都是報文的修改,根據這些規則的類型,把相似的規則放在一起,這些放在一起的規則的集合稱為表。
那不同的規則的集合就放在了不同的表中,總共有4種表,也就是4種規則:
filter表:負責過濾功能;
nat表:network address translation,網絡地址轉換功能;
mangle表:拆解、修改、並重新封裝報文;
raw表:關閉nat表上啟用的連接追蹤機制;
因為每個鏈中都有不同規則,所以表存在於每一個鏈中,但不是每個鏈都有這4種表,
PREROUTING 的規則可以存在於:raw表,mangle表,nat表。
INPUT 的規則可以存在於:mangle表,filter表,nat表(centos7中有nat表,centos6中沒有)。
FORWARD 的規則可以存在於:mangle表,filter表。
OUTPUT 的規則可以存在於:raw表mangle表,nat表,filter表。
POSTROUTING 的規則可以存在於:mangle表,nat表。
表的處理優先級如下:
raw --> mangle --> nat --> filter
所以我們一開始iptables的基本工作流程圖可以更詳細些
其實還可以再詳細些,我們單獨拿一個鏈出來,比如PREROUTING鏈,大概是如下情況,這些規則組和在了一起便成了一條鏈。
所以,我們上面加的禁止訪問本機80端口的規則是存放在filter表中的,我們來查看下filter表中的規則,可以看到我們添加的規則,netfilter默認把80端口綁定為http。
[root@c951c0a9d34d /]# iptables -L -t filter
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP tcp -- anywhere anywhere tcp dpt:http
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
iptables常用命令舉例
查看規則
按表查看: iptables -L -t table
按照鏈查看: iptables -nL INPUT
設置鏈的默認規則
#INPUT鏈默認拒絕所有數據包
iptables -P INPUT DROP
#OUTPUT默認允許所有數據包出去
iptables -P INPUT ACCEPT
清空表中的規則
#清空nat表中PREROUTING鏈的規則
iptables -t nat -F PREROUTING
#清空filter表中所有鏈的規則
iptables -t filter -F
#清空使用者自定義的表規則
iptables -X
刪除某一條規則
#可以通過編號來刪除
#--line-number在規則前面顯示了編號
[root@c951c0a9d34d /]# iptables -nL --line-number
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
[root@c951c0a9d34d /]#
[root@c951c0a9d34d /]# iptables -D INPUT 1
#也可以直接刪除規則
#下面命令中,-D后面的全是匹配條件,凡是某條規則中包含下面所有的匹配項,就刪除這條規則
[root@c951c0a9d34d /]# iptables -D INPUT -p tcp --dport 80 -j DROP
禁ping
#禁止別人ping自己,但是自己可以ping別人
#type 8: 表示ping包請求流量
#type 0: 表示ping包響應流量
iptables -A INPUT -p icmp --icmp-type 0 -j DROP
iptables -A OUTPUT -p icmp --icmp-type 8 -j DROP
#禁止別人ping自己,也禁止自己ping別人
iptables -A INPUT -p icmp -m icmp --icmp-type any -j DROP
#也可以改參數實現禁ping
echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_all
轉發
#開啟轉發功能
echo 1 > /proc/sys/net/ipv4/ip_forward
#對於外部訪問自己80端口的流量全部轉到172.17.0.4的80端口,
#xxx.xxx.xxx.xx代表本機的IP
iptables -t nat -I PREROUTING -d xxx.xxx.xxx.xx -p tcp --dport 80 -j DNAT --to-destination 172.17.0.4:80
#對於從本機出去的流量,源ip全部轉換為172.17.0.4
iptables -t nat -A POSTROUTING -p tcp -j SNAT --to-source 172.17.0.4
針對鏈接狀態作規則
#NEW 用戶發起一個全新的請求
#ESTABLISHED 對一個全新的請求進行回應
#RELATED 兩個完整連接之間的相互關系,一個完整的連接,需要依賴於另一個完整的連接。
#INVALID 無法識別的狀態。
iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
先這些吧。