大佬教程收集整理的这篇文章主要介绍了Linux Netfilter框架分析,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
netfilter是Linux底层包处理框架,在协议栈中提供了若干hook点,可以用于对数据包进行过滤、修改、地址转换(SNAT/DNAT)等处理。
netfilter在内核协议栈的不同位置实现了5个hook点:
---> PRE_RoutING ---> [RoutIng Decision] ---> FORWARD ---> [RoutIng Decision] ---> POST_RoutING --->
| ^
| |
v |
LOCAL_IN LOCAL_OUT
| ^
| |
v |
LOCAL PROCESS
NF_IP_PRE_RoutING
:数据包一进入协议栈即触发,在进行任何路由判断之前NF_IP_LOCAL_IN
:经过路由判断,如果数据包目的是本机,将触发该hookNF_IP_FORWARD
:经过路由判断,如果数据包目的是其他主机,将触发该hook转发NF_IP_LOCAL_OUT
:本机准备发送的数据包,在进入协议栈后触发该hookNF_IP_POST_RoutING
:准备发出去的包或转发的包,经过路由判断后,离开网卡前的最后一个hook点// include/uapi/linux/netfilter_ipv4.h
/* IP Hooks */
/* After promisc drops, checksum checks. */
#define NF_IP_PRE_RoutING 0
/* If the packet is desTined for this box. */
#define NF_IP_LOCAL_IN 1
/* If the packet is desTined for another interface. */
#define NF_IP_FORWARD 2
/* Packets coming from a local process. */
#define NF_IP_LOCAL_OUT 3
/* Packets about to hit the wire. */
#define NF_IP_POST_RoutING 4
#define NF_IP_NUMHOOKS 5
ip_tables等内核模块可以通过向这5个hook点注册处理函数(handler),当数据包经过hook点时,调用回调函数handler对数据包进行处理。
Wikipedia上关于netfilter在协议栈中的架构图 @H_772_85@
conntrack
是netfilter
实现的连接跟踪机制,是NAT
和iptables
状态匹配(-m state
)的基础,conntrack依赖的内核模块为nf_conntrack
。conntrack
在内核中的位置有两处:PRERoutING
和OUTPUT
之前,进入主机的所有数据包会通过PRERoutING处的conntrack,主机本地进程产生的数据包对外发出时会通过OUTPUT处的conntrack。从netfilter协议栈架构图可以看出,conntrack所处的位置非常靠前,仅位于raw表之后,如果raw将数据包标记为NOTRACK
,则conntrack不会跟踪该数据包连接。conntrack
通过连接跟踪表来维护所有的连接信息,当有数据包通过conntrack
时,通过判断该连接为一条新建的连接,还是已有连接的响应信息,对于新建连接在跟踪表中新建一条连接条目,对于已有连接信息则更新跟踪表中对于连接的状态。数据包经过conntrack时,conntrack会提取相关信息来唯一标识一条连接,对于TCP/UDP协议,一条连接信息通过源IP、源端口、目的IP、目的端口确定,对于ICMP协议,由type、code、id字段确定。
在用户态可以使用命令conntrack -L
来查看系统上的连接跟踪表:
ipv4 2 tcp 6 33 SYN_SENT src=172.16.200.119 dst=172.16.202.12 sport=54786 dport=10051 [UNREPLIED] src=172.16.202.12 dst=172.16.200.119 sport=10051 dport=54786 mark=0 zone=0 use=2
如上是一条conntrack条目,它代表当前已跟踪到的某个连接,conntrack维护的所有信息都包含在这个条目中,通过它就可以知道某个连接处于什么状态
sysctl -a |grep conntrack | grep timeout
查看不同协议不同状态下生存时间设置值,当然这些设置值都可以调整,注意若后续有收到属于此连接的数据包,则此生存时间将被重置(重新从设置值开始倒计时),并且状态改变,生存时间设置值也会响应改为新状态的值连接跟踪表能够存放的conntrack条目的最大值,即系统运行的最大连接跟踪数记作CONNTRACK_MAX
在内核中,连接跟踪表示一个二维数组结构的哈希表,哈希表的大小记作HASHSIZE
,哈希表的每一项称为bucket
,因此哈希表中有HASHSIZE
个bucket
,每个bucket包含一个链表,每个链表能够存放若干个conntrack条目(bucket size
)。
因此,系统允许的最大连接跟踪数为:
CONNTRACK_MAX
= HASHSIZE
* bucket size
#查看系统当前最大连接跟踪数CONNTRACK_MAX
sysctl -a | grep net.netfilter.nf_conntrack_max
#net.netfilter.nf_conntrack_max = 3203072
#查看当前连接跟踪表大小HASHSIZE
sysctl -a | grep net.netfilter.nf_conntrack_buckets
#400384
#或者这样
cat /sys/module/nf_conntrack/parameters/hashsize
#400384
这两个的比值即为bucket size
对于新收到的数据包,内核使用如下步骤判断该数据包是否属于已有连接:
bucket size
越大,遍历时间越长在用户态,使用工具conntrack实现对连接跟踪表的增删改查操作
#查看连接跟踪表所有条目
conntrack -L
#清除连接跟踪表
conntrack -F
#删除连接跟踪表中所有源地址是1.2.3.4的条目
conntrack -D -s 1.2.3.4
iptables是Linux系统上的主机防火墙,依赖于netfilter框架实现,在内核态通过ip_tables内核模块与netfilter交互。 iptables由table和chain组成,以前是四表五链,新增后已经不止四表了。可以说table是chain的集合,chain是iptables规则的集合。
iptables规则通过table来组织,根据需要做的操作分为Filter Table、NAT Table、Mangle Table、Raw Table、Security Table等。
Filter Table
:过滤功能,判断一个数据包是否应该放行NAT Table
:地址转换Raw Table
:决定数据包是否被连接跟踪机制处理,对于不需要跟踪的数据包可以打上NOTRACK
标签Security Table
:标记SELinux在每个table内,规则进一步组织成chain,5个chain与netfilter的5个hook点一一对应:
PRERoutING
: 由NF_IP_PRE_RoutING
触发INPUT
: 由NF_IP_LOCAL_IN
触发FORWARD
: 由NF_IP_FORWARD
触发OUTPUT
: 由NF_IP_LOCAL_OUT
触发POSTRoutING
: 由NF_IP_POST_RoutING
触发chain的优先级:
PRERoutING
->INPUT
PRERoutING
->FORWARD
->POSTRoutING
OUTPUT
->POSTRoutING
以上说明了iptables有哪些table和哪些chain,接下来讨论两个问题:
table/chain | PRERoutING | INPUT | FORWARD | OUTPUT | POSTRoutING |
---|---|---|---|---|---|
[routIng decision] | Y | ||||
raw | Y | Y | |||
连接跟踪 | Y | Y | |||
Y | Y | Y | Y | Y | |
nat(DNAT) | Y | Y | |||
[routIng decision] | Y | Y | |||
filter | Y | Y | Y | ||
security | Y | Y | Y | ||
nat(SNAT) | Y | Y |
conntrack可以跟踪数据包的状态,iptables使用-m state
进行状态匹配正是使用了conntrack连接跟踪表中标记的状态。
数据包内核态状态比较多,映射到用户空间有5种状态:
NEW
:新到达的包为合法包并且在连接跟踪表中关联不到,则为这个包创建一条新连接条目ESTABLISHED
:接收到的包为已有连接的响应包,则将NEW状态改为ESTABLISHED状态。对于TCP连接来说,就是跟SYN包对应的SYN/ACK包,对于UDP、ICMP来说就是与源相反的包RELATED
:接收到的包不属于已有连接,但是和已有连接存在一定的关系,称为辅助连接,例如 FTP 数据传输连接,或者是其他协议试图建立连接时的 ICMP 应答包INVALID
:包无法识别等原因,标记为非法UNTRACKED
:raw表中标记为NOTRACKhttps://opengers.github.io/openstack/openstack-base-netfilter-framework-overview/#conntrack条目 http://arthurchiao.art/blog/conntrack-design-and-implementation-zh/#5-个-hook-点 https://arthurchiao.art/blog/deep-dive-into-iptables-and-netfilter-arch-zh/#chain-遍历优先级
eBPF开发: https://duo.com/labs/tech-notes/wriTing-an-xdp-network-filter-with-ebpf https://github.com/cloudFlare/cloudFlare-blog/blob/master/2018-07-dropping-packets/xdp-drop-ebpf.c https://gist.github.com/fntlnz/f6638d59e0e39f0993219684d9bf57d3 https://davidlovezoe.club/wordpress/archives/937
以上是大佬教程为你收集整理的Linux Netfilter框架分析全部内容,希望文章能够帮你解决Linux Netfilter框架分析所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。