iptables基礎原理和使用簡介
概念簡介
名稱
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鏈預設拒絕所有資料包
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
先這些吧。