基础知识
table分不同的族(family):每个 table 都会从属于某个族,族决定了该 table 会处理哪些种类的数据包。族包括 ip、 ip6、 inet、 arp、 bridge 和 netdev。
- 属于 ip 族的 table 只负责处理 IPv4 数据包;
- 属于 ip6 族的 table 只负责处理 IPv6 数据包;
- 属于 inet 族的 table 则既可处理 IPv4 又可处理 IPv6 数据包。
创建base chain
创建chain的基本方式在笔者之前的博客”nf_tables入门2“中已经讲过了:
但是注意这里创建的仅仅是一个辅助用的普通chain,如果我们传入了HOOK参数,就是要创建一个base chain,这里会有好多问题,让我们逐一进行分析。
首先我们需要添加参数:
这样我们走到nf_tables_addchain
函数是就会走入第一个if中,在这里创建的是一个base_chain:https://elixir.bootlin.com/linux/v5.15/source/net/netfilter/nf_tables_api.c#L2084
可以看到首先会进入到nft_chain_parsee_hook
函数中对hook进行分析:https://elixir.bootlin.com/linux/v5.15/source/net/netfilter/nf_tables_api.c#L1924 ,首先拆解nested_attr,然后大端序获取hook_num和hook_priority:
之后就是根据当前的family和default的type来获取type结构体:
https://elixir.bootlin.com/linux/v5.15/source/net/netfilter/nf_tables_api.c#L614
但是经过调试,笔者发现这个type数组是空的:😱
之后
初始化chain_type
首先就近在nf_tables_api.c文件中找关于chain_type数组初始化的代码:
https://elixir.bootlin.com/linux/v5.15/source/net/netfilter/nf_tables_api.c#L1329
然后回溯:
nf_tables_module_init |
结果在gdb中发现找不到nft_chain_filter_netdev_init
这个函数,然后发现需要如下编译配置:
类比地,如果有如下配置