linux [报文碎片重组功能] defrag分析/调试流程

2024-06-04 21:58

本文主要是介绍linux [报文碎片重组功能] defrag分析/调试流程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

1.碎片整理测试

2.iptables -f 不生效原因

3.报文碎片 丢弃的功能调试过程

测试1.kernel 协议栈分析

测试2:尝试在netfilter中匹配分片报文

代码分析1:

代码分析2

4.小结



1.碎片整理测试

【需求】

路由器过滤greptap 接口上的碎片报文,添加规则·iptabled -A INPUT -f -j DROP·

测试环境
win10: 192.168.0.2
linux: 192.168.0.5

测试1:无分片的报文
win10# ping 192.168.0.5 -->可以ping通

测试2:带分片的报文
win10# ping 192.168.0.5 -l 3000 -->可以ping通

测试3:linux过滤碎片的报文
linux# iptables -A INPUT -f -j DROP #丢弃碎片报文
win10# ping 192.168.0.5 -l 3000 -->依旧可以ping通

linux# iptables -nvL
Chain INPUT (policy ACCEPT 6729 packets, 8666K bytes)
num pkts bytes target prot opt in out source destination
1 0 0 DROP all -f * * 0.0.0.0/0 0.0.0.0/0

测试结论:
可以发现,Chain INPUT 链没有匹配到任何一个报文。
即iptables -f 的规则无效。
iptabled -A INPUT -f -j DROP

2.iptables -f 不生效原因

原文:

Why command "iptables -f" no use ?
Dropping IP fragments is obsolete advice. Linux kernel can and will automatically re-assemble and sanity-check all fragments as needed anyway. This happens before packets are handled by iptables connection tracking, so it is likely this rule may never match anything.
 

3.报文碎片 丢弃的功能调试过程

功能作用:开启时,可以防止一些tcp 碎片攻击。
 

测试1.内核协议栈分析

kernel/net/ip_input.c
int ip_rcv()
{
...
//打印 icmp 碎片报文
if((iph->protocol == 1) && ip_is_fragment(iph)){
printk("xxxx find icmp frag len=%d id=%x \n",ntohs(iph->tot_len),ntohs(iph->id),
ntohs(iph->saddr),ntohs(iph->daddr));
}
}


Log 打印:
xxxx find icmp frag len=1500 id=6f4e
xxxx find icmp frag len=1500 id=654e
xxxx find icmp frag len=68 id=654e
→ 即ping -l 3000 被分成3个报文,符合预期

测试结论1:
在协议栈 ip_rcv()函数中,匹配到3个分片报文。
 

测试2:尝试在netfilter中匹配分片报文

通过iptables s_ip d_ip 匹配

iptables -t mangle -A PREROUTING -s 192.168.0.2 -d 192.168.0.5 -j LOG --log-prefix "11 mangle"
iptables -t nat -A PREROUTING -s 192.168.0.2 -d 192.168.0.5 -j LOG --log-prefix "22 nat"

Log:
[ 3188.325756] 11 mangleIN=BR_LAN OUT= MAC=d8:6c:a1:2f:37:a7:e8:4e:06:66:93:50:08:00 SRC=192.168.0.2 DST=192.168.0.5 LEN=3028 TOS=0x00 PREC=0x00 TTL=128 ID=22063 PROTO=ICMP TYPE=8 CODE=0 ID=1 SEQ=2847
[ 3188.343275] 22 natIN=BR_LAN OUT= MAC=d8:6c:a1:2f:37:a7:e8:4e:06:66:93:50:08:00 SRC=192.168.0.2 DST=192.168.0.5 LEN=3028 TOS=0x00 PREC=0x00 TTL=128 ID=22063 PROTO=ICMP TYPE=8 CODE=0 ID=1 SEQ=2847
-->此处应该打印三个记录,实际只打印一条记录,即分片报文已经重组

测试结论2:
在PREROUTING链的报文长度为3028,
即分片报文在 到达netfilter 的 PREROUTING链之前,已经进行重组。

Linux 网络协议栈 和 netfilter 处理流程图

代码分析1:

ip_rcv()
{
/* 1. 经过PRE_ROUTING钩子点 */
return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING,
net, NULL, skb, dev, NULL,
ip_rcv_finish);
}/* 2.碎片重组功能 注册在 PRE_ROUTING hook 上*/
static struct nf_hook_ops ipv4_defrag_ops[] = {
{
.hook = ipv4_conntrack_defrag,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP_PRI_CONNTRACK_DEFRAG,//mininum -400
},
ipv4_conntrack_defrag()
-nf_ct_ipv4_gather_frags()
--ip_defrage()


分析结论3:
从代码上,确认ip_rcv() 处理在 PREROUTING链 之前。

代码分析2

/* 3.碎片重组 缓冲区 参数*/

ip_defrage()
static struct ctl_table ip4_frags_ns_ctl_table[] = {
{
.procname = "ipfrag_high_thresh",
.data = &init_net.ipv4.frags.high_thresh,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = &init_net.ipv4.frags.low_thresh
},
{
.procname = "ipfrag_low_thresh",
.data = &init_net.ipv4.frags.low_thresh,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = &zero,
.extra2 = &init_net.ipv4.frags.high_thresh
},
}


low_thresh high_thresh的作用,具体看代码。

尝试清除碎片缓存分区,参数对应的proc 节点
Set init_net.ipv4.frags.high_thresh to 0.
Set init_net.ipv4.frags.low_thresh to 0.

echo 0 > /proc/sys/net/ipv4/ipfrag_low_thresh
echo 0 > /proc/sys/net/ipv4/ipfrag_high_thresh

ping 192.168.0.5 -l 3000
Result: time out . --符合预期,ping失败。

测试总结4:
修改sys 节点,即可实现碎片报文的丢弃功能
/proc/sys/net/ipv4/ipfrag_low_thresh
/proc/sys/net/ipv4/ipfrag_high_thresh
 

4.小结

对ip协议栈的处理和netfilter之间的流程关系,理解的更深刻。
一开始并没有使用/proc/sys 节点实现,而是在函数之中
  1.判断为碎片报文,直接丢弃。-->修改内核代码,无扩展性,丢弃。
  2.将defrag的buffer修改为0,准备创建sys节点,将buffer 大小参数传递到用户空间修改,在编写的过程中,参照ipv4 sys节点的实现时,发现这两个节点
      -->1.运气。 2.内核通过配置提供功能,机制。通过参数适配不同功能需。可适配,可调节。

这篇关于linux [报文碎片重组功能] defrag分析/调试流程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1031236

相关文章

Go语言实现将中文转化为拼音功能

《Go语言实现将中文转化为拼音功能》这篇文章主要为大家详细介绍了Go语言中如何实现将中文转化为拼音功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 有这么一个需求:新用户入职 创建一系列账号比较麻烦,打算通过接口传入姓名进行初始化。想把姓名转化成拼音。因为有些账号即需要中文也需要英

高效管理你的Linux系统: Debian操作系统常用命令指南

《高效管理你的Linux系统:Debian操作系统常用命令指南》在Debian操作系统中,了解和掌握常用命令对于提高工作效率和系统管理至关重要,本文将详细介绍Debian的常用命令,帮助读者更好地使... Debian是一个流行的linux发行版,它以其稳定性、强大的软件包管理和丰富的社区资源而闻名。在使用

基于WinForm+Halcon实现图像缩放与交互功能

《基于WinForm+Halcon实现图像缩放与交互功能》本文主要讲述在WinForm中结合Halcon实现图像缩放、平移及实时显示灰度值等交互功能,包括初始化窗口的不同方式,以及通过特定事件添加相应... 目录前言初始化窗口添加图像缩放功能添加图像平移功能添加实时显示灰度值功能示例代码总结最后前言本文将

Redis主从/哨兵机制原理分析

《Redis主从/哨兵机制原理分析》本文介绍了Redis的主从复制和哨兵机制,主从复制实现了数据的热备份和负载均衡,而哨兵机制可以监控Redis集群,实现自动故障转移,哨兵机制通过监控、下线、选举和故... 目录一、主从复制1.1 什么是主从复制1.2 主从复制的作用1.3 主从复制原理1.3.1 全量复制

C++中实现调试日志输出

《C++中实现调试日志输出》在C++编程中,调试日志对于定位问题和优化代码至关重要,本文将介绍几种常用的调试日志输出方法,并教你如何在日志中添加时间戳,希望对大家有所帮助... 目录1. 使用 #ifdef _DEBUG 宏2. 加入时间戳:精确到毫秒3.Windows 和 MFC 中的调试日志方法MFC

Python实现NLP的完整流程介绍

《Python实现NLP的完整流程介绍》这篇文章主要为大家详细介绍了Python实现NLP的完整流程,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 编程安装和导入必要的库2. 文本数据准备3. 文本预处理3.1 小写化3.2 分词(Tokenizatio

Linux Mint Xia 22.1重磅发布: 重要更新一览

《LinuxMintXia22.1重磅发布:重要更新一览》Beta版LinuxMint“Xia”22.1发布,新版本基于Ubuntu24.04,内核版本为Linux6.8,这... linux Mint 22.1「Xia」正式发布啦!这次更新带来了诸多优化和改进,进一步巩固了 Mint 在 Linux 桌面

LinuxMint怎么安装? Linux Mint22下载安装图文教程

《LinuxMint怎么安装?LinuxMint22下载安装图文教程》LinuxMint22发布以后,有很多新功能,很多朋友想要下载并安装,该怎么操作呢?下面我们就来看看详细安装指南... linux Mint 是一款基于 Ubuntu 的流行发行版,凭借其现代、精致、易于使用的特性,深受小伙伴们所喜爱。对

Redis主从复制的原理分析

《Redis主从复制的原理分析》Redis主从复制通过将数据镜像到多个从节点,实现高可用性和扩展性,主从复制包括初次全量同步和增量同步两个阶段,为优化复制性能,可以采用AOF持久化、调整复制超时时间、... 目录Redis主从复制的原理主从复制概述配置主从复制数据同步过程复制一致性与延迟故障转移机制监控与维

什么是 Linux Mint? 适合初学者体验的桌面操作系统

《什么是LinuxMint?适合初学者体验的桌面操作系统》今天带你全面了解LinuxMint,包括它的历史、功能、版本以及独特亮点,话不多说,马上开始吧... linux Mint 是一款基于 Ubuntu 和 Debian 的知名发行版,它的用户体验非常友好,深受广大 Linux 爱好者和日常用户的青睐,