Netfilter 是如何工作的(六):连接跟踪信息的入口创建(in)和出口确认(confirm)

Articles (gitee.io)

IPtables-朱双印博客 (zsythink.net)

在 Netfilter 是如何工作的(五) 中连接跟踪信息使用的创建-确认机制的

Netfilter在报文进入系统的入口处,将连接跟踪信息记录在报文上,在出口进行confirm.确认后的连接信息

本文以一个本机上送过程中的TCP/IPv4SYN握手报文为例,详细分析连接跟踪机制的工作流程。

入口 & 出口

由于是本机上送流程,因此SYN报文的入口是 PRE_ROUTING,而出口则是 LOCAL_IN。Netfilter 在初始化时,会在这两个 HOOK 点注册连接跟踪相关的处理函数。

static struct nf_hook_ops ipv4_conntrack_ops[] = {{.hook		= ipv4_conntrack_in,           // 入口回调函数.pf		    = NFPROTO_IPV4,.hooknum	= NF_INET_PRE_ROUTING,         //  PRE_ROUTING HOOK 点.priority	= NF_IP_PRI_CONNTRACK,         //  优先级},......{.hook		= ipv4_confirm,                // 出口的回调函数.pf		    = NFPROTO_IPV4,.hooknum	= NF_INET_LOCAL_IN,            // LOCAL_IN HOOK 点 .priority	= NF_IP_PRI_CONNTRACK_CONFIRM, // 优先级},
}
入口

SYN 报文进入连接跟踪的入口是 ipv4_conntrack_in(),然后调用nf_conntrack_in, 后面这个函数较长,因此我们这里分段来看

ipv4_conntrack_in||-- nf_conntrack_innf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, struct sk_buff *skb)
{// ......if (skb->nfct) {/* Previously seen (loopback or untracked)?  Ignore. */tmpl = (struct nf_conn *)skb->nfct;if (!nf_ct_is_template(tmpl)) {NF_CT_STAT_INC_ATOMIC(net, ignore);return NF_ACCEPT;}skb->nfct = NULL;}// ......
}

首先是检查 skb 上是否已经关联了连接跟踪信息。这里不是入口吗?为什么 skb 上会由连接跟踪信息 ?! 注释写了,如果这个包是从 loopback 口收到的话,这时它就有可能已经关联的链接跟踪信息了,这时就会把已关联的连接跟踪信息作为模板(tmpl)。而在我们的情境中,SYN 报文从外部网卡收到,所以显然这里 skb 是不会有连接跟踪信息的。

接着往下看:

	l3proto = __nf_ct_l3proto_find(pf);ret = l3proto->get_l4proto(skb, skb_network_offset(skb),&dataoff, &protonum);l4proto = __nf_ct_l4proto_find(pf, protonum);                  

这一段代码片段完成了两件事

  • 将协议族 pf 转换得到 L3 协议对应的函数操作集(operations),在我们的例子中,入参pf = AF_INET,也就是 IP 协议,因此这里会得到l3proto = nf_conntrack_l3proto_ipv4
  • 进一步解析报文 L4 对应的协议号,这里会调用ipv4_get_l4proto,在我们的例子中,会得到 TCP 对应的协议号,protonum = 6,进而得到l4proto = nf_conntrack_l4proto_tcp4

接下来就是入口函数的核心流程resolve_normal_ct(), 正常情况下,这个函数会返回连接跟踪信息的指针ct和简要信息ctinfo,并将它们分别设置到skb->nfcfskb->ctinfo

    struct nf_conn *ct;enum ip_conntrack_info ctinfo;int set_reply = 0;ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum,l3proto, l4proto, &set_reply, &ctinfo);

下面将 resolve_normal_ct 展开

第一步调用nf_ct_get_tuple, 将报文的五元组信息填充到struct nf_conntrack_tuple结构的变量中

static inline struct nf_conn *
resolve_normal_ct(struct net *net, struct nf_conn *tmpl,struct sk_buff *skb,unsigned int dataoff,u_int16_t l3num,u_int8_t protonum,struct nf_conntrack_l3proto *l3proto,struct nf_conntrack_l4proto *l4proto,int *set_reply,enum ip_conntrack_info *ctinfo)
{          const struct nf_conntrack_zone *zone;struct nf_conntrack_tuple tuple;struct nf_conntrack_tuple_hash *h;//  @tuple 是出参, 对tcp来说是 tcp_pkt_to_tuple, 只是填了dport和sportif (!nf_ct_get_tuple(skb, skb_network_offset(skb),dataoff, l3num, protonum, net, &tuple, l3proto,l4proto)) {pr_debug("resolve_normal_ct: Can't get tuple\n");return NULL;}// ...... 
}

第二步,计算tuple的哈希值,然后根据此哈希值查找连接跟踪信息表中是否已存在这个哈希值的记录,将其值赋予h

    ......zone = nf_ct_zone_tmpl(tmpl, skb, &tmp);hash = hash_conntrack_raw(&tuple);                    // 计算hashh = __nf_conntrack_find_get(net, zone, &tuple, hash); // 查找该tuple的元组信息是否已经存在

在我们的例子中,假设原本没有这样的记录,于是这里会使用init_conntrack创建一条新的连接跟踪信息

	if (!h) {h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto,skb, dataoff, hash);

最后,将连接跟踪信息设置到报文skb上。特别注意,这里只会将连接信息保存在skb上,并不会将这条信息插入到连接跟踪信息表中,插入到表中这是出口 confirm 阶段的工作。

    ct = nf_ct_tuplehash_to_ctrack(h);......} else {......} else {pr_debug("nf_conntrack_in: new packet for %p\n", ct);*ctinfo = IP_CT_NEW;}*set_reply = 0;}skb->nfct = &ct->ct_general;skb->nfctinfo = *ctinfo;
出口

出口处,Netfilter 将连接跟踪信息设置到报文 skb 上,这样在出口的地方就可以将其取出,再插入到连接信息的哈希表中,完成确认

ipv4_confirm||-- nf_conntrack_confirm||-- __nf_conntrack_confirm/* Confirm a connection given skb; places it in hash table */
int
__nf_conntrack_confirm(struct sk_buff *skb)
{struct nf_conn *ct;enum ip_conntrack_info ctinfo;// ......ct = nf_ct_get(skb, &ctinfo);// ......__nf_conntrack_hash_insert(ct, hash, reply_hash);// ......return NF_ACCEPT;
}        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/620101.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【MATLAB】CEEMDAN+FFT+HHT组合算法

代码原理 集成经验模态分解(CEEMDAN)是一种信号处理方法,旨在将非线性和非平稳信号分解为本质模态函数(IMF)。这种方法通过对信号进行多轮迭代,结合了噪声干扰的累计退化,从而更好地处理了信号…

关于React你必须知道的3个错误用法。

1. 你知道如何使用“&&”吗? 在React程序中,我经常使用“&&”运算符来决定是否显示内容,如下所示: 我的组长: “你不知道&&运算符的特性吗?当请求还没有成功返回时,会直接渲染“0”。” 我并不信服, 因为我一直都是这样编写代码,从未出过错。为了…

计算机网络技术-2022期末考试解析

【前言】 这是计算机网络技术这门课,感觉和计网还是有不一样的,但也有能做的,把能做的做了。 一、单项选择题(每题2分,共20分) 1. 用于测试两台计算机连通状况的命令是 。 ( ) A. cmd B. ping C. ipconf…

Java副本的概念

在Java中,"副本"(copy)一词可以用于描述不同的概念,具体取决于上下文。以下是两个常见的用法: 对象的副本:在Java中,当你创建一个对象并将其赋值给另一个变量时,实际上是创…

配置CentOS系统以支持静态HTTP服务

CentOS是一个流行的Linux发行版,广泛应用于服务器环境。要配置CentOS系统以支持静态HTTP服务,您可以按照以下步骤进行操作: 安装Web服务器软件:CentOS自带了Apache HTTP服务器软件,您可以使用以下命令安装它&#xff1…

Go 知多少?

作为一名已接触过其他语言的开发,再去学习一门新语言可比之前轻松不少, 语言之间存在很多相似点,但是新语言也有自己的不同点,通常我会先了解它与其他语言常遇到的不同点有哪些, 使自己先能够上手编写基础程序&#…

Java多线程:初识多线程!左手画方,右手画圆

👑专栏内容:Java⛪个人主页:子夜的星的主页💕座右铭:前路未远,步履不停 目录 一、线程与进程二、创建线程方法1、继承Thread类2、实现Runnable接口3、两者区别4、举个栗子5、简洁写法Ⅰ、Thread匿名内部类写…

DNS 正/反向解析 主从复制 分离解析

一 DNS概念它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网 每一台 DNS 服务器都只负责管理一个有限范围 根域: 全球根服务器节点只有13个,10个在美国,1个荷兰,1个瑞典,1个日本 一级域名&#xff…

【已解决】C语言实现多线程的同步与异步

说真的写了这篇博文时,才知道c语言本身不支持多线程,而是一些windowsapi让c语言拥有多线程的能力,那下面内容就以打开对话框为例,展现如何实现多线程的同步与异步。 文章目录 问题起源c语言多线程同步方案c语言多线程异步方案总结…

Typora使用及Markdow学习笔记1

编程如画,我是panda! 最近有在学习Markdown,所以这次分享一下我的Markdown学习笔记 目录 前言 一、标题 二、段落 1.换行 2.分割线 三、文字显示 1.字体 2.上下标 四、列表 1.无序列表 2.有序列表 3.任务列表 五、区块 六、代…

【Linux运维】LVM和RAID学习及实践

LVM和RAID学习及实践 背景LVM简介新加硬盘的操作RAID-磁盘阵列应用场景RAID0RAID1其他结构RAID制作RAID 小结 背景 某台服务器的磁盘管理需要自己动手处理,找了一些资料也踩了一些坑,在这里记录一下,先介绍一下LVM和RAID这两个东西。在计算机…

【天龙八部】攻略day6

关键字: 灵武、寻宝要求、雁门 1】灵武选择 西凉枫林,锦带,短匕 白溪湖,明镜,双刺 竹海,玉钩,锁甲 2】楼兰寻宝需求 等级80级,40级前6本心法 3】雁门奖励 简单35*4元佑碎金 普…

慕尼黑工业大学最新提出!单目实时密集建图的混合隐式场方法

作者:小柠檬 | 来源:3DCV 在公众号「3DCV」后台,回复「原论文」可获取论文pdf 我们提出了一种新颖的方法,它将基于深度学习的密集SLAM与神经隐式场相结合,实时生成密集地图,而无需像以前的方法那样依赖RGB-…

数据库练习题

素材: 表名:worker-- 表中字段均为中文,比如 部门号 工资 职工号 参加工作 等 CREATE TABLE worker ( 部门号 int(11) NOT NULL, 职工号 int(11) NOT NULL, 工作时间 date NOT NULL, 工资 float(8,2) NOT NULL, 政治面貌 varchar(10) NO…

java大学生宿舍共享厨房系统宿舍自习室宿舍洗衣房系统源码包含技术文档

主要功能:学生可注册登录,预约自己宿舍楼栋的共享厨房和评价,也可以使用该楼栋的洗衣房,查看洗衣机吹风机的使用情况和报修,还可以进入该楼栋自习室打卡和评价。管理员可管理所有的学生和宿管,分配宿舍&…

10年果粉拯救老掉牙Mac心得(没错我是标题党)

连续两周了,当我不能用Mac,或者说当我闲置了近10年隔三差五的用Mac时,成功发现我的AppleID已经无法登录了。事情是这样的,当我踌躇满志地准备改一篇稿子(潜在的稿费啊亲!)时,发现Pages竟然没有W…

用Kimi chat识别并整理图片里面的文字

Kimi chat是有OCR功能的,可以识别图片中的文字。 下面这张图片是一本书的注释,里面提到有不少图书,利用Kimi chat就可以轻松完成提取其中图书书名的任务。 先拿一张图片来做实验。Kimichat的回复: 在您提供的文件内容中&#xf…

LLM大模型显存计算

一、目录 模型参数单位内存计算案例显卡算力推理显存计算训练显存计算huggface 官网计算 模型推理/训练 需要的显存大模型输入长度与显存的关系大模型推理 多线程与显存的关系 参考:https://blog.csdn.net/Johntill/article/details/132629075 二、实现 模型参数…

【RV1126 学习】SDK/ U-Boot/kernel/rootfs 编译学习

文章目录 RV1126芯片介绍rv1126 模块代码目录相关说明 SDK 包下的脚本使用build.sh 脚本使用envsetup.sh 脚本使用mkfirmware.sh 脚本使用rkflash.sh 脚本使用 U-Boot 编译和配置uboot 的配置修改编译操作 kernel 的修改编译rootfs 编译和配置buildroot 配置busybox 配置 固件打…

爬虫之牛刀小试(四):爬取B站番剧的简介

今天爬取的是b站。 如何爬取b站中的番剧呢? 首先我们来到番剧索引中,随便点开一部动漫,检查代码。 每个作品对应一个链接: https://www.bilibili.com/bangumi/play/ss…(ss后面的数字称为ss号) 发现关于动漫的信息…