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

news2024/9/24 1:17:17

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_in

nf_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和sport
	if (!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);                    // 计算hash
	h = __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.coloradmin.cn/o/1380739.html

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

相关文章

【LeetCode每日一题】2182. 构造限制重复的字符串

2024-1-13 文章目录 [2182. 构造限制重复的字符串](https://leetcode.cn/problems/construct-string-with-repeat-limit/)思路: 2182. 构造限制重复的字符串 思路: 按照字符出现次数从高到低的顺序进行重复,通过维护一个指针 j 来寻找下一个…

如何在你的网站接入QQ登录?

文章目录 准备阶段申请QQ登录的权限创建应用最后上传qqlogin.php代码 准备阶段 国内服务器和备案域名需要你有张独一无二本人的身份证你正面手持身份证的图片一张100px*100px的网站图标 申请QQ登录的权限 首先访问qq互联,点击我直接访问 登陆完成后我们点击面的…

Java判断字符串当中是否有中文符号(不是中文名称,是符号)

public static void main(String[] args) throws ParseException, IOException, URISyntaxException {// 测试示例String testString1 "Hello,test!";String testString2 "This is a test.";boolean result1 containsChineseSymbols(testStr…

又涨了:net的域名铁定涨价

关注卢松松,会经常给你分享一些我的经验和观点。 又要涨价了,又要涨价了,又要涨价了!继.com域名涨价后,.net的域名也逐步涨价。最近一年来域名疯狂涨价,几个月内已经几乎翻番。 阿里云2月1日起上调.net英文域名价格…

专业课148,总分410+电子科技大学858信号与系统考研经验电子信息与通信

今年专业课148分,总分410顺利被电子科技大学录取,回望这一年复习还有很多不足,总结一下自己的复习经历,希望对大家复习有所帮助。 数学:(多动手,多计算,多总结,打好基础…

YOLOv8改进:小目标涨点系列篇 | UNet v2 多层次特征融合模块结合DualConv、GSConv

🚀🚀🚀本文改进:多层次特征融合(SDI)结合DualConv、GSConv模块等实现二次创新 🚀🚀🚀SDI 亲测在多个数据集能够实现涨点,同样适用于小目标检测 🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研…

Android 13 辅助屏导航栏不显示问题

问题 在Android 13 上开启辅助屏幕。但是发现辅助屏systemui 导航按 icon没有显示,但是点击对应的区域有作用 分析 可以用 anroid device monitor 工具分析视图 解决 public NavigationBarView(Context context, AttributeSet attrs) {super(context, attrs);…

微信订阅号 服务号区别

服务号和订阅号有什么区别?服务号转为订阅号有哪些作用?很多小伙伴想把服务号改为订阅号,但是不知道改了之后具体有什么作用,今天跟大家具体讲解一下。首先我们知道服务号一个月只能发四次文章,但是订阅号每天都可以发…

GitHub注册新账号的操作流程(详细)

目录 第一步 进入官网,点击右上角的"Sign up" 第二步 输入email地址 第三步 设置密码 第四步 输入昵称 第五步 根据个人喜好决定要不要接收GitHub的邮件推送。然后回答他们的验证问题 第六步 输入验证码 我在注册github账号时遇到过一些阻碍&#x…

VMware workstation安装debian-12.1.0虚拟机并配置网络

VMware workstation安装debian-12.1.0虚拟机并配置网络 Debian 是一个完全自由的操作系统!Debian 有一个由普罗大众组成的社区!该文档适用于在VMware workstation平台安装debian-12.1.0虚拟机。 1.安装准备 1.1安装平台 Windows 11 1.2软件信息 软…

软件测试|Selenium StaleElementReferenceException 异常分析与解决

简介 Selenium 是一个流行的自动化测试工具,用于模拟用户与网页交互。然而,当我们在使用 Selenium 时,可能会遇到一个常见的异常,即 StaleElementReferenceException。这个异常通常在我们尝试与网页上的元素交互时抛出&#xff0…

跟着cherno手搓游戏引擎【5】layer(层)

编写基类层: Layer.h:提供Attach链接、Detach解绑、Update刷新、Event事件、GetName方法 #pragma once #include"YOTO/Core.h" #include"YOTO/Event/Event.h" namespace YOTO {class YOTO_API Layer{public:Layer(const std::string& nam…

竞赛保研 基于生成对抗网络的照片上色动态算法设计与实现 - 深度学习 opencv python

文章目录 1 前言1 课题背景2 GAN(生成对抗网络)2.1 简介2.2 基本原理 3 DeOldify 框架4 First Order Motion Model5 最后 1 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 基于生成对抗网络的照片上色动态算法设计与实现 该项目较为新颖&am…

只不过孤岛罢了:我的2023年总结

2023已悄然过去,还记得跨年夜那天,我突然接到一星期要期末考的消息,我的内心是多么奔溃,先不说一天一门强度如此之高,重要的是矩阵论,工程优化等等科目,还要速成,于是麻木得预习一日…

Redis:原理速成+项目实战——Redis企业级项目实战终结篇(HyperLogLog实现UV统计)

👨‍🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习 🌌上期文章:Redis:原理速成项目实战——Redis实战14(BitMap实现用户签到功能) 📚订阅专栏&am…

Open CASCADE学习|基于visual studio 2022编译源码

目录 1、简介 2、下载 2.1下载visual studio 2022 community 2.2下载下载cmake工具 2.3下载源码 2.4下载第三方插件 3、安装 3.1安装visual studio 2022 community 3.2安装cmake 4、编译源码 5、测试 1、简介 Open CASCADE(简称…

maya , motionbuilder 骨骼动画相关操作与脚本

文章目录 Maya导入时增加namespacemaya 解除/增加父子关系maya 修改骨骼局部坐标系显示骨骼局部坐标系删除不需要的骨骼重命名骨骼重定向基础细节 Motionbuildermb同时打开两个动画文件 Maya 导入时增加namespace import pymel.core as pm pm.namespace(add"src") …

蓝桥杯省赛无忧 STL 课件16 set

01 set集合 修改set比较方法的常见手段&#xff0c;后面的multiset类似 #include<bits/stdc.h> using namespace std; int main() {set<int,greater<int>> myset;myset.insert(25);myset.insert(17);myset.insert(39);myset.insert(42);for(const auto&…

【Kafka-3.x-教程】-【三】Kafka-Broker、Kafka-Kraft

【Kafka-3.x-教程】专栏&#xff1a; 【Kafka-3.x-教程】-【一】Kafka 概述、Kafka 快速入门 【Kafka-3.x-教程】-【二】Kafka-生产者-Producer 【Kafka-3.x-教程】-【三】Kafka-Broker、Kafka-Kraft 【Kafka-3.x-教程】-【四】Kafka-消费者-Consumer 【Kafka-3.x-教程】-【五…

Binder 机制 javanative

一&#xff1a;Binder介绍 Binder是一套ipc通信方案 Binder框架定义了四个角色&#xff1a; Server &#xff0c;Client&#xff0c;ServiceManager &#xff08;以后简称SMgr&#xff09;以及Binder驱动。其中Server &#xff0c;Client&#xff0c;SMgr运行于用户空间&#…