ANN/Li Yu Netfilter
ANN/Li Yu Netfilter
ANN/Li Yu Netfilter
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
<strong>ANN</strong>/<strong>Li</strong> <strong>Yu</strong>
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
<strong>Li</strong>nux 网络协议栈概况<br />
<strong>Netfilter</strong><br />
Iptable<br />
连接跟踪<br />
NAT
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
<strong>Li</strong>nux networking protocol stack overview
Inside <strong>Li</strong>nux <strong>Netfilter</strong>
<strong>Netfilter</strong><br />
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
什么是 netfilter ?<br />
<strong>Netfilter</strong> 如何工作?<br />
Iptable, netfilter, 连接跟踪及 NAT.<br />
Play source code.
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
什么是 netfilter?<br />
只是在 <strong>Li</strong>nux 协议栈上的各层接合点上的一个 hook 注入机制。举个<br />
例子,当内核检测到接收到的数据包是到达本机的,就会调用内核函数<br />
ip_local_deliver() ,这个函数不会直接处理相应的事务,而是主动给<br />
<strong>Netfilter</strong> 一次执行 hook 的机会。<br />
这个机制简单,但提供了足够的灵活性,我们可以利用它过滤、修<br />
改、抛弃、统计数据包,甚至凭空注入新的数据包。事实上,我们甚至几<br />
乎可以在 <strong>Netfilter</strong> 上实现另一套 <strong>Li</strong>nux 协议栈。
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
<strong>Netfilter</strong> 如何工作?<br />
<strong>Netfilter</strong> 的工作方式非常简单,它的主要功能入口是通过 NF_HOOK<br />
宏,以下是一个例子:<br />
int ip_local_deliver(struct sk_buff *skb)<br />
{<br />
/* 这里省略若干代码 */<br />
return NF_HOOK(PF_INET, NF_INET_LOCAL_IN, skb,<br />
skb->dev, NULL,<br />
ip_local_deliver_finish);<br />
}
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
Iptable, netfilter ,连接跟踪以及 NAT<br />
Iptable, 连接跟踪, NAT 都在用 netfitler 框架提供的 hook 功能实现<br />
的扩展。<br />
内核中的 Iptable 的功能是根据数据包在协议栈上出现的位置,方<br />
向和所管理员指定的配置完成对数据包的匹配和目标操作。防火墙一般在<br />
filter 表内完成,网络地址转换的准备工作在 NAT 表内完成,此外,还有<br />
mangle 表和 security 表。<br />
<strong>Li</strong>nux 的防火墙功能之所以强大,就是因为它不仅仅是一个包过滤<br />
系统,而且网络连接的状态对数据包判定也有所影响,这势必需要在内核<br />
里维护网络连接的状态信息,这个功能就是由 “ 连接跟踪 ” 子系统完成的。<br />
注:这里的连接并不是局限于 TCP / SCTP 这样的有状态协议。<br />
iptable 中的 nat 表完成的只是 NAT 中的准备工作,即计算出了转<br />
换后的地址,具体转换是在 iptable 之外完成的。而且, NAT 功能不仅<br />
依赖于 iptable ,也依赖于 “ 连接跟踪 ” 。
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
It‘s time to play source code !
Iptable<br />
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
基本术语及其数据结构<br />
数据结构的组织<br />
Play source code: (1) 初始化过程<br />
Play source code: (2) 核心处理过程
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
基本术语及其数据结构<br />
规则 → ipt_entry,” 包模式 ” 保存于 ipt_entry 的 ip 成员内;<br />
匹配 → ipt_match<br />
目标 → ipt_target<br />
表 → xt_table 和 xt_table_info<br />
其他 : ipt_replace
数据结构的组织<br />
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
Ipt_replace 和 xt_table_info 的 entries 成员保存的是一个 ipt_entry 数组<br />
” 匹配要求 ” 和 “ 目标处理 ” 保存于 ipt_entry 的 elems 成员内,这又是一个<br />
结构数组。这个数组以 ipt_match 序列开始,之后是 ipt_target 序<br />
列。 Ipt_target 序列以字节 ipt_entry->target_offset 开始。<br />
Ipt_replace 和 xt_table_info 的成员 hook_entry[NF_INET_NUMHOOKS] 保<br />
存的是一系列 entries 的偏移。例如, hook_entry[NF_INET_LOCAL_IN] 保存着<br />
LOCAL_IN 链上需要处理的第一个 iptable 规则的偏移。 Iptables 的核心函数<br />
ipt_do_table() 会从这个偏移上找到的 iptable 规则开始处理。请注意,默认<br />
hooks 表中有许多 hook 其实只是 ipt_do_table() 的包装函数,它们使用不同的<br />
iptable table 调用它。<br />
Ipt_replace 和 xt_table_info 的成员 underflow[NF_INET_NUMHOOKS] 保<br />
存的是也一系列 entries 的偏移。有些 iptable target 可能返回 IPT_RETURN ,<br />
这表明这要求内核返回到上一个处理的规则上,这个回溯关系事实上是一条 “ 链<br />
栈 ” 。而每个 chain 都可以有这样一个链栈, underflow[] 记录的就是这个栈的栈<br />
底偏移。
数据结构的组织<br />
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
图 1 整 “ <strong>Li</strong>nux netfilter 机制分析 ” PDF 。<br />
图 2 整补充图,现场手工绘制,不到场的<br />
看不着喽!
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
Source code is our good friend, huh? So do not let it<br />
live alone!
连接跟踪<br />
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
抽象网络连接状态<br />
重要数据结构<br />
Play source code: tracking and confirm
抽象连接状态<br />
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
NF_CT_ESTABLISHED :数据报属于已经完全建立的连接<br />
NF_CT_RELATED : 数据报属于一个新的连接,但此连接与一个现有连<br />
接相关(预期连接),或者是 ICMP 错误<br />
NF_CT_NEW :数据报属于一个新的连接<br />
NF_CT_IS_REPLY :数据报属于一个连接的回复,不单独使用,两种用<br />
法: ESTABLISHED+IS_REPLY , RELATED+IS_REPLY<br />
这里的状态与 TCP 无一一对应关系
• 抽象连接状态<br />
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
发包方向 TCP 标志位 连接状态 说明<br />
A->B SYN NEW Also apply for<br />
UDP, ICMP<br />
B->A SYN/ACK ESTABLISHED<br />
+IS_REPLY<br />
Also apply for<br />
UDP, ICMP<br />
A->B ACK ESTABLISHED TCP only
重要的数据结构<br />
Inside <strong>Li</strong>nux <strong>Netfilter</strong>
重要的数据结构<br />
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
实际上,连接跟踪中涉及到的数据结构很多,画<br />
图太累了,还是用代码说明数据结构最直接,再说我<br />
也挺 LAN 的 ~
Play source code<br />
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
Defragment IP datagram first if need.<br />
Tracking a connection operation.<br />
Confirm a connection if need.
NAT<br />
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
NAT 的概念过程<br />
<strong>Li</strong>nux 如何实现 NAT<br />
重要数据结构<br />
Play source code
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
NAT 的概念过程<br />
SNAT 中的 S ,和 DNAT 中的 D 是什么意思,地球人都知<br />
道。<br />
可是实现 SNAT 还需要转换 D 地址,同理, DNAT 的实<br />
现也得转换 S 地址,为什么呢?<br />
实现 NAT 功能需要完整的 IP 数据报。<br />
实现 NAT 功能需要连接跟踪功能。<br />
SNAT , DNAT 典型场景。
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
<strong>Li</strong>nux 如何实现 NAT<br />
连接跟踪即已经要求 IP 分片重组了。<br />
Iptable 的 Nat 表内保存了 NAT 规则。<br />
使用连接跟踪状态表保存地址转换关系。
重要数据结构<br />
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
前面都已经提到过了。<br />
懒惰,是一种美德,所以,请参考之前的图片。
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
Source code is alive, they need your understanding.
Inside <strong>Li</strong>nux <strong>Netfilter</strong><br />
●GAME OVER