Netfilter (配合 iptables)使得用戶空間應(yīng)用程序可以注冊(cè)內(nèi)核網(wǎng)絡(luò)棧在處理數(shù)據(jù)包時(shí)應(yīng)用的處理規(guī)則,實(shí)現(xiàn)高效的網(wǎng)絡(luò)轉(zhuǎn)發(fā)和過(guò)濾。很多常見(jiàn)的主機(jī)防火墻程序以及 Kubernetes 的 Service 轉(zhuǎn)發(fā)都是通過(guò) iptables 來(lái)實(shí)現(xiàn)的。
關(guān)于 netfilter 的介紹文章大部分只描述了抽象的概念,實(shí)際上其內(nèi)核代碼的基本實(shí)現(xiàn)不算復(fù)雜,本文主要參考 Linux 內(nèi)核 2.6 版本代碼(早期版本較為簡(jiǎn)單),與最新的 5.x 版本在實(shí)現(xiàn)上可能有較大差異,但基本設(shè)計(jì)變化不大,不影響理解其原理。
本文假設(shè)讀者已對(duì) TCP/IP 協(xié)議有基本了解。
Netfilter 的設(shè)計(jì)與實(shí)現(xiàn)
netfilter 的定義是一個(gè)工作在 Linux 內(nèi)核的網(wǎng)絡(luò)數(shù)據(jù)包處理框架,為了徹底理解 netfilter 的工作方式,我們首先需要對(duì)數(shù)據(jù)包在 Linux 內(nèi)核中的處理路徑建立基本認(rèn)識(shí)。
數(shù)據(jù)包的內(nèi)核之旅
數(shù)據(jù)包在內(nèi)核中的處理路徑,也就是處理網(wǎng)絡(luò)數(shù)據(jù)包的內(nèi)核代碼調(diào)用鏈,大體上也可按 TCP/IP 模型分為多個(gè)層級(jí),以接收一個(gè) IPv4 的 tcp 數(shù)據(jù)包為例:
- 在物理-網(wǎng)絡(luò)設(shè)備層,網(wǎng)卡通過(guò) DMA 將接收到的數(shù)據(jù)包寫入內(nèi)存中的 ring buffer,經(jīng)過(guò)一系列中斷和調(diào)度后,操作系統(tǒng)內(nèi)核調(diào)用 __skb_dequeue 將數(shù)據(jù)包加入對(duì)應(yīng)設(shè)備的處理隊(duì)列中,并轉(zhuǎn)換成 sk_buffer 類型(即 socket buffer - 將在整個(gè)內(nèi)核調(diào)用棧中持續(xù)作為參數(shù)傳遞的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu),下文指稱的數(shù)據(jù)包都可以認(rèn)為是 sk_buffer),最后調(diào)用 netif_receive_skb 函數(shù)按協(xié)議類型對(duì)數(shù)據(jù)包進(jìn)行分類,并跳轉(zhuǎn)到對(duì)應(yīng)的處理函數(shù)。如下圖所示:
network-path
- 假設(shè)該數(shù)據(jù)包為 IP 協(xié)議包,對(duì)應(yīng)的接收包處理函數(shù) ip_rcv 將被調(diào)用,數(shù)據(jù)包處理進(jìn)入網(wǎng)絡(luò)(IP)層。ip_rcv 檢查數(shù)據(jù)包的 IP 首部并丟棄出錯(cuò)的包,必要時(shí)還會(huì)聚合被分片的 IP 包。然后執(zhí)行 ip_rcv_finish 函數(shù),對(duì)數(shù)據(jù)包進(jìn)行路由查詢并決定是將數(shù)據(jù)包交付本機(jī)還是轉(zhuǎn)發(fā)其他主機(jī)。假設(shè)數(shù)據(jù)包的目的地址是本主機(jī),接著執(zhí)行的 dst_input 函數(shù)將調(diào)用 ip_local_deliver 函數(shù)。ip_local_deliver 函數(shù)中將根據(jù) IP 首部中的協(xié)議號(hào)判斷載荷數(shù)據(jù)的協(xié)議類型,最后調(diào)用對(duì)應(yīng)類型的包處理函數(shù)。本例中將調(diào)用 TCP 協(xié)議對(duì)應(yīng)的 tcp_v4_rcv 函數(shù),之后數(shù)據(jù)包處理進(jìn)入傳輸層。
- tcp_v4_rcv 函數(shù)同樣讀取數(shù)據(jù)包的 TCP 首部并計(jì)算校驗(yàn)和,然后在數(shù)據(jù)包對(duì)應(yīng)的 TCP control buffer 中維護(hù)一些必要狀態(tài)包括 TCP 序列號(hào)以及 SACK 號(hào)等。該函數(shù)下一步將調(diào)用 __tcp_v4_lookup 查詢數(shù)據(jù)包對(duì)應(yīng)的 socket,如果沒(méi)找到或 socket 的連接狀態(tài)處于TCP_TIME_WAIT,數(shù)據(jù)包將被丟棄。如果 socket 處于未加鎖狀態(tài),數(shù)據(jù)包將通過(guò)調(diào)用 tcp_prequeue 函數(shù)進(jìn)入 prequeue 隊(duì)列,之后數(shù)據(jù)包將可被用戶態(tài)的用戶程序所處理。傳輸層的處理流程超出本文討論范圍,實(shí)際上還要復(fù)雜很多。
netfilter hooks
接下來(lái)我們正式進(jìn)入主題。netfilter 的首要組成部分是 netfilter hooks。
hook 觸發(fā)點(diǎn)
對(duì)于不同的協(xié)議(IPv4、IPv6 或 ARP 等),Linux 內(nèi)核網(wǎng)絡(luò)棧會(huì)在該協(xié)議棧數(shù)據(jù)包處理路徑上的預(yù)設(shè)位置觸發(fā)對(duì)應(yīng)的 hook。在不同協(xié)議處理流程中的觸發(fā)點(diǎn)位置以及對(duì)應(yīng)的 hook 名稱(藍(lán)色矩形外部的黑體字)如下,本文僅重點(diǎn)關(guān)注 IPv4 協(xié)議:
netfilter-flow
所謂的 hook 實(shí)質(zhì)上是代碼中的枚舉對(duì)象(值為從 0 開(kāi)始遞增的整型):
enum nf_inet_hooks { NF_INET_PRE_ROUTING, NF_INET_LOCAL_IN, NF_INET_FORWARD, NF_INET_LOCAL_OUT, NF_INET_POST_ROUTING, NF_INET_NUMHOOKS };
每個(gè) hook 在內(nèi)核網(wǎng)絡(luò)棧中對(duì)應(yīng)特定的觸發(fā)點(diǎn)位置,以 IPv4 協(xié)議棧為例,有以下 netfilter hooks 定義:
netfilter-hooks-stack
- NF_INET_PRE_ROUTING: 這個(gè) hook 在 IPv4 協(xié)議棧的 ip_rcv 函數(shù)或 IPv6 協(xié)議棧的 ipv6_rcv 函數(shù)中執(zhí)行。所有接收數(shù)據(jù)包到達(dá)的第一個(gè) hook 觸發(fā)點(diǎn)(實(shí)際上新版本 Linux 增加了 INGRESS hook 作為最早觸發(fā)點(diǎn)),在進(jìn)行路由判斷之前執(zhí)行。
- NF_INET_LOCAL_IN: 這個(gè) hook 在 IPv4 協(xié)議棧的 ip_local_deliver() 函數(shù)或 IPv6 協(xié)議棧的 ip6_input() 函數(shù)中執(zhí)行。經(jīng)過(guò)路由判斷后,所有目標(biāo)地址是本機(jī)的接收數(shù)據(jù)包到達(dá)此 hook 觸發(fā)點(diǎn)。
- NF_INET_FORWARD: 這個(gè) hook 在 IPv4 協(xié)議棧的 ip_forward() 函數(shù)或 IPv6 協(xié)議棧的 ip6_forward() 函數(shù)中執(zhí)行。經(jīng)過(guò)路由判斷后,所有目標(biāo)地址不是本機(jī)的接收數(shù)據(jù)包到達(dá)此 hook 觸發(fā)點(diǎn)。
- NF_INET_LOCAL_OUT: 這個(gè) hook 在 IPv4 協(xié)議棧的 __ip_local_out() 函數(shù)或 IPv6 協(xié)議棧的 __ip6_local_out() 函數(shù)中執(zhí)行。所有本機(jī)產(chǎn)生的準(zhǔn)備發(fā)出的數(shù)據(jù)包,在進(jìn)入網(wǎng)絡(luò)棧后首先到達(dá)此 hook 觸發(fā)點(diǎn)。
- NF_INET_POST_ROUTING: 這個(gè) hook 在 IPv4 協(xié)議棧的 ip_output() 函數(shù)或 IPv6 協(xié)議棧的 ip6_finish_output2() 函數(shù)中執(zhí)行。本機(jī)產(chǎn)生的準(zhǔn)備發(fā)出的數(shù)據(jù)包或者轉(zhuǎn)發(fā)的數(shù)據(jù)包,在經(jīng)過(guò)路由判斷之后, 將到達(dá)此 hook 觸發(fā)點(diǎn)。
NF_HOOK 宏和 netfilter 向量
所有的觸發(fā)點(diǎn)位置統(tǒng)一調(diào)用 NF_HOOK 這個(gè)宏來(lái)觸發(fā) hook:
static inline int NF_HOOK(uint8_t pf, unsigned int hook, struct sk_buff *skb, struct net_device *in, struct net_device *out, int (*okfn)(struct sk_buff *)) { return NF_HOOK_THRESH(pf, hook, skb, in, out, okfn, INT_MIN); }
NF-HOOK 接收的參數(shù)如下:
- pf: 數(shù)據(jù)包的協(xié)議族,對(duì) IPv4 來(lái)說(shuō)是 NFPROTO_IPV4。
- hook: 上圖中所示的 netfilter hook 枚舉對(duì)象,如 NF_INET_PRE_ROUTING 或 NF_INET_LOCAL_OUT。
- skb: SKB 對(duì)象,表示正在被處理的數(shù)據(jù)包。
- in: 數(shù)據(jù)包的輸入網(wǎng)絡(luò)設(shè)備。
- out: 數(shù)據(jù)包的輸出網(wǎng)絡(luò)設(shè)備。
- okfn: 一個(gè)指向函數(shù)的指針,該函數(shù)將在該 hook 即將終止時(shí)調(diào)用,通常傳入數(shù)據(jù)包處理路徑上的下一個(gè)處理函數(shù)。
NF-HOOK 的返回值是以下具有特定含義的 netfilter 向量之一:
- NF_ACCEPT: 在處理路徑上正常繼續(xù)(實(shí)際上是在 NF-HOOK 中最后執(zhí)行傳入的 okfn)。
- NF_DROP: 丟棄數(shù)據(jù)包,終止處理。
- NF_STOLEN: 數(shù)據(jù)包已轉(zhuǎn)交,終止處理。
- NF_QUEUE: 將數(shù)據(jù)包入隊(duì)后供其他處理。
- NF_REPEAT: 重新調(diào)用當(dāng)前 hook。
回歸到源碼,IPv4 內(nèi)核網(wǎng)絡(luò)棧會(huì)在以下代碼模塊中調(diào)用 NF_HOOK():
NF_HOOK
實(shí)際調(diào)用方式以 net/ipv4/ip_forward.c
[1] 對(duì)數(shù)據(jù)包進(jìn)行轉(zhuǎn)發(fā)的源碼為例,在 ip_forward 函數(shù)結(jié)尾部分的第 115 行以 NF_INET_FORWARDhook 作為入?yún)⒄{(diào)用了 NF_HOOK 宏,并將網(wǎng)絡(luò)棧接下來(lái)的處理函數(shù) ip_forward_finish 作為 okfn 參數(shù)傳入:
int ip_forward(struct sk_buff *skb) { .....(省略部分代碼) if (rt- >rt_flags&RTCF_DOREDIRECT && !opt- >srr && !skb_sec_path(skb)) ip_rt_send_redirect(skb); skb- >priority = rt_tos2priority(iph- >tos); return NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD, skb, skb- >dev, rt- >dst.dev, ip_forward_finish); .....(省略部分代碼) }
回調(diào)函數(shù)與優(yōu)先級(jí)
netfilter 的另一組成部分是 hook 的回調(diào)函數(shù)。內(nèi)核網(wǎng)絡(luò)棧既使用 hook 來(lái)代表特定觸發(fā)位置,也使用 hook (的整數(shù)值)作為數(shù)據(jù)索引來(lái)訪問(wèn)觸發(fā)點(diǎn)對(duì)應(yīng)的回調(diào)函數(shù)。
內(nèi)核的其他模塊可以通過(guò) netfilter 提供的 api 向指定的 hook 注冊(cè)回調(diào)函數(shù),同一 hook 可以注冊(cè)多個(gè)回調(diào)函數(shù),通過(guò)注冊(cè)時(shí)指定的 priority 參數(shù)可指定回調(diào)函數(shù)在執(zhí)行時(shí)的優(yōu)先級(jí)。
注冊(cè) hook 的回調(diào)函數(shù)時(shí),首先需要定義一個(gè) nf_hook_ops 結(jié)構(gòu)(或由多個(gè)該結(jié)構(gòu)組成的數(shù)組),其定義如下:
struct nf_hook_ops { struct list_head list; /* User fills in from here down. */ nf_hookfn *hook; struct module *owner; u_int8_t pf; unsigned int hooknum; /* Hooks are ordered in ascending priority. */ int priority; };
在定義中有 3 個(gè)重要成員:
- hook: 將要注冊(cè)的回調(diào)函數(shù),函數(shù)參數(shù)定義與 NF_HOOK 類似,可通過(guò) okfn參數(shù)嵌套其他函數(shù)。
- hooknum: 注冊(cè)的目標(biāo) hook 枚舉值。
- priority: 回調(diào)函數(shù)的優(yōu)先級(jí),較小的值優(yōu)先執(zhí)行。
定義結(jié)構(gòu)體后可通過(guò) int nf_register_hook(struct nf_hook_ops *reg) 或 int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n); 分別注冊(cè)一個(gè)或多個(gè)回調(diào)函數(shù)。同一 netfilter hook 下所有的nf_hook_ops 注冊(cè)后以 priority 為順序組成一個(gè)鏈表結(jié)構(gòu),注冊(cè)過(guò)程會(huì)根據(jù) priority 從鏈表中找到合適的位置,然后執(zhí)行鏈表插入操作。
在執(zhí)行 NF-HOOK 宏觸發(fā)指定的 hook 時(shí),將調(diào)用 nf_iterate 函數(shù)迭代這個(gè) hook 對(duì)應(yīng)的 nf_hook_ops 鏈表,并依次調(diào)用每一個(gè) nf_hook_ops 的注冊(cè)函數(shù)成員 hookfn。示意圖如下:
netfilter-hookfn1
這種鏈?zhǔn)秸{(diào)用回調(diào)函數(shù)的工作方式,也讓 netfilter hook 被稱為 Chain,下文的 iptables 介紹中尤其體現(xiàn)了這一關(guān)聯(lián)。
每個(gè)回調(diào)函數(shù)也必須返回一個(gè) netfilter 向量;如果該向量為 NF_ACCEPT,nf_iterate 將會(huì)繼續(xù)調(diào)用下一個(gè) nf_hook_ops 的回調(diào)函數(shù),直到所有回調(diào)函數(shù)調(diào)用完畢后返回 NF_ACCEPT;如果該向量為 NF_DROP,將中斷遍歷并直接返回 NF_DROP; 如果該向量為 NF_REPEAT ,將重新執(zhí)行該回調(diào)函數(shù) 。nf_iterate 的返回值也將作為 NF-HOOK 的返回值,網(wǎng)絡(luò)棧將根據(jù)該向量值判斷是否繼續(xù)執(zhí)行處理函數(shù)。示意圖如下:
netfilter-hookfn2
netfilter hook 的回調(diào)函數(shù)機(jī)制具有以下特性:
- 回調(diào)函數(shù)按優(yōu)先級(jí)依次執(zhí)行,只有上一回調(diào)函數(shù)返回 NF_ACCEPT 才會(huì)繼續(xù)執(zhí)行下一回調(diào)函數(shù)。
- 任一回調(diào)函數(shù)都可以中斷該 hook 的回調(diào)函數(shù)執(zhí)行鏈,同時(shí)要求整個(gè)網(wǎng)絡(luò)棧中止對(duì)數(shù)據(jù)包的處理。
iptables
基于內(nèi)核 netfilter 提供的 hook 回調(diào)函數(shù)機(jī)制,netfilter 作者 Rusty Russell 還開(kāi)發(fā)了 iptables,實(shí)現(xiàn)在用戶空間管理應(yīng)用于數(shù)據(jù)包的自定義規(guī)則。
iptbles 分為兩部分:
- 用戶空間的 iptables 命令向用戶提供訪問(wèn)內(nèi)核 iptables 模塊的管理界面。
- 內(nèi)核空間的 iptables 模塊在內(nèi)存中維護(hù)規(guī)則表,實(shí)現(xiàn)表的創(chuàng)建及注冊(cè)。
內(nèi)核空間模塊
xt_table 的初始化
在內(nèi)核網(wǎng)絡(luò)棧中,iptables 通過(guò) xt_table 結(jié)構(gòu)對(duì)眾多的數(shù)據(jù)包處理規(guī)則進(jìn)行有序管理,一個(gè) xt_table 對(duì)應(yīng)一個(gè)規(guī)則表,對(duì)應(yīng)的用戶空間概念為 table。不同的規(guī)則表有以下特征:
- 對(duì)不同的 netfilter hooks 生效。
- 在同一 hook 中檢查不同規(guī)則表的優(yōu)先級(jí)不同。
基于規(guī)則的最終目的,iptables 默認(rèn)初始化了 4 個(gè)不同的規(guī)則表,分別是 raw、 filter、nat 和 mangle。下文以 filter 為例介紹 xt_table的初始化和調(diào)用過(guò)程。
filter table 的定義如下:
#define FILTER_VALID_HOOKS ((1 < < NF_INET_LOCAL_IN) | (1 < < NF_INET_FORWARD) | (1 < < NF_INET_LOCAL_OUT)) static const struct xt_table packet_filter = { .name = "filter", .valid_hooks = FILTER_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_IPV4, .priority = NF_IP_PRI_FILTER, }; (net/ipv4/netfilter/iptable_filter.c)
在 iptable_filter.c[2] 模塊的初始化函數(shù) iptable_filter_init ****中,調(diào)用xt_hook_link 對(duì) xt_table 結(jié)構(gòu) packet_filter 執(zhí)行如下初始化過(guò)程:
- 通過(guò) .valid_hooks 屬性迭代 xt_table 將生效的每一個(gè) hook,對(duì)于 filter 來(lái)說(shuō)是 NF_INET_LOCAL_IN,NF_INET_FORWARD 和 NF_INET_LOCAL_OUT這 3 個(gè) hook。
- 對(duì)每一個(gè) hook,使用 xt_table 的 priority 屬性向 hook 注冊(cè)一個(gè)回調(diào)函數(shù)。
不同 table 的 priority 值如下:
enum nf_ip_hook_priorities { NF_IP_PRI_RAW = -300, NF_IP_PRI_MANGLE = -150, NF_IP_PRI_NAT_DST = -100, NF_IP_PRI_FILTER = 0, NF_IP_PRI_SECURITY = 50, NF_IP_PRI_NAT_SRC = 100, };
當(dāng)數(shù)據(jù)包到達(dá)某一 hook 觸發(fā)點(diǎn)時(shí),會(huì)依次執(zhí)行不同 table 在該 hook 上注冊(cè)的所有回調(diào)函數(shù),這些回調(diào)函數(shù)總是根據(jù)上文的 priority 值以固定的相對(duì)順序執(zhí)行:
tables-priority
ipt_do_table()
filter 注冊(cè)的 hook 回調(diào)函數(shù) iptable_filter_hook[3] 將對(duì) xt_table 結(jié)構(gòu)執(zhí)行公共的規(guī)則檢查函數(shù) ipt_do_table[4]。ipt_do_table 接收 skb、hook 和 xt_table作為參數(shù),對(duì) skb 執(zhí)行后兩個(gè)參數(shù)所確定的規(guī)則集,返回 netfilter 向量作為回調(diào)函數(shù)的返回值。
在深入規(guī)則執(zhí)行過(guò)程前,需要先了解規(guī)則集如何在內(nèi)存中表示。每一條規(guī)則由 3 部分組成:
- 一個(gè) ipt_entry 結(jié)構(gòu)體。通過(guò) .next_offset 指向下一個(gè) ipt_entry 的內(nèi)存偏移地址。
- 0 個(gè)或多個(gè) ipt_entry_match 結(jié)構(gòu)體,每個(gè)結(jié)構(gòu)體可以動(dòng)態(tài)的添加額外數(shù)據(jù)。
- 1 個(gè) ipt_entry_target 結(jié)構(gòu)體, 結(jié)構(gòu)體可以動(dòng)態(tài)的添加額外數(shù)據(jù)。
ipt_entry 結(jié)構(gòu)體定義如下:
struct ipt_entry { struct ipt_ip ip; unsigned int nfcache; /* ipt_entry + matches 在內(nèi)存中的大小*/ u_int16_t target_offset; /* ipt_entry + matches + target 在內(nèi)存中的大小 */ u_int16_t next_offset; /* 跳轉(zhuǎn)后指向前一規(guī)則 */ unsigned int comefrom; /* 數(shù)據(jù)包計(jì)數(shù)器 */ struct xt_counters counters; /* 長(zhǎng)度為0數(shù)組的特殊用法,作為 match 的內(nèi)存地址 */ unsigned char elems[0]; };
ipt_do_table 首先根據(jù) hook 類型以及 xt_table.private.entries屬性跳轉(zhuǎn)到對(duì)應(yīng)的規(guī)則集內(nèi)存區(qū)域,執(zhí)行如下過(guò)程:
ipt_do_table
- 首先檢查數(shù)據(jù)包的 IP 首部與第一條規(guī)則 ipt_entry 的 .ipt_ip 屬性是否一致,如不匹配根據(jù) next_offset 屬性跳轉(zhuǎn)到下一條規(guī)則。
- 若 IP 首部匹配 ,則開(kāi)始依次檢查該規(guī)則所定義的所有 ipt_entry_match 對(duì)象,與對(duì)象關(guān)聯(lián)的匹配函數(shù)將被調(diào)用,根據(jù)調(diào)用返回值有返回到回調(diào)函數(shù)(以及是否丟棄數(shù)據(jù)包)、跳轉(zhuǎn)到下一規(guī)則或繼續(xù)檢查等結(jié)果。
- 所有檢查通過(guò)后讀取 ipt_entry_target,根據(jù)其屬性返回 netfilter 向量到回調(diào)函數(shù)、繼續(xù)下一規(guī)則或跳轉(zhuǎn)到指定內(nèi)存地址的其他規(guī)則,非標(biāo)準(zhǔn) ipt_entry_target 還會(huì)調(diào)用被綁定的函數(shù),但只能返回向量值不能跳轉(zhuǎn)其他規(guī)則。
靈活性和更新時(shí)延
以上數(shù)據(jù)結(jié)構(gòu)與執(zhí)行方式為 iptables 提供了強(qiáng)大的擴(kuò)展能力,我們可以靈活地自定義每條規(guī)則的匹配條件并根據(jù)結(jié)果執(zhí)行不同行為,甚至還能在額外的規(guī)則集之間棧式跳轉(zhuǎn)。
由于每條規(guī)則長(zhǎng)度不等、內(nèi)部結(jié)構(gòu)復(fù)雜,且同一規(guī)則集位于連續(xù)的內(nèi)存空間,iptables 使用全量替換的方式來(lái)更新規(guī)則,這使得我們能夠從用戶空間以原子操作來(lái)添加/刪除規(guī)則,但非增量式的規(guī)則更新會(huì)在規(guī)則數(shù)量級(jí)較大時(shí)帶來(lái)嚴(yán)重的性能問(wèn)題:假如在一個(gè)大規(guī)模 Kubernetes 集群中使用 iptables 方式實(shí)現(xiàn) Service,當(dāng) service 數(shù)量較多時(shí),哪怕更新一個(gè) service 也會(huì)整體修改 iptables 規(guī)則表。全量提交的過(guò)程會(huì) kernel lock 進(jìn)行保護(hù),因此會(huì)有很大的更新時(shí)延。
用戶空間的 tables、chains 和 rules
用戶空間的 iptables 命令行可以讀取指定表的數(shù)據(jù)并渲染到終端,添加新的規(guī)則(實(shí)際上是替換整個(gè) table 的規(guī)則表)等。
iptables 主要操作以下幾種對(duì)象:
- table:對(duì)應(yīng)內(nèi)核空間的 xt_table 結(jié)構(gòu),iptable 的所有操作都對(duì)指定的 table 執(zhí)行,默認(rèn)為 filter。
- chain:對(duì)應(yīng)指定 table 通過(guò)特定 netfilter hook 調(diào)用的規(guī)則集,此外還可以自定義規(guī)則集,然后從 hook 規(guī)則集中跳轉(zhuǎn)過(guò)去。
- rule:對(duì)應(yīng)上文中 ipt_entry、ipt_entry_match 和ipt_entry_target,定義了對(duì)數(shù)據(jù)包的匹配規(guī)則以及匹配后執(zhí)行的行為。
- match:具有很強(qiáng)擴(kuò)展性的自定義匹配規(guī)則。
- target:具有很強(qiáng)擴(kuò)展性的自定義匹配后行為。
基于上文介紹的代碼調(diào)用過(guò)程流程,chain 和 rule 按如下示意圖執(zhí)行:
iptables-chains
對(duì)于 iptables 具體的用法和指令本文不做詳細(xì)介紹。
conntrack
僅僅通過(guò) 3、4 層的首部信息對(duì)數(shù)據(jù)包進(jìn)行過(guò)濾是不夠的,有時(shí)候還需要進(jìn)一步考慮連接的狀態(tài)。netfilter 通過(guò)另一內(nèi)置模塊 conntrack 進(jìn)行連接跟蹤(connection tracking),以提供根據(jù)連接過(guò)濾、地址轉(zhuǎn)換(NAT)等更進(jìn)階的網(wǎng)絡(luò)過(guò)濾功能。由于需要對(duì)連接狀態(tài)進(jìn)行判斷,conntrack 在整體機(jī)制相同的基礎(chǔ)上,又針對(duì)協(xié)議特點(diǎn)有單獨(dú)的實(shí)現(xiàn)。
-
數(shù)據(jù)包
+關(guān)注
關(guān)注
0文章
263瀏覽量
24407 -
模型
+關(guān)注
關(guān)注
1文章
3255瀏覽量
48899 -
應(yīng)用程序
+關(guān)注
關(guān)注
37文章
3280瀏覽量
57742 -
netfilter
+關(guān)注
關(guān)注
0文章
6瀏覽量
7192
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論