Netfilter中规则(rule)的组织框架

本文深入解析Linux内核Netfilter框架的架构设计,包括大蓝图、table表定义与管理、rule在内核中的存储方式等内容。重点介绍了table和rule的数据结构、match与target的工作原理以及它们在内核中的注册流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、大蓝图

table->chain->rule(match:target)

从上图所示,在内核空间,每个CPU上维护了一份rule的拷贝。这样做是为了减少锁的使用及增加硬件L1 cache的命中次数,以空间换时间

2table(表)

include/linux/netfilter/x_table.h

struct xt_table

{

    struct list_head list;

    unsigned int valid_hooks; /*该表中有效的hook点位图*/

    struct xt_table_info *private; //指向真正存储rule的结构体

    struct module *me;

    u_int8_t af; /* address/protocol family */

    const char name[XT_TABLE_MAXNAMELEN];//表名字

};

 

struct xt_table_info

{

    unsigned int size; //表的大小

    unsigned int number; //表中存的rule个数

    unsigned int initial_entries;//初始化表时创建的默认rule个数
  
//各个hook(chain)在表中的偏移量

    unsigned int hook_entry[NF_INET_NUMHOOKS]; 
    //各个hook(chain)中默认规则在表中的偏移量

    unsigned int underflow[NF_INET_NUMHOOKS];
    //数组,存储各个cpu上自己rule拷贝的内存首地址

    void *entries[1]; 

};

 

表的注册:

每个网络命名空间管理自己Netfilter中创建的table。并把这些表链接到相应的协议族链表里。

这样就可以通过用户空间传下来的表名查找到相应的表了。

struct net

{

struct netns_xt xt;

}

 

struct netns_xt 

{

    struct list_head tables[NFPROTO_NUMPROTO];

    #if defined(CONFIG_BRIDGE_NF_EBTABLES) || \

    defined(CONFIG_BRIDGE_NF_EBTABLES_MODULE)

    struct ebt_table *broute_table;

    struct ebt_table *frame_filter;

    struct ebt_table *frame_nat;

    #endif

};

struct xt_table *xt_register_table(struct net *net,

   const struct xt_table *input_table,

   struct xt_table_info *bootstrap,

   struct xt_table_info *newinfo)

{

    int ret;

    struct xt_table_info *private;

    struct xt_table *t, *table;

 

    /*申请x_table内存*/

    table = kmemdup(input_table, sizeof(struct xt_table), GFP_KERNEL);

    if (!table) {

        ret = -ENOMEM;

        goto out;

    }

 

    ret = mutex_lock_interruptible(&xt[table->af].mutex);

    if (ret != 0)

        goto out_free;

 

    /* 在命名空间里查找是否有相同名字的表 */

    list_for_each_entry(t, &net->xt.tables[table->af], list) {

        if (strcmp(t->name, table->name) == 0) {

            ret = -EEXIST;

            goto unlock;

        }

    }

 

    /* 初始化table_private*/

    table->private = bootstrap;

    if (!xt_replace_table(table, 0, newinfo, &ret))

        goto unlock;

    private = table->private;

    /* save number of initial entries */

    private->initial_entries = private->number;

     //把表挂到对应网络命名空间管理的链表上

    list_add(&table->list, &net->xt.tables[table->af]);

    mutex_unlock(&xt[table->af].mutex);

    return table;

 
unlock:

    mutex_unlock(&xt[table->af].mutex);

    out_free:

    kfree(table);

out:

    return ERR_PTR(ret);

}


3rule在内核中的定义和存储

不同的协议族定义的rule不同。为了通用,netfilter把各个协议族的一些共性的数据结构提取出来单独定义,各个协议族再自己定义自己独有的数据结构,并包含netfilter提供的通用数据结构。

 

我们以IPv4为例来看一下,通过用户空间的iptables所配置到内核中的每条rule是怎么存储的。

如图,ip_entry 是标准的匹配规则,ipt_entry_match是扩展的匹配规则,是可选项。每个rule最后带一个targetTraget有系统自带的,也有扩展的。

 

1、标准的匹配规则

struct ipt_entry

{

    struct ipt_ip ip; //五元组,ipv4报文通用的匹配元素

    /* Mark with fields that we care about. */

    unsigned int nfcache;

/*详见上图,rule首地址到target的偏移量*/

    /* Size of ipt_entry + matches */

    u_int16_t target_offset; 

    /* Size of ipt_entry + matches + target */
    /*下一条rule的偏移量*/

    u_int16_t next_offset;

 

    /* Back pointer */

    unsigned int comefrom;
    /*命中报文的统计计数*/

    /* Packet and byte counters. */

    struct xt_counters counters;

 

    /* The matches (if any), then the target. */

    unsigned char elems[0];

};

 

ipv4报文通用的匹配元素,源/目的ip地址/掩码,源/目的接口名/接口名掩码,传输层协议类型

struct ipt_ip 

{

    /* Source and destination IP addr */

    struct in_addr src, dst;

    /* Mask for src and dest IP addr */

    struct in_addr smsk, dmsk;

    char iniface[IFNAMSIZ], outiface[IFNAMSIZ];

    unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];

    /* Protocol, 0 = ANY */

    u_int16_t proto;

 

    /* Flags word */

    u_int8_t flags;

    /* Inverse flags */
    //位图,每一位代表以上匹配元素配置时是否是带!符号(取反)

    u_int8_t invflags;

};

4. 扩展的Macth

#define ipt_entry_match xt_entry_match

netfilter定义了一个通用的match数据结构struct xt_match

struct xt_match

{

    struct list_head list;
    //match名字,和iptables配置的-m参数相同

    const char name[XT_FUNCTION_MAXNAMELEN-1];

    u_int8_t revision;

    //规则匹配函数

    bool (*match)(const struct sk_buff *skb,

              const struct xt_match_param *);

 

    /* 匹配函数入参检查函数 */

    bool (*checkentry)(const struct xt_mtchk_param *);

 

    /* Called when entry of this type deleted. */

    void (*destroy)(const struct xt_mtdtor_param *);
    。。。。。。

    const char *table;
    //match的自定义数据长度

    unsigned int matchsize;

    unsigned int compatsize;

    unsigned int hooks;

    unsigned short proto;

    unsigned short family;

};

 

每个struct xt_match代表一个扩展matchnetfilter中各个扩展match自己定义自己的匹配参数数据结构,自己实现匹配函数。

 

netfilter中,每个扩展match 被注册到全局变量xt管理的match链表上,可根据match的名字来找到相应的struct xt_match

 

用户使用-m 来配置的扩展match下发给内核,在内核中以struct xt_entry_match数据结构来存储,该结构后紧跟着存储着扩展match自定义的匹配参数数据。

 

Match的基本处理流程

1、取到rule中存储的xt_entry_match,这里记录着iptables下发给内核的值,同时找到内核中注册的xt_match,从xt_match里找到相应的match函数.

2、根据xt_entry_match中记录的配置值初始化xt_match_param,

3、把报文和xt_match_param传给match函数进行匹配处理。

 

 

注册match

Int xt_register_match(struct xt_match *match)

{

    u_int8_t af = match->family;

    int ret;

    ret = mutex_lock_interruptible(&xt[af].mutex);

    if (ret != 0)

    return ret;

    list_add(&match->list, &xt[af].match);//加入Netfilter管理的全局Match链表上

    mutex_unlock(&xt[af].mutex);

 

    return ret;

}


5. Target

Netfilter中对扩展target 和扩展match的管理非常相似


target分扩展target和标准target

#define ipt_entry_target xt_entry_target

 

标准target

#define ipt_standard_target  xt_standard_target

struct xt_standard_target

{

    struct xt_entry_target target;

//verdict 可以是指定返回值,也可以是goto到下一个rule的偏移量,

也可以是queue的队列号。

    int verdict;

};

 

如果struct xt_entry->target 值为空,表示是标准target,根据verdict值来处理报文。

 

如果struct xt_entry->target不为空,表示不是标准target,就使用targettarget函数返回值来处理报文。

 

调用函数xt_register_target()来注册扩展target
### Linux 中 TC 框架Netfilter 框架的比较 #### 区别 Netfilter 和 Traffic Control (TC) 是 Linux 网络子系统的两个重要组成部分,各自负责不同的网络处理任务。 - **功能定位** - Netfilter 主要用于包过滤和地址转换等功能。它允许内核模块在数据包通过网络堆栈的不同位置进行操作,支持防火墙、NAT(Network Address Translation)、IPSec 等安全特性[^1]。 - TC 则专注于流量整形和带宽管理,在发送方向上控制数据流的速度以及优先级调度策略,确保不同类型的业务能够获得合理的资源分配[^2]。 - **工作阶段** - Netfilter 处理的是进入或离开主机的数据报文,在 OSI 参考模型中的第三层(网络层)到第七层(应用层)之间运作;而 TC 更多关注于第二层之后至传输层之前的部分,即链路层以上的部分,并且主要作用是在输出路径上的队列管理和速率限制等方面发挥作用。 - **配置工具** - 对应这两个框架有不同的命令行工具来进行设置:`iptables`, `nftables` 常被用来定制 netfilter 的行为模式;对于 tc,则有专门设计好的 iproute2 工具集下的 `tc` 命令来完成相应参数调整。 #### 联系 尽管两者有着明显的分工差异,但在实际部署过程中往往相辅相成: - 当需要对特定应用程序产生的流量实施精确调控时,可以先利用 netfilter 定义匹配条件筛选目标连接对象,再交由 tc 执行具体的 QoS (Quality of Service,服务质量)措施; - 同样地,在某些复杂环境中可能既存在对外部访问权限的安全管控需求又涉及到内部服务间通信效率优化的要求——此时便可以通过组合运用这两种技术手段达到理想效果。 #### 应用场景 根据不同侧重点,两种机制适用于不同类型的应用场合: - **Netfilter 场景** - 实现企业级网络安全防护体系,如入侵检测系统IDS(Intrusion Detection System),防止恶意攻击者未经授权获取敏感资料; - 构建虚拟专用网(VPN,Virtural Private Network),使得远程工作者能安全接入公司内部网络环境; - 提供负载均衡解决方案,提高服务器集群的整体性能表现并增强可用性和可靠性。 - **TC 场景** - 面向 ISP(Internet Service Provider)/运营商提供差异化服务水平协议SLA(Service Level Agreement),保障高价值客户享有更优质的互联网体验; - 支持多媒体实时交互类应用例如 VoIP/VoLTE(voice over IP/Long Term Evolution)通话质量不受拥塞影响保持清晰流畅; - 协助大型数据中心有效规划计算节点间的通讯带宽配额,促进资源共享最大化的同时减少延迟现象发生概率。 ```bash # 示例:使用 iptables 设置简单的入站规则 sudo iptables -A INPUT -p tcp --dport ssh -j ACCEPT # 示例:创建 HTB 类型的 qdisc 并为其根节点指定默认 classid sudo tc qdisc add dev eth0 root handle 1: htb default 10 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值