• linux netfilter rule match target 数据结构


    对于netfilter 可以参考 https://netfilter.org/documentation/HOWTO/netfilter-hacking-HOWTO-3.html

    netfilter 框架中包含了:filter mat mangle raw security;

    在net结构中的成员struct netns_xt xt,是用来存储所有table的,

    netns_xt结构的成员如下,其中tables存储了多种协议对应的table链表,每种协议对应一个链表,多种table存储在自己所属协议的链表上;

    struct netns_xt {
        struct list_head tables[NFPROTO_NUMPROTO];
        bool notrack_deprecated_warning;
        bool clusterip_deprecated_warning;
    #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
    };

    每个具体类型的table如下:

    /* Furniture shopping... */
    struct xt_table {
        struct list_head list;
        /* What hooks you will enter on */
        unsigned int valid_hooks; /* 该表关注的钩子点 */
        /* Man behind the curtain... *//* 私有数据,真正的规则,指向xt_table_info */
        struct xt_table_info *private;
        /* Set this to THIS_MODULE if you are a module, otherwise NULL */
        struct module *me;
        u_int8_t af;        /* address/protocol family */ /* 协议族 */
        int priority;        /* hook order */ /* 优先级 */
        /* called when table is needed in the given netns */
        int (*table_init)(struct net *net);
        /* A unique name... */
        const char name[XT_TABLE_MAXNAMELEN];//表的名字
    };

    xt_table的private成员又指向了xt_table_info结构,存储真正的规则相关信息,包括入口和偏移

    /* The table itself */
    struct xt_table_info {
        /* Size per table */
        unsigned int size;  /* 表大小,占用的内存空间 */
        /* Number of entries: FIXME. --RR */
        unsigned int number;  /* 表中规则数量 */
        /* Initial number of entries. Needed for module usage count */
        unsigned int initial_entries;/* 初始的规则数量,用于模块计数 */
    
        /* Entry points and underflows 
    *   hook_entries:记录所影响的HOOK的规则入口相对于下面的entries变量的偏移量
    *   underflows:与hook_entry相对应的规则表上限偏移量
        */
        
        unsigned int hook_entry[NF_INET_NUMHOOKS];/* 钩子规则入口,相对于下面的entries偏移量 */
        unsigned int underflow[NF_INET_NUMHOOKS];  /* 与hook_entry相对应的规则表上限偏移量,当无规则录入时,hook_entry和underflow均为0 */
        /*
         * Number of user chains. Since tables cannot have loops, at most
         * @stacksize jumps (number of user chains) can possibly be made.
         */
        unsigned int stacksize;
        void ***jumpstack;
      /* 每个cpu的ipt_entry指针,指向ipt_entry的首地址 */
        unsigned char entries[0] __aligned(8);
    };

    xt_table_info结构的entries成员指向了匹配规则的入口,入口的每个数组包含了多个rule;

    Netfilter 中规则是顺序存储的,一条rule规则主要包括三个部

    • ipt_entry:标准匹配结构,主要包含数据包的源、目的IP,出、入接口和掩码等;
    • ipt_entry_match:扩展匹配。一条rule规则可能有零个或多个ipt_entry_match结构;
    • ipt_entry_target:一条rule规则有且仅有一个target动作。就是当所有的标准匹配和扩展匹配都符合之后才来执行该target
        • /*ipt_entry中包含ipt_ip结构,用于标准match,匹配内容为源目的地址,入出口设备,协议等*/
          /* Yes, Virginia, you have to zero the padding. */
          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 */
              __u16 proto;/* 协议号 */
          
              /* Flags word */
              __u8 flags;
              /* Inverse flags */
              __u8 invflags; /* 是否是反转匹配 */
          };
          /* This structure defines each of the firewall rules.  Consists of 3
             parts which are 1) general IP header stuff 2) match specific
             stuff 3) the target to perform if the rule matches */
          struct ipt_entry {
              struct ipt_ip ip;
          
              /* Mark with fields that we care about. */
              unsigned int nfcache;
          
              /* Size of ipt_entry + matches */
              /* target区的偏移,通常target区位于match区之后,而match区则在ipt_entry的末尾;
          初始化为sizeof(struct ipt_entry),即假定没有match */
              __u16 target_offset;
              /* Size of ipt_entry + matches + target */
              /* 下一条规则相对于本规则的偏移,也即本规则所用空间的总和,
          初始化为sizeof(struct ipt_entry)+sizeof(struct ipt_target),即没有match */
          
              __u16 next_offset;
          
              /* Back pointer */
              unsigned int comefrom;
          
              /* Packet and byte counters. *//* 记录该规则处理过的报文数和报文总字节数 */
              struct xt_counters counters;
          
              /* The matches (if any), then the target. *//*target或者是match的起始位置 */
              unsigned char elems[0];
          };
          /*
          ipt_entry_match将内核态与用户态关联起来,按我的理解,内核和用户在注册和维护match时使用的是各自的match结构ipt_match和iptables_match,
          但在具体应用到某个规则时则需要统一成ipt_entry_match结构。
          前面说过,match区存储在ipt_entry的末尾,target在最后,结合ipt_entry_match的定义,可以知道一条具体的规则中存储的数据结构不是:
          ipt_entry + ipt_match1 + ipt_match2 + ipt_match3 + … + target
          而是:
          ipt_entry + ipt_entry_match1 + ipt_entry_match2 + ipt_entry_match3 + … + target
          */
          struct xt_entry_match {
              union {
                  struct {
                      __u16 match_size;
                      /* Used by userspace */
                      char name[XT_EXTENSION_MAXNAMELEN];
                      __u8 revision;
                  } user;
                  struct {
                      __u16 match_size;
                      /* Used inside the kernel */
                      struct xt_match *match;
                  } kernel;
                  /* Total length */
                  __u16 match_size;
              } u;
              unsigned char data[0];
          };
          /*

          在某条规则匹配之后,执行的动作;也分为标准target和扩展target;

          标准target:t->u.kernel.target->target为NULL,则为标准target,根据verdict返回值决定如何进行下一步处理;扩展target:t->u.kernel.target->target不为NULL,则为扩展target,这时候需要执行该target函数

          */
          struct xt_entry_target {
              union {
                  struct {
                      __u16 target_size;
                      /* Used by userspace */
                      char name[XT_EXTENSION_MAXNAMELEN];
                      __u8 revision;
                  } user;
                  struct {
                      __u16 target_size;
                      /* Used inside the kernel */
                      struct xt_target *target;
                  } kernel;
                  /* Total length */
                  __u16 target_size;
              } u;
              unsigned char data[0];
          xt_standard_target对xt_entry_target成员进行了封装,增加了verdict,该字段用于返回处理结果
          struct xt_standard_target {
              struct xt_entry_target target;
              int verdict;
          };
          
          };

          target主要用来处理:当某条规则中的所有match都被数据包匹配后该执行什么样的动作来处理这个报文,最后将处理后结果通过verdict值返回给Netfilter框架

    http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!! 但行好事 莫问前程 --身高体重180的胖子
  • 相关阅读:
    mybatis 错误 Invalid bound statement (not found)
    Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
    bug 记录 Unable to start ServletWebServerApplicationContext due to multiple ServletWebServerFactory beans
    解决:The Tomcat connector configured to listen on port 8182 failed to start. The port may already be in use or the connector may be misconfigured.
    jquery validate 验证插件 解决多个相同的Name 只验证第一个的方案
    phpStorm+xdebug调试(php7.3)
    小程序视频多个视频播放与暂停
    CSS实现单行、多行文本溢出显示省略号(…)
    Packet for query is too large (4,544,730 > 4,194,304). You can change this value on the server by setting the 'max_allowed_packet' variable.
    idea自动在文件头中添加作者和创建时间
  • 原文地址:https://www.cnblogs.com/codestack/p/10850658.html
Copyright © 2020-2023  润新知