Netfilter 之 连接跟踪相关数据结构
Netfilter通过连接跟踪来记录和跟踪连接的状态,为状态防火墙和NAT提供基础支持;
钩子点与钩子函数
下图为钩子点和钩子函数的关系图(点击图片查看原图),其中ipv4_conntrack_defrag、ipv4_conntrack_in、ipv4_helper、ipv4_confirm为连接跟踪相关的钩子函数,其作用的钩子点为PRE_ROUTING、LOCAL_IN、LOCAL_OUT、POST_ROUTING:
钩子函数的调用流程
通过上图,可以得到连接跟踪的流程:
输入本地:
ipv4_conntrack_defrag–>ipv4_conntrack_in–>ipv4_helper–>ipv4_confirm
【<————-PRE_ROUTING————>】 【<—— LOCAL_IN——>】
转发:
ipv4_conntrack_defrag–>ipv4_conntrack_in–>ipv4_helper–>ipv4_confirm
【<————-PRE_ROUTING————>】 【<—— LOCAL_IN——>】
本地输出:
ipv4_conntrack_defrag–>ipv4_conntrack_local–>ipv4_helper–>ipv4_confirm
【<————–LOCAL_OUT—————–>】 【<—-POST_ROUTING—>】
连接跟踪的状态
ip_conntrack_info用来描述连接跟踪的状态,如下:
enum ip_conntrack_info {
/* Part of an established connection (either direction). */
/* 已建立连接的一部分(任一方向) */
IP_CT_ESTABLISHED, /* Like NEW, but related to an existing connection, or ICMP error
(in either direction). */
/* 已建立连接的关联连接,或者是ICMP错误(任一方向) */
IP_CT_RELATED, /* Started a new connection to track (only
IP_CT_DIR_ORIGINAL); may be a retransmission. */
/* 开始一个新连接; 可能是重传 */
IP_CT_NEW, /* >= this indicates reply direction */
/* >=这个值的都是响应方向的 */
IP_CT_IS_REPLY, /* 已建立连接的响应 */
IP_CT_ESTABLISHED_REPLY = IP_CT_ESTABLISHED + IP_CT_IS_REPLY,
/* 已建立连接的关联连接的响应 */
IP_CT_RELATED_REPLY = IP_CT_RELATED + IP_CT_IS_REPLY,
/* No NEW in reply direction. */ /* Number of distinct IP_CT types. */
/* IP_CT类型的数量 */
IP_CT_NUMBER, /* only for userspace compatibility */
#ifndef __KERNEL__
IP_CT_NEW_REPLY = IP_CT_NUMBER,
#else
IP_CT_UNTRACKED = ,
#endif
};
数据结构图
本文中涉及的数据结构之间的关系图如下:
源码分析
nf_conn是对连接跟踪抽象的基础结构,其中tuplehash为连接跟踪nf_conntrack_tuple的hash,分两个方向;
struct nf_conn {
/* Usage count in here is 1 for hash table, 1 per skb,
* plus 1 for any connection(s) we are `master' for
*
* Hint, SKB address this struct and refcnt via skb->_nfct and
* helpers nf_conntrack_get() and nf_conntrack_put().
* Helper nf_ct_put() equals nf_conntrack_put() by dec refcnt,
* beware nf_ct_get() is different and don't inc refcnt.
*/
/* 连接跟踪的引用计数 */
struct nf_conntrack ct_general; spinlock_t lock;
u16 cpu; #ifdef CONFIG_NF_CONNTRACK_ZONES
struct nf_conntrack_zone zone;
#endif
/* XXX should I move this to the tail ? - Y.K */
/* These are my tuples; original and reply */
/* 连接跟踪两个方向的tuple节点,即五元组 */
struct nf_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX]; /* Have we seen traffic both ways yet? (bitset) */
/* 状态 */
unsigned long status; /* jiffies32 when this ct is considered dead */
/* 连接跟踪的超时时间 */
u32 timeout; /* 命名空间 */
possible_net_t ct_net; #if IS_ENABLED(CONFIG_NF_NAT)
struct rhlist_head nat_bysource;
#endif
/* all members below initialized via memset */
u8 __nfct_init_offset[]; /* If we were expected by an expectation, this will be it */
/* 如果当前连接是某个连接期望的连接,该字段指向主连接 */
struct nf_conn *master; #if defined(CONFIG_NF_CONNTRACK_MARK)
u_int32_t mark;
#endif #ifdef CONFIG_NF_CONNTRACK_SECMARK
u_int32_t secmark;
#endif /* Extensions */
/* 扩展项 */
struct nf_ct_ext *ext; /* Storage reserved for other modules, must be the last member */
/* 不同协议实现连接跟踪的额外参数 */
union nf_conntrack_proto proto;
};
nf_conntrack_tuple_hash的定义如下:
struct nf_conntrack_tuple_hash {
struct hlist_nulls_node hnnode;
struct nf_conntrack_tuple tuple;
};
nf_ct_ext用于实现对连接跟踪的扩展;
struct nf_ct_ext {
struct rcu_head rcu;
u8 offset[NF_CT_EXT_NUM];
u8 len;
char data[];
};
nf_conntrack_tuple是用来区分一条连接的信息,定义如下:
/* 该结构包含源目的信息用来区分一条连接 */
struct nf_conntrack_tuple {
/* 源,可操作? */
struct nf_conntrack_man src; /* These are the parts of the tuple which are fixed. */
/* 目的,不可操作? */
struct {
union nf_inet_addr u3;
union {
/* Add other protocols here. */
__be16 all; struct {
__be16 port;
} tcp;
struct {
__be16 port;
} udp;
struct {
u_int8_t type, code;
} icmp;
struct {
__be16 port;
} dccp;
struct {
__be16 port;
} sctp;
struct {
__be16 key;
} gre;
} u; /* The protocol. */
/* 协议 */
u_int8_t protonum; /* The direction (for tuplehash) */
/* 方向(tuplehash使用) */
u_int8_t dir;
} dst;
};
上面结构中的源方向信息使用了nf_conntrack_man结构,其中包括了三层识别信息,四层识别信息,以及三层协议号;
/* The manipulable part of the tuple. */
/* tuple可操作的部分? */
struct nf_conntrack_man {
/* 三层识别信息 */
union nf_inet_addr u3;
/* 四层识别信息 */
union nf_conntrack_man_proto u;
/* Layer 3 protocol */
/* 三层协议号 */
u_int16_t l3num;
};
union nf_inet_addr {
__u32 all[];
__be32 ip;
__be32 ip6[];
struct in_addr in;
struct in6_addr in6;
};
/* The protocol-specific manipulable parts of the tuple: always in
* network order
*/
union nf_conntrack_man_proto {
/* Add other protocols here. */
__be16 all; struct {
__be16 port;
} tcp;
struct {
__be16 port;
} udp;
struct {
__be16 id;
} icmp;
struct {
__be16 port;
} dccp;
struct {
__be16 port;
} sctp;
struct {
__be16 key; /* GRE key is 32bit, PPtP only uses 16bit */
} gre;
};
nf_conn中的proto成员用来存储协议特有的用来表示连接跟踪的信息,其联合体nf_conntack_proto定义如下:
/* per conntrack: protocol private data */
union nf_conntrack_proto {
/* insert conntrack proto private data here */
struct nf_ct_dccp dccp;
struct ip_ct_sctp sctp;
struct ip_ct_tcp tcp;
struct nf_ct_gre gre;
unsigned int tmpl_padto;
};
下面是TCP的一些必要信息;
struct ip_ct_tcp {
struct ip_ct_tcp_state seen[]; /* connection parameters per direction */
u_int8_t state; /* state of the connection (enum tcp_conntrack) */
/* For detecting stale connections */
u_int8_t last_dir; /* Direction of the last packet (enum ip_conntrack_dir) */
u_int8_t retrans; /* Number of retransmitted packets */
u_int8_t last_index; /* Index of the last packet */
u_int32_t last_seq; /* Last sequence number seen in dir */
u_int32_t last_ack; /* Last sequence number seen in opposite dir */
u_int32_t last_end; /* Last seq + len */
u_int16_t last_win; /* Last window advertisement seen in dir */
/* For SYN packets while we may be out-of-sync */
u_int8_t last_wscale; /* Last window scaling factor seen */
u_int8_t last_flags; /* Last flags set */
};
struct ip_ct_tcp_state {
u_int32_t td_end; /* max of seq + len */
u_int32_t td_maxend; /* max of ack + max(win, 1) */
u_int32_t td_maxwin; /* max(win) */
u_int32_t td_maxack; /* max of ack */
u_int8_t td_scale; /* window scale factor */
u_int8_t flags; /* per direction options */
};
Netfilter 之 连接跟踪相关数据结构的更多相关文章
- Netfilter之连接跟踪实现机制初步分析
Netfilter之连接跟踪实现机制初步分析 原文: http://blog.chinaunix.net/uid-22227409-id-2656910.html 什么是连接跟踪 连接跟踪(CONNT ...
- Netfilter 之 连接跟踪钩子函数分析
ipv4_conntrack_defrag ipv4_conntrack_defrag对输入包进行检查,如果是分片包,则调用nf_ct_ipv4_gather_frags函数进行重组: static ...
- Netfilter 之 连接跟踪初始化
基础参数初始化 nf_conntrack_init_start函数完成连接跟踪基础参数的初始化,包括了hash,slab,扩展项,GC任务等: int nf_conntrack_init_start( ...
- Netfilter 之 连接跟踪的helper
注册helper nf_conntrack_ftp_init是连接跟踪ftp模块的初始化函数,可以看到其调用了nf_conntrack_helpers_register来注册helper: stati ...
- Netfilter&iptables:如何理解连接跟踪机制?
如何理解Netfilter中的连接跟踪机制? 本篇我打算以一个问句开头,因为在知识探索的道路上只有多问然后充分调动起思考的机器才能让自己走得更远.连接跟踪定义很简单:用来记录和跟踪连接的状态. 问:为 ...
- linux内核netfilter连接跟踪的hash算法
linux内核netfilter连接跟踪的hash算法 linux内核中的netfilter是一款强大的基于状态的防火墙,具有连接跟踪(conntrack)的实现.conntrack是netfilte ...
- linux nf_conntrack 连接跟踪机制
PRE_ROUTING和LOCAL_OUT点可以看作是整个netfilter的入口,而POST_ROUTING和LOCAL_IN可以看作是其出口; 报文到本地:PRE_ROUTING----LOCAL ...
- [转]nf_conntrack: table full, dropping packet 连接跟踪表已满,开始丢包 的解决办法
nf_conntrack: table full, dropping packet 连接跟踪表已满,开始丢包 的解决办法 中午业务说机器不能登录,我通过USM管理界面登录单板的时候发现机器没有僵 ...
- linux nf_conntrack 连接跟踪机制 3-hook
conntrack hook函数分析 enum nf_ip_hook_priorities { NF_IP_PRI_FIRST = INT_MIN, NF_IP_PRI_CONNTRACK_DEFRA ...
随机推荐
- linux文件目录详细介绍
linux文件目录 目录 /bin 存放二进制可执行文件(ls,cat,mkdir等),常用命令一般都在这里 /etc 存放系统管理和配置文件 /home 存放所有用户文件的根目录,是用户主目录的基点 ...
- docker 无法使用vi
更新来源 apt-get update 安装vim apt-get install -y vim
- Django中间件理解
一.中间件 https://www.cnblogs.com/maple-shaw/articles/9333824.html 中间件:是一个类处理django的请求和响应,本质上就是一个类,在类里面定 ...
- 2018 年 IoT 那些事儿
本文作者:murphyzhang.xmy.fen @腾讯安全云鼎实验室 2018年,是 IoT 高速发展的一年,从空调到电灯,从打印机到智能电视,从路由器到监控摄像头统统都开始上网.随着5G网络的 ...
- 变种XSS:持久控制
变种XSS:持久控制 tig3r · 2015/11/30 10:42 0x00 引言 首先声明,这不是一个新洞,看过 Homakov 文章(最后附)以及译文的人想必对这种漏洞有所了解. 但原文写的太 ...
- 本地套接字-本地socket
本地套接字简单应用场景 一 #服务端--简单 import socket import os a='sock_file' if os.path.exists(a): os.remove(a) s=so ...
- 随机模块 random 函数的调用
随机模块 random 作用: 用于模拟或生成随机输出的模块. 用法示意: import random as R 函数名 描述 R.random() 返回一个[0, 1) 之间的随机实数 R.unif ...
- 十七,k8s集群指标API及自定义API
目录 资源指标: Metrics-Server 资源指标: Metric-Server介绍 Metric-Server部署 下载yaml文件 因为有墙, 所以提前下载image镜像, 当然也可以手动修 ...
- 判断一个python字符串中是否包含中文字符
#在python中一个汉字算一个字符,一个英文字母算一个字符 #用 ord() 函数判断单个字符的unicode编码是否大于255即可. def is_contain_chinese(check_st ...
- 用实例的方式去理解storm的并发度
什么是storm的并发度 一个topology(拓扑)在storm集群上最总是以executor和task的形式运行在suppervisor管理的worker节点上.而worker进程都是运行在jvm ...