iptables基礎原理和使用簡介

大鵬SP發表於2020-11-05

概念簡介

名稱

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

先這些吧。

相關文章