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 之 连接跟踪相关数据结构的更多相关文章

  1. Netfilter之连接跟踪实现机制初步分析

    Netfilter之连接跟踪实现机制初步分析 原文: http://blog.chinaunix.net/uid-22227409-id-2656910.html 什么是连接跟踪 连接跟踪(CONNT ...

  2. Netfilter 之 连接跟踪钩子函数分析

    ipv4_conntrack_defrag ipv4_conntrack_defrag对输入包进行检查,如果是分片包,则调用nf_ct_ipv4_gather_frags函数进行重组: static ...

  3. Netfilter 之 连接跟踪初始化

    基础参数初始化 nf_conntrack_init_start函数完成连接跟踪基础参数的初始化,包括了hash,slab,扩展项,GC任务等: int nf_conntrack_init_start( ...

  4. Netfilter 之 连接跟踪的helper

    注册helper nf_conntrack_ftp_init是连接跟踪ftp模块的初始化函数,可以看到其调用了nf_conntrack_helpers_register来注册helper: stati ...

  5. Netfilter&iptables:如何理解连接跟踪机制?

    如何理解Netfilter中的连接跟踪机制? 本篇我打算以一个问句开头,因为在知识探索的道路上只有多问然后充分调动起思考的机器才能让自己走得更远.连接跟踪定义很简单:用来记录和跟踪连接的状态. 问:为 ...

  6. linux内核netfilter连接跟踪的hash算法

    linux内核netfilter连接跟踪的hash算法 linux内核中的netfilter是一款强大的基于状态的防火墙,具有连接跟踪(conntrack)的实现.conntrack是netfilte ...

  7. linux nf_conntrack 连接跟踪机制

    PRE_ROUTING和LOCAL_OUT点可以看作是整个netfilter的入口,而POST_ROUTING和LOCAL_IN可以看作是其出口; 报文到本地:PRE_ROUTING----LOCAL ...

  8. [转]nf_conntrack: table full, dropping packet 连接跟踪表已满,开始丢包 的解决办法

      nf_conntrack: table full, dropping packet  连接跟踪表已满,开始丢包 的解决办法 中午业务说机器不能登录,我通过USM管理界面登录单板的时候发现机器没有僵 ...

  9. linux nf_conntrack 连接跟踪机制 3-hook

    conntrack hook函数分析 enum nf_ip_hook_priorities { NF_IP_PRI_FIRST = INT_MIN, NF_IP_PRI_CONNTRACK_DEFRA ...

随机推荐

  1. 6. Java基本数据类型

    Java 基本数据类型 变量就是申请内存来存储值.也就是说,当创建变量的时候,需要在内存中申请空间. 内存管理系统根据变量的类型为变量分配存储空间,分配的空间只能用来储存该类型数据. 因此,通过定义不 ...

  2. Swagger学习(二、配置swagger)

    基于上一篇 其实只是在SwaggerConfig.class中配置docket,apiInfo @Configuration //变成配置文件 @EnableSwagger2 //开启swagger2 ...

  3. Pytorch中的自编码(autoencoder)

    Pytorch中的自编码(autoencoder) 本文资料来源:https://www.bilibili.com/video/av15997678/?p=25 什么是自编码 先压缩原数据.提取出最有 ...

  4. linux 操作系统安装

    操作系统安装 安装虚拟机软件:一路Next即可 VMWare:如果14版本不支持你的CPU,就换成12版本 Virtual Box:比VMWare小很多 安装ubuntu操作系统:比较美观,实用性强 ...

  5. vue路径中的#号

    最近学习vue过程中,发现路径当中总是存在一个#号,比如这个: 这种情况是因为在入口js文件中,如果你不更改设置的话,vue会默认使用hash模式,该模式下回将路径格式化为 # 开头. 如果需要美化路 ...

  6. 说说css hack,说真的,我也是才去了解这个东西

    之前在很多地方看到css hack,今天狠下心,看看到底是什么鬼,所有我去百度了,然后看了一篇文章,然后写个小总结. css hack就是通过加一些特定的符号,不同的浏览器可以识别特定符号的样式,以此 ...

  7. C++ STL 之 string

    #include <iostream> #include <string> using namespace std; // 初始化 void test01() { string ...

  8. 每日命令:(7)mv

    mv命令是move的缩写,可以用来移动文件或者将文件改名(move (rename) files),是Linux系统下常用的命令,经常用来备份文件或者目录. 1.命令格式: mv [选项] 源文件或目 ...

  9. Django_03_后台管理

    后台管理 站点分为内容发布和公共访问两部分 内容发布的部分由网站的管理员负责查看.添加.修改.删除数据,开发这些重复的功能是一件单调乏味.缺乏创造力的工作,为此,Django能够根据定义的模型类自动地 ...

  10. Python怎么检验数据的正态分布

    在对数据建模前,很多时候我们需要对数据做正态性检验,进而通过检验结果确定下一步的分析方案.下面介绍 Python 中常用的几种正态性检验方法: scipy.stats.kstest kstest 是一 ...