netfilter的笔记3--那些内置的表

时间:2022-02-01 10:26:20

通过netfilter的笔记2的例子,我们知道了怎么使用netfilter的框架,对于内核的设计原则来说,策略和机制分离,所以提供了iptables来供用户配置防火墙策略。

那么,怎么使用iptables呢?由于iptables的资料很多,本文将汇集一些,作为自己的学习过程记录。

netfiler内置了一些表,来管理iptables工具下发的规则,规则的保存是这样的:

可以这么说,Netfilter管理多张表,表管理多条链,链管理规则。简单地讲, tables 由 chains 组成,而 chains 又由 rules 组成。 iptables 默认有四个表 Filter, NAT, Mangle, Raw 。

 这里只描述ipv4的,v6的和其他协议的类似,在配置中搜索的话,可以看到其他tables:

[root@Discovery ~]# grep CONFIG_NF_TABLES /boot/config-3.10.0-862.*
/boot/config-3.10.0-862.6.3.el7.x86_64:CONFIG_NF_TABLES=m
/boot/config-3.10.0-862.6.3.el7.x86_64:CONFIG_NF_TABLES_INET=m
/boot/config-3.10.0-862.6.3.el7.x86_64:CONFIG_NF_TABLES_IPV4=m
/boot/config-3.10.0-862.6.3.el7.x86_64:CONFIG_NF_TABLES_ARP=m
/boot/config-3.10.0-862.6.3.el7.x86_64:CONFIG_NF_TABLES_IPV6=m
/boot/config-3.10.0-862.6.3.el7.x86_64:CONFIG_NF_TABLES_BRIDGE=m

需要注意的是,在支持net的命名空间之后,所有的描述都是针对某一个net来说的。

描述table的数据结构是:

/* Furniture shopping... */
struct xt_table {
    struct list_head list;

    /* What hooks you will enter on */
    unsigned int valid_hooks;

    /* Man behind the curtain... */
    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 */

    /* A unique name... */
    const char name[XT_TABLE_MAXNAMELEN];
};

 

filter表:定义在iptable_filter文件中,

#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,------------------v4的
    .priority    = NF_IP_PRI_FILTER,
};

 

NAT表,定义在iptable_nat.c文件。

static const struct xt_table nf_nat_ipv4_table = {
    .name        = "nat",
    .valid_hooks    = (1 << NF_INET_PRE_ROUTING) |
              (1 << NF_INET_POST_ROUTING) |
              (1 << NF_INET_LOCAL_OUT) |
              (1 << NF_INET_LOCAL_IN),
    .me        = THIS_MODULE,
    .af        = NFPROTO_IPV4,-------------v4的
};

 

mangle表:定义在iptables_mangle.c文件中。

#define MANGLE_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | \
                (1 << NF_INET_LOCAL_IN) | \ (1 << NF_INET_FORWARD) | \ (1 << NF_INET_LOCAL_OUT) | \ (1 << NF_INET_POST_ROUTING)) static const struct xt_table packet_mangler = { .name = "mangle", .valid_hooks = MANGLE_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_IPV4,-------------针对ipv4的 .priority = NF_IP_PRI_MANGLE, };

 

raw表,定义在iptable_raw.c文件中:

#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT))

static const struct xt_table packet_raw = {
    .name = "raw",
    .valid_hooks =  RAW_VALID_HOOKS,
    .me = THIS_MODULE,
    .af = NFPROTO_IPV4,-----------------v4
    .priority = NF_IP_PRI_RAW,
};

 可以看出,这些表的优先级是不一样的,:

enum nf_ip_hook_priorities {
    NF_IP_PRI_FIRST = INT_MIN,
    NF_IP_PRI_CONNTRACK_DEFRAG = -400,
    NF_IP_PRI_RAW = -300,
    NF_IP_PRI_SELINUX_FIRST = -225,
    NF_IP_PRI_CONNTRACK = -200,
    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,
    NF_IP_PRI_SELINUX_LAST = 225,
    NF_IP_PRI_CONNTRACK_HELPER = 300,
    NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX,
    NF_IP_PRI_LAST = INT_MAX,
};

总体上看,优先级顺序是:raw —> mangle —> nat —> filter。值越小优先级越大,也就是说在某一个链上有多张表,从chain的角度来说,相同的chain决定了hooknum是一样的,然后和pf一起决定了nf_hooks[reg->pf][reg->hooknum]中的位置,所以看出,表只是容器,起作用的还是chain,那么chain中的rule是如何生效的呢?