0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Netfilter 的設(shè)計(jì)與實(shí)現(xiàn)

科技綠洲 ? 來(lái)源:Linux開(kāi)發(fā)架構(gòu)之路 ? 作者:Linux開(kāi)發(fā)架構(gòu)之路 ? 2023-11-13 10:34 ? 次閱讀

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ù)包為例:

  1. 在物理-網(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

  1. 假設(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)入傳輸層。
  2. 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 向量之一:

  1. NF_ACCEPT: 在處理路徑上正常繼續(xù)(實(shí)際上是在 NF-HOOK 中最后執(zhí)行傳入的 okfn)。
  2. NF_DROP: 丟棄數(shù)據(jù)包,終止處理。
  3. NF_STOLEN: 數(shù)據(jù)包已轉(zhuǎn)交,終止處理。
  4. NF_QUEUE: 將數(shù)據(jù)包入隊(duì)后供其他處理。
  5. 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ò)程:

  1. 通過(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。
  2. 對(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 部分組成:

  1. 一個(gè) ipt_entry 結(jié)構(gòu)體。通過(guò) .next_offset 指向下一個(gè) ipt_entry 的內(nèi)存偏移地址。
  2. 0 個(gè)或多個(gè) ipt_entry_match 結(jié)構(gòu)體,每個(gè)結(jié)構(gòu)體可以動(dòng)態(tài)的添加額外數(shù)據(jù)。
  3. 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

  1. 首先檢查數(shù)據(jù)包的 IP 首部與第一條規(guī)則 ipt_entry 的 .ipt_ip 屬性是否一致,如不匹配根據(jù) next_offset 屬性跳轉(zhuǎn)到下一條規(guī)則。
  2. 若 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é)果。
  3. 所有檢查通過(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)。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 數(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
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Linux內(nèi)核防火墻netfilter的原理和應(yīng)用

    netfilter內(nèi)核防火墻,它采用更完善的框架結(jié)構(gòu),具有許多新功能,如完整的動(dòng)態(tài)NAT、基于用戶和MAC地址的過(guò)濾、真正基于狀態(tài)的過(guò)濾等。netfilter實(shí)現(xiàn)了擴(kuò)展過(guò)濾規(guī)則而不必修改內(nèi)核。2 
    發(fā)表于 09-19 09:22

    netfilter的工作原理是什么?

    netfilter定義了協(xié)議棧中的檢查點(diǎn)和檢查點(diǎn)上引用的數(shù)據(jù)結(jié)構(gòu)以及對(duì)這些數(shù)據(jù)結(jié)構(gòu)引用的過(guò)程。檢查點(diǎn)由宏NF_HOOK定義。
    發(fā)表于 09-26 09:10

    如何去實(shí)現(xiàn)netfilter

    Linux下支持netfilter機(jī)制的配置工具就是iptables,它也就相當(dāng)與一個(gè)應(yīng)用程序,可以對(duì)netfilter進(jìn)行配置(包過(guò)濾規(guī)則,NAT等等)。所以要實(shí)現(xiàn)netfilter
    發(fā)表于 11-05 06:12

    netfilter技術(shù)分析及在入侵響應(yīng)中的應(yīng)用

    netfilter總體結(jié)構(gòu)入手,分析了netfilter的連線跟蹤、包過(guò)濾、地址轉(zhuǎn)換、包處理等關(guān)鍵技術(shù)。在此基礎(chǔ)上,研究了入侵響應(yīng)策略,提出了基于netfilter的主動(dòng)響應(yīng)模型。經(jīng)測(cè)試證明
    發(fā)表于 11-18 09:47 ?23次下載

    基于Netfilter的NAT技術(shù)及其應(yīng)用

    NAT技術(shù)是為了解決IPv4網(wǎng)絡(luò)地址空間的不夠而提出的一種過(guò)渡技術(shù),并由于其簡(jiǎn)單、高效的特性而得到了廣泛的應(yīng)用。該文介紹了NAT技術(shù)及在Linux 2.4內(nèi)核中基于Netfilter框架的NAT實(shí)現(xiàn)
    發(fā)表于 12-29 23:53 ?20次下載

    基于Netfilter內(nèi)核態(tài)網(wǎng)絡(luò)流量分析研究

    網(wǎng)絡(luò)流量采集與分析是網(wǎng)絡(luò)流量測(cè)量的核心技術(shù)。本文基于Linux 平臺(tái)內(nèi)核空間下的Netfilter 框架,提出并實(shí)現(xiàn)了內(nèi)核級(jí)的流量采集和分析的方法,能對(duì)流經(jīng)局域網(wǎng)內(nèi)的所有數(shù)據(jù)包進(jìn)
    發(fā)表于 01-09 15:13 ?22次下載

    netfilter技術(shù)分析

    netfilter技術(shù)分析 netfilter是由Rusty Russell提出的Linux 2.4內(nèi)核防火墻框架,該框架既簡(jiǎn)潔又靈活,可實(shí)現(xiàn)安全策略應(yīng)用
    發(fā)表于 11-18 09:50 ?849次閱讀
    <b class='flag-5'>netfilter</b>技術(shù)分析

    什么是netfilter?netfilter是什么意思?

    netfilter的定義: netfilter是由Rusty Russell提出的Linux 2.4內(nèi)核防火墻框架,該框架既簡(jiǎn)潔又靈活,
    發(fā)表于 11-18 09:54 ?2330次閱讀
    什么是<b class='flag-5'>netfilter</b>?<b class='flag-5'>netfilter</b>是什么意思?

    Linux網(wǎng)絡(luò)防火墻Netfilter的數(shù)據(jù)包傳輸過(guò)濾原理

    給出了Linux網(wǎng)絡(luò)防火墻Netfilter在IPV4網(wǎng)絡(luò)環(huán)境下,Netfilter框架掛接點(diǎn)結(jié)構(gòu)及數(shù)據(jù)包的傳輸流程,并描述了在該流程中進(jìn)行數(shù)據(jù)包傳輸過(guò)濾的5個(gè)掛接點(diǎn)鉤子函數(shù)的功能,以及鉤子函數(shù)各種可能返
    發(fā)表于 02-27 11:33 ?22次下載
    Linux網(wǎng)絡(luò)防火墻<b class='flag-5'>Netfilter</b>的數(shù)據(jù)包傳輸過(guò)濾原理

    Netfilter架構(gòu)下數(shù)據(jù)包信息存儲(chǔ)的應(yīng)用_吳良敏

    Netfilter架構(gòu)下數(shù)據(jù)包信息存儲(chǔ)的應(yīng)用_吳良敏
    發(fā)表于 03-19 11:27 ?0次下載

    Iptables的移植步驟

    Linux下支持netfilter機(jī)制的配置工具就是iptables,它也就相當(dāng)與一個(gè)應(yīng)用程序,可以對(duì)netfilter進(jìn)行配置(包過(guò)濾規(guī)則,NAT等等)。所以要實(shí)現(xiàn)netfilter
    發(fā)表于 08-18 09:01 ?2559次閱讀

    Iptables移植到嵌入式Linux系統(tǒng)

    Linux下支持netfilter機(jī)制的配置工具就是iptables,它也就相當(dāng)與一個(gè)應(yīng)用程序,可以對(duì)netfilter進(jìn)行配置(包過(guò)濾規(guī)則,NAT等等)。所以要實(shí)現(xiàn)netfilter
    發(fā)表于 11-02 14:51 ?1次下載
    Iptables移植到嵌入式Linux系統(tǒng)

    Linux內(nèi)核中Netfilter的設(shè)計(jì)與實(shí)現(xiàn)

    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)
    的頭像 發(fā)表于 05-26 15:27 ?2037次閱讀

    簡(jiǎn)述kube-proxy ipvs原理

    iptables 與 IPVS 都是基于 Netfilter 實(shí)現(xiàn)的,但因?yàn)槎ㄎ徊煌?,二者有著本質(zhì)的差別:iptables 是為防火墻而設(shè)計(jì)的;IPVS 則專門用于高性能負(fù)載均衡,并使用更高效的數(shù)據(jù)結(jié)構(gòu)(Hash 表),允許幾乎無(wú)限的規(guī)模擴(kuò)張。
    的頭像 發(fā)表于 05-22 11:35 ?761次閱讀

    Netfilter/iptables

    Netfilter是運(yùn)行在Linux中的一個(gè)功能,因?yàn)長(zhǎng)inux是一個(gè)模塊化的內(nèi)核,所以Netfilter是以模塊形式存在于Linux中的。Netfilter和iptables的關(guān)系我的github
    的頭像 發(fā)表于 04-06 15:13 ?519次閱讀
    <b class='flag-5'>Netfilter</b>/iptables