1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        深入理解 netfilter 和 iptables

        共 5612字,需瀏覽 12分鐘

         ·

        2022-05-31 14:43

        在公眾號(hào)后臺(tái)回復(fù):JGNB,可獲取杰哥原創(chuàng)的 PDF 手冊(cè)。

        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ā)和過濾。很多常見的主機(jī)防火墻程序以及 Kubernetes 的 Service 轉(zhuǎn)發(fā)都是通過 iptables 來實(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ì)變化不大,不影響理解其原理。

        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)卡通過 DMA 將接收到的數(shù)據(jù)包寫入內(nèi)存中的 ring buffer,經(jīng)過一系列中斷和調(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,如果沒找到或 socket 的連接狀態(tài)處于TCP_TIME_WAIT,數(shù)據(jù)包將被丟棄。如果 socket 處于未加鎖狀態(tài),數(shù)據(jù)包將通過調(diào)用 tcp_prequeue 函數(shù)進(jìn)入 prequeue 隊(duì)列,之后數(shù)據(jù)包將可被用戶態(tài)的用戶程序所處理。傳輸層的處理流程超出本文討論范圍,實(shí)際上還要復(fù)雜很多。

        netfilter hooks

        接下來我們正式進(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 開始遞增的整型):

        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)過路由判斷后,所有目標(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)過路由判斷后,所有目標(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)過路由判斷之后, 將到達(dá)此 hook 觸發(fā)點(diǎn)。

        NF_HOOK 宏和 netfilter 向量

        所有的觸發(fā)點(diǎn)位置統(tǒng)一調(diào)用 NF_HOOK 這個(gè)宏來觸發(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 來說是 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ò)棧接下來的處理函數(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 來代表特定觸發(fā)位置,也使用 hook (的整數(shù)值)作為數(shù)據(jù)索引來訪問觸發(fā)點(diǎn)對(duì)應(yīng)的回調(diào)函數(shù)。

        內(nèi)核的其他模塊可以通過 netfilter 提供的 api 向指定的 hook 注冊(cè)回調(diào)函數(shù),同一 hook 可以注冊(cè)多個(gè)回調(diào)函數(shù),通過注冊(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 類似,可通過 okfn參數(shù)嵌套其他函數(shù)。

        • hooknum: 注冊(cè)的目標(biāo) hook 枚舉值。

        • priority: 回調(diào)函數(shù)的優(yōu)先級(jí),較小的值優(yōu)先執(zhí)行。

        定義結(jié)構(gòu)體后可通過 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è)過程會(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 還開發(fā)了 iptables,實(shí)現(xiàn)在用戶空間管理應(yīng)用于數(shù)據(jù)包的自定義規(guī)則。

        iptbles 分為兩部分:

        • 用戶空間的 iptables 命令向用戶提供訪問內(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 通過 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)用過程。

        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](https://elixir.bootlin.com/linux/v2.6.39.4/C/ident/iptable_filter_init "iptable_filter_init") ****中,調(diào)用xt_hook_link 對(duì) xt_table 結(jié)構(gòu) packet_filter 執(zhí)行如下初始化過程:

        通過 .valid_hooks 屬性迭代 xt_table 將生效的每一個(gè) hook,對(duì)于 filter 來說是 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ī)則集如何在內(nèi)存中表示。每一條規(guī)則由 3 部分組成:

        • 一個(gè) ipt_entry 結(jié)構(gòu)體。通過 .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;?/*?長度為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í)行如下過程:

        ipt_do_table

        首先檢查數(shù)據(jù)包的 IP 首部與第一條規(guī)則 ipt_entry 的 .ipt_ip 屬性是否一致,如不匹配根據(jù) next_offset 屬性跳轉(zhuǎn)到下一條規(guī)則。

        若 IP 首部匹配 ,則開始依次檢查該規(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é)果。

        所有檢查通過后讀取 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ī)則長度不等、內(nèi)部結(jié)構(gòu)復(fù)雜,且同一規(guī)則集位于連續(xù)的內(nèi)存空間,iptables 使用全量替換的方式來更新規(guī)則,這使得我們能夠從用戶空間以原子操作來添加/刪除規(guī)則,但非增量式的規(guī)則更新會(huì)在規(guī)則數(shù)量級(jí)較大時(shí)帶來嚴(yán)重的性能問題:假如在一個(gè)大規(guī)模 Kubernetes 集群中使用 iptables 方式實(shí)現(xiàn) Service,當(dāng) service 數(shù)量較多時(shí),哪怕更新一個(gè) service 也會(huì)整體修改 iptables 規(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 通過特定 netfilter hook 調(diào)用的規(guī)則集,此外還可以自定義規(guī)則集,然后從 hook 規(guī)則集中跳轉(zhuǎn)過去。

        • 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)用過程流程,chain 和 rule 按如下示意圖執(zhí)行:

        iptables-chains

        對(duì)于 iptables 具體的用法和指令本文不做詳細(xì)介紹。

        conntrack

        僅僅通過 3、4 層的首部信息對(duì)數(shù)據(jù)包進(jìn)行過濾是不夠的,有時(shí)候還需要進(jìn)一步考慮連接的狀態(tài)。netfilter 通過另一內(nèi)置模塊 conntrack 進(jìn)行連接跟蹤(connection tracking),以提供根據(jù)連接過濾、地址轉(zhuǎn)換(NAT)等更進(jìn)階的網(wǎng)絡(luò)過濾功能。由于需要對(duì)連接狀態(tài)進(jìn)行判斷,conntrack 在整體機(jī)制相同的基礎(chǔ)上,又針對(duì)協(xié)議特點(diǎn)有單獨(dú)的實(shí)現(xiàn)。

        推薦閱讀

        iptables 防火墻(三)- 規(guī)則的導(dǎo)出 / 導(dǎo)入、使用防火墻腳本程序 |(附體系思維導(dǎo)圖)


        iptables 防火墻(二)- SNAT / DNAT 策略及應(yīng)用 |(附體系思維導(dǎo)圖)


        iptables 防火墻(一)- 四表/五鏈、數(shù)據(jù)包匹配流程、編寫 iptables 規(guī)則


        防火墻知識(shí)點(diǎn)梳理


        只需一條命令,就可以查出哪些端口被防火墻阻止了!


        通俗易懂解說計(jì)算機(jī)“防火墻”!


        什么是防火墻?

        瀏覽 69
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            中文字幕丰满乱孑伦无码专区 | 国产呦萝稀缺另类资源 | 一级性生活视频 | 国产91福利在线 | 公的淫之手日剧 | 电车痴汉系列h文 | 少妇寂寞小伙满足少妇在线观看 | 婷婷丁香五月天色 | 久久久久久久高潮 | 亚洲色图第三页 |