連接跟蹤(conntrack)
連接跟蹤是許多網(wǎng)絡(luò)應(yīng)用的基礎(chǔ)。例如,Kubernetes Service、ServiceMesh sidecar、 軟件四層負(fù)載均衡器 LVS/IPVS、Docker network、OVS、iptables 主機(jī)防火墻等等,都依賴連接跟蹤功能。
連接跟蹤,顧名思義,就是跟蹤(并記錄)連接的狀態(tài)。例如,圖 1.1 是一臺 IP 地址為 10.1.1.2 的 Linux 機(jī)器,我們能看到這臺機(jī)器上有三條 連接:
機(jī)器訪問外部 HTTP 服務(wù)的連接(目的端口 80)
外部訪問機(jī)器內(nèi) FTP 服務(wù)的連接(目的端口 21)
機(jī)器訪問外部 DNS 服務(wù)的連接(目的端口 53)
連接跟蹤所做的事情就是發(fā)現(xiàn)并跟蹤這些連接的狀態(tài),具體包括:
從數(shù)據(jù)包中提取元組(tuple)信息,辨別數(shù)據(jù)流(flow)和對應(yīng)的連接(connection)。
為所有連接維護(hù)一個(gè)狀態(tài)數(shù)據(jù)庫(conntrack table),例如連接的創(chuàng)建時(shí)間、發(fā)送 包數(shù)、發(fā)送字節(jié)數(shù)等等。
回收過期的連接(GC)。
為更上層的功能(例如 NAT)提供服務(wù)。
需要注意的是,連接跟蹤中所說的“連接”,概念和 TCP/IP 協(xié)議中“面向連接”(connection oriented)的“連接”并不完全相同,簡單來說:
TCP/IP 協(xié)議中,連接是一個(gè)四層(Layer 4)的概念。TCP 是有連接的,或稱面向連接的(connection oriented),發(fā)送出去的包都要求對端應(yīng)答(ACK),并且有重傳機(jī)制。UDP 是無連接的,發(fā)送的包無需對端應(yīng)答,也沒有重傳機(jī)制。
conntrack(CT) 中,一個(gè)元組(tuple)定義的一條數(shù)據(jù)流(flow )就表示一條連接(connection)。后面會(huì)看到 UDP 甚至是 ICMP 這種三層協(xié)議在 CT 中也都是有連接記錄的,但不是所有協(xié)議都會(huì)被連接跟蹤。
Netfilter
Linux 的連接跟蹤是在 Netfilter 中實(shí)現(xiàn)的。
Netfilter 是 Linux 內(nèi)核中一個(gè)對數(shù)據(jù) 包進(jìn)行控制、修改和過濾(manipulation and filtering)的框架。它在內(nèi)核協(xié)議棧中設(shè)置了若干 hook 點(diǎn),以此對數(shù)據(jù)包進(jìn)行攔截、過濾或其他處理。
現(xiàn)在提到連接跟蹤(conntrack),可能首先都會(huì)想到 Netfilter,Netfilter 只是 Linux 內(nèi)核中的一種連接跟蹤實(shí)現(xiàn)。換句話說,只要具備了 hook 能力,能攔截到進(jìn)出主機(jī)的每個(gè)包,完全可以在此基礎(chǔ)上自己實(shí)現(xiàn)一套連接跟蹤。
云原生網(wǎng)絡(luò)方案 Cilium 在 1.7.4+ 版本就實(shí)現(xiàn)了這樣一套獨(dú)立的連接跟蹤和 NAT 機(jī)制 (完備功能需要 Kernel 4.19+)。其基本原理是:
基于 BPF hook 實(shí)現(xiàn)數(shù)據(jù)包的攔截功能(等價(jià)于 netfilter 里面的 hook 機(jī)制)
在 BPF hook 的基礎(chǔ)上,實(shí)現(xiàn)一套全新的 conntrack 和 NAT 因此,即便卸載掉 Netfilter ,也不會(huì)影響 Cilium 對 Kubernetes ClusterIP、NodePort、ExternalIPs 和 LoadBalancer 等功能的支持。由于這套連接跟蹤機(jī)制是獨(dú)立于 Netfilter 的,因此它的 conntrack 和 NAT 信息也沒有 存儲(chǔ)在內(nèi)核的(也就是 Netfilter 的)conntrack table 和 NAT table。所以常規(guī)的 conntrack/netstats/ss/lsof 等工具是看不到的,要使用 Cilium 的命令,例如:
$ciliumbpfnatlist $ciliumbpfctlistglobal
Iptables
Iptables 是配置 Netfilter 過濾功能的用戶空間工具。netfilter 才是防火墻真正的安全框架(framework),netfilter 位于內(nèi)核空間。iptables 其實(shí)是一個(gè)命令行工具,位于用戶空間,我們用這個(gè)工具操作真正的框架。Iptable 根據(jù)規(guī)則所定義的方法來處理數(shù)據(jù)包,如放行(accept)、拒絕(reject)和丟棄(drop)等。
例如當(dāng)客戶端訪問服務(wù)器的web服務(wù)時(shí),客戶端發(fā)送報(bào)文到網(wǎng)卡,而 tcp/ip 協(xié)議棧是屬于內(nèi)核的一部分,所以,客戶端的信息會(huì)通過內(nèi)核的 TCP 協(xié)議傳輸?shù)接脩艨臻g中的 web 服務(wù)中,而此時(shí),客戶端報(bào)文的目標(biāo)終點(diǎn)為 web 服務(wù)所監(jiān)聽的套接字(IP:Port)上,當(dāng)web服務(wù)需要響應(yīng)客戶端請求時(shí),web 服務(wù)發(fā)出的響應(yīng)報(bào)文的目標(biāo)終點(diǎn)則為客戶端,這個(gè)時(shí)候,web 服務(wù)所監(jiān)聽的 IP 與端口反而變成了原點(diǎn),我們說過,netfilter 才是真正的防火墻,它是內(nèi)核的一部分,所以,如果我們想要防火墻能夠達(dá)到”防火”的目的,則需要在內(nèi)核中設(shè)置關(guān)卡,所有進(jìn)出的報(bào)文都要通過這些關(guān)卡,經(jīng)過檢查后,符合放行條件的才能放行,符合阻攔條件的則需要被阻止。
iptables 包含 4個(gè)表,5個(gè)鏈。其中表是按照對數(shù)據(jù)包的操作區(qū)分(過濾, NAT等)的,鏈?zhǔn)前凑詹煌?Hook 點(diǎn)來區(qū)分的,表和鏈實(shí)際上是netfilter的兩個(gè)維度。
iptables 的四個(gè)表分別是 filter,mangle,nat,raw,默認(rèn)表是filter。
filter 表:用來對數(shù)據(jù)包進(jìn)行過濾,具體的規(guī)則要求決定如何處理一個(gè)數(shù)據(jù)包。
nat 表:主要用來修改數(shù)據(jù)包的 IP 地址、端口號信息。
mangle 表:主要用來修改數(shù)據(jù)包的服務(wù)類型,生存周期,為數(shù)據(jù)包設(shè)置標(biāo)記,實(shí)現(xiàn)流量整形、策略路由等。
raw 表:主要用來決定是否對數(shù)據(jù)包進(jìn)行狀態(tài)跟蹤。
iptables 的五個(gè)鏈分別是 PREROUTING,INPUT,F(xiàn)ORWARD,OUTPUT,POSTROUTING。
input 鏈:當(dāng)收到訪問本機(jī)地址的數(shù)據(jù)包時(shí),將應(yīng)用此鏈中的規(guī)則。
output 鏈:當(dāng)本機(jī)向外發(fā)送數(shù)據(jù)包時(shí),將應(yīng)用此鏈中的規(guī)則。
forward 鏈:當(dāng)收到需要轉(zhuǎn)發(fā)給其他地址的數(shù)據(jù)包時(shí),將應(yīng)用此鏈中的規(guī)則,注意如果需要實(shí)現(xiàn)forward轉(zhuǎn)發(fā)需要開啟Linux內(nèi)核中的ip_forward功能。
prerouting 鏈:在對數(shù)據(jù)包做路由選擇之前,將應(yīng)用此鏈中的規(guī)則。
postrouting 鏈:在對數(shù)據(jù)包做路由選擇之后,將應(yīng)用此鏈中的規(guī)則。
表和鏈的對應(yīng)關(guān)系如下圖所示:
我們能夠想象出某些常用場景中,報(bào)文的流向:
到本機(jī)某進(jìn)程的報(bào)文:PREROUTING –> INPUT。
由本機(jī)轉(zhuǎn)發(fā)的報(bào)文:PREROUTING –> FORWARD –> POSTROUTING。
由本機(jī)的某進(jìn)程發(fā)出報(bào)文(通常為響應(yīng)報(bào)文):OUTPUT –> POSTROUTING。
我們可以將數(shù)據(jù)包通過防火墻的流程總結(jié)為下圖:
查詢規(guī)則
-t:表名
-n:不解析IP地址
-v:會(huì)顯示出計(jì)數(shù)器的信息,數(shù)據(jù)包的數(shù)量和大小
-x:選項(xiàng)表示顯示計(jì)數(shù)器的精確值
--line-numbers:顯示規(guī)則的序號(簡寫為--line)
-L:鏈名
#iptables-tfilter-nvxLDOCKER--line ChainDOCKER(1references) numpktsbytestargetprotoptinoutsourcedestination 15076321478ACCEPTtcp--!docker0docker00.0.0.0/0172.17.0.2tcpdpt:8443 23723354082508ACCEPTtcp--!docker0docker00.0.0.0/0172.17.0.2tcpdpt:22 31712255195ACCEPTtcp--!docker0docker00.0.0.0/0172.17.0.3tcpdpt:9000 400ACCEPTtcp--!docker0docker00.0.0.0/0172.17.0.3tcpdpt:8000 5402246343104ACCEPTtcp--!docker0docker00.0.0.0/0172.17.0.4tcpdpt:3443 6210342227009ACCEPTtcp--!docker0docker00.0.0.0/0172.17.0.5tcpdpt:3306 7585459ACCEPTtcp--!docker0docker00.0.0.0/0172.17.0.6tcpdpt:80 882670081ACCEPTtcp--!docker0docker00.0.0.0/0172.17.0.6tcpdpt:443 9103069051063612492ACCEPTtcp--!docker0docker00.0.0.0/0172.17.0.9tcpdpt:3306 1015977512297727ACCEPTtcp--!docker0docker00.0.0.0/0172.17.0.7tcpdpt:11111
增加規(guī)則
在指定表的指定鏈的尾部添加一條規(guī)則,-A 選項(xiàng)表示在對應(yīng)鏈的末尾添加規(guī)則,省略 -t 選項(xiàng)時(shí),表示默認(rèn)操作 filter 表中的規(guī)則:
命令語法:iptables-t表名-A鏈名匹配條件-j動(dòng)作 示例:iptables-tfilter-AINPUT-s192.168.1.146-jDROP
在指定表的指定鏈的首部添加一條規(guī)則,-I 選型表示在對應(yīng)鏈的開頭添加規(guī)則:
命令語法:iptables-t表名-I鏈名匹配條件-j動(dòng)作 示例:iptables-tfilter-IINPUT-s192.168.1.146-jACCEPT
在指定表的指定鏈的指定位置添加一條規(guī)則:
命令語法:iptables-t表名-I鏈名規(guī)則序號匹配條件-j動(dòng)作 示例:iptables-tfilter-IINPUT5-s192.168.1.146-jREJECT
刪除規(guī)則
按照規(guī)則序號刪除規(guī)則,刪除指定表的指定鏈的指定規(guī)則,-D 選項(xiàng)表示刪除對應(yīng)鏈中的規(guī)則。示例表示刪除filter表中INPUT鏈中序號為3的規(guī)則。:
命令語法:iptables -t 表名-D 鏈名規(guī)則序號 示例:iptables -t filter-DINPUT3
按照具體的匹配條件與動(dòng)作刪除規(guī)則,刪除指定表的指定鏈的指定規(guī)則。示例表示刪除filter表中INPUT鏈中源地址為192.168.1.146并且動(dòng)作為DROP的規(guī)則。:
命令語法:iptables-t表名-D鏈名匹配條件-j動(dòng)作 示例:iptables-tfilter-DINPUT-s192.168.1.146-jDROP
刪除指定表的指定鏈中的所有規(guī)則,-F選項(xiàng)表示清空對應(yīng)鏈中的規(guī)則:
命令語法:iptables -t 表名-F鏈名 示例:iptables -t filter -FINPUT
修改規(guī)則
修改指定表中指定鏈的指定規(guī)則,-R 選項(xiàng)表示修改對應(yīng)鏈中的規(guī)則,使用 -R 選項(xiàng)時(shí)要同時(shí)指定對應(yīng)的鏈以及規(guī)則對應(yīng)的序號,并且規(guī)則中原本的匹配條件不可省略。示例表示修改filter表中INPUT鏈的第3條規(guī)則,將這條規(guī)則的動(dòng)作修改為ACCEPT, -s 192.168.1.146為這條規(guī)則中原本的匹配條件,如果省略此匹配條件,修改后的規(guī)則中的源地址可能會(huì)變?yōu)?.0.0.0/0:
命令語法:iptables-t表名-R鏈名規(guī)則序號規(guī)則原本的匹配條件-j動(dòng)作 示例:iptables-tfilter-RINPUT3-s192.168.1.146-jACCEPT
設(shè)置指定表的指定鏈的默認(rèn)策略(默認(rèn)動(dòng)作):
命令語法:iptables -t 表名-P 鏈名動(dòng)作 示例:iptables -t filter -P FORWARDACCEPT
保存規(guī)則
方式一
當(dāng)我們對規(guī)則進(jìn)行了修改以后,如果想要修改永久生效,必須使用下面命令保存規(guī)則:
serviceiptablessave
當(dāng)然,如果你誤操作了規(guī)則,但是并沒有保存,那么使用 service iptables restart 命令重啟 iptables 以后,規(guī)則會(huì)再次回到上次保存 /etc/sysconfig/iptables 文件時(shí)的模樣。
centos7 中,已經(jīng)不再使用 init 風(fēng)格的腳本啟動(dòng)服務(wù),而是使用 unit 文件,所以,在 centos7 中已經(jīng)不能再使用類似 service iptables start 這樣的命令了,所以 service iptables save 也無法執(zhí)行,同時(shí),在 centos7中,使用 firewall 替代了原來的 iptables service,不過不用擔(dān)心,我們只要通過 yum 源安裝 iptables與iptables-services 即可(iptables 一般會(huì)被默認(rèn)安裝,但是iptables-services 在 centos7 中一般不會(huì)被默認(rèn)安裝),在centos7 中安裝完 iptables-services 后,即可像 centos6 中一樣,通過 service iptables save 命令保存規(guī)則了,規(guī)則同樣保存在 /etc/sysconfig/iptables 文件中。此處給出 centos7 中配置 iptables-service 的步驟:
#配置好yum源以后安裝iptables-service yuminstall-yiptables-services #停止firewalld systemctlstopfirewalld #禁止firewalld自動(dòng)啟動(dòng) systemctldisablefirewalld #啟動(dòng)iptables systemctlstartiptables #將iptables設(shè)置為開機(jī)自動(dòng)啟動(dòng),以后即可通過iptables-service控制iptables服務(wù) systemctlenableiptables
上述配置過程只需一次,以后即可在 centos7 中使用 service iptables save 命令保存 iptables 規(guī)則了。
方式二
還可以使用另一種方法保存 iptables 規(guī)則,就是使用 iptables-save 命令。使用 iptables-save 并不能保存當(dāng)前的 iptables 規(guī)則,但是可以將當(dāng)前的 iptables 規(guī)則以”保存后的格式”輸出到屏幕上。
所以,我們可以使用 iptables-save 命令,再配合重定向,將規(guī)則重定向到 /etc/sysconfig/iptables 文件中即可。
iptables-save>/etc/sysconfig/iptables
加載規(guī)則
我們也可以將 /etc/sysconfig/iptables 中的規(guī)則重新載入為當(dāng)前的iptables 規(guī)則,但是注意,未保存入 /etc/sysconfig/iptables 文件中的修改將會(huì)丟失或者被覆蓋。
使用 iptables-restore 命令可以從指定文件中重載規(guī)則,示例如下
iptables-restore/etc/sysconfig/iptables
匹配條件
當(dāng)規(guī)則中同時(shí)存在多個(gè)匹配條件時(shí),多個(gè)條件之間默認(rèn)存在”與”的關(guān)系,即報(bào)文必須同時(shí)滿足所有條件,才能被規(guī)則匹配。
-s 用于匹配報(bào)文的源地址,可以同時(shí)指定多個(gè)源地址,每個(gè)IP之間用逗號隔開,也可以指定為一個(gè)網(wǎng)段。
#示例如下 iptables-tfilter-IINPUT-s192.168.1.111,192.168.1.118-jDROP iptables-tfilter-IINPUT-s192.168.1.0/24-jACCEPT iptables-tfilter-IINPUT!-s192.168.1.0/24-jACCEPT
-d 用于匹配報(bào)文的目標(biāo)地址,可以同時(shí)指定多個(gè)目標(biāo)地址,每個(gè) IP 之間用逗號隔開,也可以指定為一個(gè)網(wǎng)段。
#示例如下 iptables-tfilter-IOUTPUT-d192.168.1.111,192.168.1.118-jDROP iptables-tfilter-IINPUT-d192.168.1.0/24-jACCEPT iptables-tfilter-IINPUT!-d192.168.1.0/24-jACCEPT
-p 用于匹配報(bào)文的協(xié)議類型,可以匹配的協(xié)議類型 tcp、udp、udplite、icmp、esp、ah、sctp 等(centos7 中還支持 icmpv6、mh)。
#示例如下 iptables-tfilter-IINPUT-ptcp-s192.168.1.146-jACCEPT iptables-tfilter-IINPUT!-pudp-s192.168.1.146-jACCEPT
-i 用于匹配報(bào)文是從哪個(gè)網(wǎng)卡接口流入本機(jī)的,由于匹配條件只是用于匹配報(bào)文流入的網(wǎng)卡,所以在 OUTPUT 鏈與 POSTROUTING 鏈中不能使用此選項(xiàng)。
#示例如下 iptables-tfilter-IINPUT-picmp-ieth4-jDROP iptables-tfilter-IINPUT-picmp!-ieth4-jDROP
-o 用于匹配報(bào)文將要從哪個(gè)網(wǎng)卡接口流出本機(jī),于匹配條件只是用于匹配報(bào)文流出的網(wǎng)卡,所以在 INPUT 鏈與 PREROUTING 鏈中不能使用此選項(xiàng)。
#示例如下 iptables-tfilter-IOUTPUT-picmp-oeth4-jDROP iptables-tfilter-IOUTPUT-picmp!-oeth4-jDROP
擴(kuò)展匹配條件
tcp擴(kuò)展模塊
常用的擴(kuò)展匹配條件如下:
–sport:用于匹配 tcp 協(xié)議報(bào)文的源端口,可以使用冒號指定一個(gè)連續(xù)的端口范圍。
–dport:用于匹配 tcp 協(xié)議報(bào)文的目標(biāo)端口,可以使用冒號指定一個(gè)連續(xù)的端口范圍。
–tcp-flags:用于匹配報(bào)文的tcp頭的標(biāo)志位。
–syn:用于匹配 tcp 新建連接的請求報(bào)文,相當(dāng)于使用 –tcp-flags SYN,RST,ACK,FIN SYN。
注意,-p tcp與 -m tcp 并不沖突,-p 用于匹配報(bào)文的協(xié)議,-m 用于指定擴(kuò)展模塊的名稱,正好,這個(gè)擴(kuò)展模塊也叫 tcp。
#示例如下 iptables-tfilter-IOUTPUT-d192.168.1.146-ptcp-mtcp--sport22-jREJECT iptables-tfilter-IINPUT-s192.168.1.146-ptcp-mtcp--dport22:25-jREJECT iptables-tfilter-IINPUT-s192.168.1.146-ptcp-mtcp--dport:22-jREJECT iptables-tfilter-IINPUT-s192.168.1.146-ptcp-mtcp--dport80:-jREJECT iptables-tfilter-IOUTPUT-d192.168.1.146-ptcp-mtcp!--sport22-jACCEPT iptables-tfilter-IINPUT-ptcp-mtcp--dport22--tcp-flagsSYN,ACK,FIN,RST,URG,PSHSYN-jREJECT iptables-tfilter-IOUTPUT-ptcp-mtcp--sport22--tcp-flagsSYN,ACK,FIN,RST,URG,PSHSYN,ACK-jREJECT iptables-tfilter-IINPUT-ptcp-mtcp--dport22--tcp-flagsALLSYN-jREJECT iptables-tfilter-IOUTPUT-ptcp-mtcp--sport22--tcp-flagsALLSYN,ACK-jREJECT iptables-tfilter-IINPUT-ptcp-mtcp--dport22--syn-jREJECT
udp 擴(kuò)展模塊
常用的擴(kuò)展匹配條件:
–sport:匹配udp報(bào)文的源地址。
–dport:匹配udp報(bào)文的目標(biāo)地址。
#示例 iptables-tfilter-IINPUT-pudp-mudp--dport137-jACCEPT iptables-tfilter-IINPUT-pudp-mudp--dport137:157-jACCEPT
icmp 擴(kuò)展模塊
常用的擴(kuò)展匹配條件:
–icmp-type:匹配icmp報(bào)文的具體類型。
#示例 iptables-tfilter-IINPUT-picmp-micmp--icmp-type8/0-jREJECT iptables-tfilter-IINPUT-picmp--icmp-type8-jREJECT iptables-tfilter-IOUTPUT-picmp-micmp--icmp-type0/0-jREJECT iptables-tfilter-IOUTPUT-picmp--icmp-type0-jREJECT iptables-tfilter-IINPUT-picmp--icmp-type"echo-request"-jREJECT
multiport 擴(kuò)展模塊
常用的擴(kuò)展匹配條件如下:
-p tcp -m multiport –sports 用于匹配報(bào)文的源端口,可以指定離散的多個(gè)端口號,端口之間用”逗號”隔開。
-p udp -m multiport –dports 用于匹配報(bào)文的目標(biāo)端口,可以指定離散的多個(gè)端口號,端口之間用”逗號”隔開。
#示例如下 iptables-tfilter-IOUTPUT-d192.168.1.146-pudp-mmultiport--sports137,138-jREJECT iptables-tfilter-IINPUT-s192.168.1.146-ptcp-mmultiport--dports22,80-jREJECT iptables-tfilter-IINPUT-s192.168.1.146-ptcp-mmultiport!--dports22,80-jREJECT iptables-tfilter-IINPUT-s192.168.1.146-ptcp-mmultiport--dports80:88-jREJECT iptables-tfilter-IINPUT-s192.168.1.146-ptcp-mmultiport--dports22,80:88-jREJECT
iprange 模塊
包含的擴(kuò)展匹配條件如下:
–src-range:指定連續(xù)的源地址范圍。
–dst-range:指定連續(xù)的目標(biāo)地址范圍。
#示例 iptables-tfilter-IINPUT-miprange--src-range192.168.1.127-192.168.1.146-jDROP iptables-tfilter-IOUTPUT-miprange--dst-range192.168.1.127-192.168.1.146-jDROP iptables-tfilter-IINPUT-miprange!--src-range192.168.1.127-192.168.1.146-jDROP
string 模塊
常用擴(kuò)展匹配條件如下:
–algo:指定對應(yīng)的匹配算法,可用算法為bm、kmp,此選項(xiàng)為必需選項(xiàng)。
–string:指定需要匹配的字符串
我們想要達(dá)到的目的是,如果報(bào)文中包含”O(jiān)OXX”字符,我們就拒絕報(bào)文進(jìn)入本機(jī):
#示例 iptables-tfilter-IINPUT-mstring--algobm--string"OOXX"-jREJECT
time 模塊
常用擴(kuò)展匹配條件如下:
–timestart:用于指定時(shí)間范圍的開始時(shí)間,不可取反。
–timestop:用于指定時(shí)間范圍的結(jié)束時(shí)間,不可取反。
–weekdays:用于指定”星期幾”,可取反。
–monthdays:用于指定”幾號”,可取反。
–datestart:用于指定日期范圍的開始日期,不可取反。
–datestop:用于指定日期范圍的結(jié)束時(shí)間,不可取反。
#示例 iptables-tfilter-IOUTPUT-ptcp--dport80-mtime--timestart09:00:00--timestop19:00:00-jREJECT iptables-tfilter-IOUTPUT-ptcp--dport443-mtime--timestart09:00:00--timestop19:00:00-jREJECT iptables-tfilter-IOUTPUT-ptcp--dport80-mtime--weekdays6,7-jREJECT iptables-tfilter-IOUTPUT-ptcp--dport80-mtime--monthdays22,23-jREJECT iptables-tfilter-IOUTPUT-ptcp--dport80-mtime!--monthdays22,23-jREJECT iptables-tfilter-IOUTPUT-ptcp--dport80-mtime--timestart09:00:00--timestop18:00:00--weekdays6,7-jREJECT iptables-tfilter-IOUTPUT-ptcp--dport80-mtime--weekdays5--monthdays22,23,24,25,26,27,28-jREJECT iptables-tfilter-IOUTPUT-ptcp--dport80-mtime--datestart2017-12-24--datestop2017-12-27-jREJECT
connlimit 模塊
常用的擴(kuò)展匹配條件如下:
–connlimit-above:單獨(dú)使用此選項(xiàng)時(shí),表示限制每個(gè)IP的鏈接數(shù)量。
–connlimit-mask:此選項(xiàng)不能單獨(dú)使用,在使用–connlimit-above選項(xiàng)時(shí),配合此選項(xiàng),則可以針對”某類IP段內(nèi)的一定數(shù)量的IP”進(jìn)行連接數(shù)量的限制,如果不明白可以參考上文的詳細(xì)解釋。
#示例 iptables-IINPUT-ptcp--dport22-mconnlimit--connlimit-above2-jREJECT iptables-IINPUT-ptcp--dport22-mconnlimit--connlimit-above20--connlimit-mask24-jREJECT iptables-IINPUT-ptcp--dport22-mconnlimit--connlimit-above10--connlimit-mask27-jREJECT
limit 模塊
connlimit 模塊是對連接數(shù)量進(jìn)行限制的,limit 模塊是對”報(bào)文到達(dá)速率”進(jìn)行限制的。用大白話說就是,如果我想要限制單位時(shí)間內(nèi)流入的包的數(shù)量,就能用 limit 模塊。我們可以以秒為單位進(jìn)行限制,也可以以分鐘、小時(shí)、天作為單位進(jìn)行限制。常用的擴(kuò)展匹配條件如下:
–limit-burst:類比”令牌桶”算法,此選項(xiàng)用于指定令牌桶中令牌的最大數(shù)量。
–limit:類比”令牌桶”算法,此選項(xiàng)用于指定令牌桶中生成新令牌的頻率,可用時(shí)間單位有second、minute 、hour、day。
示例表示限制外部主機(jī)對本機(jī)進(jìn)行ping操作時(shí),本機(jī)最多每6秒中放行一個(gè)ping包
#示例,注意,如下兩條規(guī)則需配合使用 #令牌桶中最多能存放3個(gè)令牌,每分鐘生成10個(gè)令牌(即6秒鐘生成一個(gè)令牌)。 iptables-tfilter-IINPUT-picmp-mlimit--limit-burst3--limit10/minute-jACCEPT #默認(rèn)將icmp包丟棄 iptables-tfilter-AINPUT-picmp-jREJECT
state 擴(kuò)展模塊
當(dāng)我們通過 http 的 url 訪問某個(gè)網(wǎng)站的網(wǎng)頁時(shí),客戶端向服務(wù)端的 80 端口發(fā)起請求,服務(wù)端再通過 80 端口響應(yīng)我們的請求,于是,作為客戶端,我們似乎應(yīng)該理所應(yīng)當(dāng)?shù)姆判?80 端口,以便服務(wù)端回應(yīng)我們的報(bào)文可以進(jìn)入客戶端主機(jī),于是,我們在客戶端放行了 80 端口,同理,當(dāng)我們通過 ssh 工具遠(yuǎn)程連接到某臺服務(wù)器時(shí),客戶端向服務(wù)端的 22 號端口發(fā)起請求,服務(wù)端再通過 22 號端口響應(yīng)我們的請求,于是我們理所應(yīng)當(dāng)?shù)姆判辛怂?22 號端口,以便遠(yuǎn)程主機(jī)的響應(yīng)請求能夠通過防火墻,但是,作為客戶端,如果我們并沒有主動(dòng)向 80 端口發(fā)起請求,也沒有主動(dòng)向 22 號端口發(fā)起請求,那么其他主機(jī)通過 80 端口或者 22 號端口向我們發(fā)送數(shù)據(jù)時(shí),我們可以接收到嗎?應(yīng)該是可以的,因?yàn)槲覀優(yōu)榱耸盏?http 與 ssh 的響應(yīng)報(bào)文,已經(jīng)放行了 80 端口與 22 號端口,所以,不管是”響應(yīng)”我們的報(bào)文,還是”主動(dòng)發(fā)送”給我們的報(bào)文,應(yīng)該都是可以通過這兩個(gè)端口的,那么仔細(xì)想想,這樣是不是不太安全呢?此時(shí) state 擴(kuò)展模塊就派上用場了。
對于 state 模塊的連接而言,”連接”其中的報(bào)文可以分為5種狀態(tài),分別為:
NEW:連接中的第一個(gè)包,狀態(tài)就是 NEW,我們可以理解為新連接的第一個(gè)包的狀態(tài)為 NEW。
ESTABLISHED:我們可以把 NEW 狀態(tài)包后面的包的狀態(tài)理解為 ESTABLISHED,表示連接已建立。
RELATED:從字面上理解 RELATED 譯為關(guān)系,但是這樣仍然不容易理解,我們舉個(gè)例子。比如 FTP 服務(wù),F(xiàn)TP 服務(wù)端會(huì)建立兩個(gè)進(jìn)程,一個(gè)命令進(jìn)程,一個(gè)數(shù)據(jù)進(jìn)程。命令進(jìn)程負(fù)責(zé)服務(wù)端與客戶端之間的命令傳輸(我們可以把這個(gè)傳輸過程理解成 state 中所謂的一個(gè)”連接”,暫稱為”命令連接”)。數(shù)據(jù)進(jìn)程負(fù)責(zé)服務(wù)端與客戶端之間的數(shù)據(jù)傳輸 (我們把這個(gè)過程暫稱為”數(shù)據(jù)連接”)。但是具體傳輸哪些數(shù)據(jù),是由命令去控制的,所以,”數(shù)據(jù)連接”中的報(bào)文與”命令連接”是有”關(guān)系”的。那么,”數(shù)據(jù)連接”中的報(bào)文可能就是 RELATED 狀態(tài),因?yàn)檫@些報(bào)文與”命令連接”中的報(bào)文有關(guān)系。(注:如果想要對ftp進(jìn)行連接追蹤,需要單獨(dú)加載對應(yīng)的內(nèi)核模塊 nf_conntrack_ftp,如果想要自動(dòng)加載,可以配置 /etc/sysconfig/iptables-config 文件)
INVALID:如果一個(gè)包沒有辦法被識別,或者這個(gè)包沒有任何狀態(tài),那么這個(gè)包的狀態(tài)就是 INVALID,我們可以主動(dòng)屏蔽狀態(tài)為 INVALID 的報(bào)文。
UNTRACKED:報(bào)文的狀態(tài)為 untracked 時(shí),表示報(bào)文未被追蹤,當(dāng)報(bào)文的狀態(tài)為 Untracked 時(shí)通常表示無法找到相關(guān)的連接。
剛才舉例中的問題即可使用 state 擴(kuò)展模塊解決,我們只要放行狀態(tài)為 ESTABLISHED 的報(bào)文即可,因?yàn)槿绻麍?bào)文的狀態(tài)為 ESTABLISHED,那么報(bào)文肯定是之前發(fā)出的報(bào)文的回應(yīng),這樣,就表示只有回應(yīng)我們的報(bào)文能夠通過防火墻,如果是別人主動(dòng)發(fā)送過來的新的報(bào)文,則無法通過防火墻:
iptables-tfilter-IINPUT-mstate--stateESTABLISHED-jACCEPT
mangle 表
mangle 表的主要功能是根據(jù)規(guī)則修改數(shù)據(jù)包的一些標(biāo)志位,以便其他規(guī)則或程序可以利用這種標(biāo)志對數(shù)據(jù)包進(jìn)行過濾或策略路由。mangle 表主要有以下 3 種操作:
TOS:用來設(shè)置或改變數(shù)據(jù)包的服務(wù)類型域。這常用來設(shè)置網(wǎng)絡(luò)上的數(shù)據(jù)包如何被路由等策略。注意這個(gè)操作并不完善,有時(shí)得不所愿。它在Internet 上還不能使用,而且很多路由器不會(huì)注意到這個(gè)域值。換句話說,不要設(shè)置發(fā)往 Internet 的包,除非你打算依靠 TOS 來路由,比如用 iproute2。
TTL:用來改變數(shù)據(jù)包的生存時(shí)間域,我們可以讓所有數(shù)據(jù)包只有一個(gè)特殊的 TTL。它的存在有 一個(gè)很好的理由,那就是我們可以欺騙一些ISP。為什么要欺騙他們呢?因?yàn)樗麄儾辉敢庾屛覀児蚕硪粋€(gè)連接。那些 ISP 會(huì)查找一臺單獨(dú)的計(jì)算機(jī)是否使用不同的 TTL,并且以此作為判斷連接是否被共享的標(biāo)志。
MARK 用來給包設(shè)置特殊的標(biāo)記。iproute 2能識別這些標(biāo)記,并根據(jù)不同的標(biāo)記(或沒有標(biāo)記) 決定不同的路由。用這些標(biāo)記我們可以做帶寬限制和基于請求的分類。
例如內(nèi)網(wǎng)的客戶端通過 Linux 主機(jī)連入 Internet,而 Linux 主機(jī)與Internet 連接時(shí)有兩條線路,它們的網(wǎng)關(guān)如圖所示?,F(xiàn)要求對內(nèi)網(wǎng)進(jìn)行策略路由,所有通過 TCP 協(xié)議訪問 80 端口的數(shù)據(jù)包都從 ChinaNet 線路出去,而所有訪問 UDP 協(xié)議 53 號端口的數(shù)據(jù)包都從 Cernet 線路出去。
這是一個(gè)策略路由的問題,為了達(dá)到目的,在對數(shù)據(jù)包進(jìn)行路由前,要先根據(jù)數(shù)據(jù)包的協(xié)議和目的端口給數(shù)據(jù)包做上一種標(biāo)志,然后再指定相應(yīng)規(guī)則,根據(jù)數(shù)據(jù)包的標(biāo)志進(jìn)行策略路由。為了給特定的數(shù)據(jù)包做上標(biāo)志,需要使用mangle 表,mangle 表共有 5 條鏈,由于需要在路由選擇前做標(biāo)志,因此應(yīng)該使用 PREROUTING 鏈,下面是具體的命令:
iptables-tmangle-APREROUTING-ieth0-ptcp--dport80-jMARK--set-mark1; iptables-tmangle-APREROUTING-ieth0-pudp--dprot53-jMARK--set-mark2;
數(shù)據(jù)包經(jīng)過 PREROUTING 鏈后,將要進(jìn)入路由選擇模塊,為了對其進(jìn)行策略路由,執(zhí)行以下兩條命令,添加相應(yīng)的規(guī)則:
ipruleaddfromallfwmark1table10 ipruleaddfromallfwmark2table20
以上兩條命令表示所有標(biāo)志是1的數(shù)據(jù)包使用路由表 10 進(jìn)行路由,而所有標(biāo)志是 2 的數(shù)據(jù)包使用路由表 20 進(jìn)行路由。路由表 10 和 20 分別使用了 ChinaNet 和 Cernet 線路上的網(wǎng)關(guān)作為默認(rèn)網(wǎng)關(guān),具體設(shè)置命令如下所示:
iprouteadddefaultvia10.10.1.1deveth1table10 iprouteadddefaultvia10.10.2.1deveth2table20
以上兩條命令在路由表 10 和 20 上分別指定了 10.10.1.1 和 10.10.2.1 作為默認(rèn)網(wǎng)關(guān),它們分別位于 ChinaNet 和 Cernet 線路上。于是,使用路由表 10 的數(shù)據(jù)包將通過 ChinaNet 線路出去,而使用路由表20的數(shù)據(jù)包將通過 Cernet 線路出去。
自定義鏈
當(dāng)默認(rèn)鏈中的規(guī)則非常多時(shí),不方便我們管理。想象一下,如果 INPUT 鏈中存放了 200 條規(guī)則,這 200 條規(guī)則有針對 httpd 服務(wù)的,有針對 sshd 服務(wù)的,有針對私網(wǎng) IP 的,有針對公網(wǎng) IP 的,假如,我們突然想要修改針對 httpd 服務(wù)的相關(guān)規(guī)則,難道我們還要從頭看一遍這 200 條規(guī)則,找出哪些規(guī)則是針對 httpd 的嗎?這顯然不合理。
所以,iptables 中,可以自定義鏈,通過自定義鏈即可解決上述問題。假設(shè),我們自定義一條鏈,鏈名叫 IN_WEB,我們可以將所有針對 80 端口的入站規(guī)則都寫入到這條自定義鏈中,當(dāng)以后想要修改針對 web 服務(wù)的入站規(guī)則時(shí),就直接修改 IN_WEB 鏈中的規(guī)則就好了,即使默認(rèn)鏈中有再多的規(guī)則,我們也不會(huì)害怕了,因?yàn)槲覀冎?,所有針?80 端口的入站規(guī)則都存放在IN_WEB鏈中。
創(chuàng)建自定義鏈
#在filter表中創(chuàng)建IN_WEB自定義鏈 iptables-tfilter-NIN_WEB
引用自定義鏈
#在INPUT鏈中引用剛才創(chuàng)建的自定義鏈 iptables-tfilter-IINPUT-ptcp--dport80-jIN_WEB
重命名自定義鏈
#將IN_WEB自定義鏈重命名為WEB iptables-EIN_WEBWEB
刪除自定義鏈
刪除自定義鏈需要滿足兩個(gè)條件:
自定義鏈沒有被引用。
自定義鏈中沒有任何規(guī)則。
#第一步:清除自定義鏈中的規(guī)則 iptables-tfilter-FWEB #第二步:刪除自定義鏈 iptables-tfilter-XWEB
LOG 動(dòng)作
LOG 動(dòng)作默認(rèn)會(huì)將報(bào)文的相關(guān)信息記錄在/var/log/message文件中,當(dāng)然,我們也可以將相關(guān)信息記錄在指定的文件中,以防止 iptables 的相關(guān)信息與其他日志信息相混淆,修改 /etc/rsyslog.conf 文件(或者 /etc/syslog.conf),在 rsyslog 配置文件中添加如下配置即可:
kern.warning/var/log/iptables.log
完成上述配置后,重啟rsyslog服務(wù)(或者syslogd):
servicersyslogrestart
LOG 動(dòng)作也有自己的選項(xiàng),常用選項(xiàng)如下:
–log-level 選項(xiàng)可以指定記錄日志的日志級別,可用級別有 emerg,alert,crit,error,warning,notice,info,debug。
–log-prefix 選項(xiàng)可以給記錄到的相關(guān)信息添加”標(biāo)簽”之類的信息,以便區(qū)分各種記錄到的報(bào)文信息,方便在分析時(shí)進(jìn)行過濾。–log-prefix 對應(yīng)的值不能超過 29 個(gè)字符。
比如,我想要將主動(dòng)連接22號端口的報(bào)文的相關(guān)信息都記錄到日志中,并且把這類記錄命名為”want-in-from-port-22″,則可以使用如下命令:
iptables-IINPUT-ptcp--dport22-mstate--stateNEW-jLOG--log-prefix"want-in-from-port-22"
完成上述配置后,我在IP地址為 192.168.1.98 的客戶端機(jī)上,嘗試使用 ssh 工具連接上例中的主機(jī),然后查看對應(yīng)的日志文件(已經(jīng)將日志文件設(shè)置為 /var/log/iptables.log):
如上圖所示,ssh 連接操作的報(bào)文的相關(guān)信息已經(jīng)被記錄到了 iptables.log 日志文件中,而且這條日志中包含”標(biāo)簽”:want-in-from-port-22,如果有很多日志記錄,我們就能通過這個(gè)”標(biāo)簽”進(jìn)行篩選了,這樣方便我們查看日志,同時(shí),從上述記錄中還能夠得知報(bào)文的源IP與目標(biāo)IP,源端口與目標(biāo)端口等信息,從上述日志我們能夠看出,192.168.1.98 這個(gè) IP 想要在 14點(diǎn)11分 連接到 192.168.1.139(當(dāng)前主機(jī)的 IP)的22號端口,報(bào)文由eth4網(wǎng)卡進(jìn)入,eth4 網(wǎng)卡的 MAC 地址為 0029f4:d1,客戶端網(wǎng)卡的 MAC 地址為 f438b1:29。
審核編輯:湯梓紅
-
Linux
+關(guān)注
關(guān)注
87文章
11352瀏覽量
210540 -
HTTP
+關(guān)注
關(guān)注
0文章
511瀏覽量
31572 -
云原生
+關(guān)注
關(guān)注
0文章
252瀏覽量
7996
原文標(biāo)題:Iptables 介紹與使用
文章出處:【微信號:良許Linux,微信公眾號:良許Linux】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
Linux中使用Iptables實(shí)現(xiàn)簡單的網(wǎng)站防火墻
![Linux中使用<b class='flag-5'>Iptables</b>實(shí)現(xiàn)簡單的網(wǎng)站防火墻](https://file1.elecfans.com/web2/M00/A5/A1/wKgaomUM-ISAed5wAAAbwzSR_ew091.png)
nuc972如何啟動(dòng)iptables?
iptables 工具常用命令規(guī)則有哪些
使用iptables連接局域網(wǎng)和外網(wǎng)網(wǎng)卡時(shí)出現(xiàn)錯(cuò)誤
Linux的iptables配置文件
怎么下載iptables,如何安裝
請問如何自動(dòng)加載iptables的防火墻規(guī)則?
如何安裝“bridge-nf-call-iptables”模塊(I.MX8M Plus:hardknott)?
nuc972如何啟動(dòng)iptables?
nuc972如何啟動(dòng)iptables?
Iptables的移植步驟
基于Linux下iptables超詳細(xì)教程和使用示例
嵌入式linux 系統(tǒng)iptables 編譯及安裝
![嵌入式linux 系統(tǒng)<b class='flag-5'>iptables</b> 編譯及安裝](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
Iptables移植到嵌入式Linux系統(tǒng)
![<b class='flag-5'>Iptables</b>移植到嵌入式Linux系統(tǒng)](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
Netfilter/iptables
![Netfilter/<b class='flag-5'>iptables</b>](https://file.elecfans.com/web2/M00/7F/2E/pYYBAGOGQFSAZRlWAAA_-_un8Gs246.png)
評論