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

相关文章

Python的time模块一些常用功能(各种与时间相关的函数)

《Python的time模块一些常用功能(各种与时间相关的函数)》Python的time模块提供了各种与时间相关的函数,包括获取当前时间、处理时间间隔、执行时间测量等,:本文主要介绍Python的... 目录1. 获取当前时间2. 时间格式化3. 延时执行4. 时间戳运算5. 计算代码执行时间6. 转换为指

利用Python调试串口的示例代码

《利用Python调试串口的示例代码》在嵌入式开发、物联网设备调试过程中,串口通信是最基础的调试手段本文将带你用Python+ttkbootstrap打造一款高颜值、多功能的串口调试助手,需要的可以了... 目录概述:为什么需要专业的串口调试工具项目架构设计1.1 技术栈选型1.2 关键类说明1.3 线程模

Android实现两台手机屏幕共享和远程控制功能

《Android实现两台手机屏幕共享和远程控制功能》在远程协助、在线教学、技术支持等多种场景下,实时获得另一部移动设备的屏幕画面,并对其进行操作,具有极高的应用价值,本项目旨在实现两台Android手... 目录一、项目概述二、相关知识2.1 MediaProjection API2.2 Socket 网络

Redis消息队列实现异步秒杀功能

《Redis消息队列实现异步秒杀功能》在高并发场景下,为了提高秒杀业务的性能,可将部分工作交给Redis处理,并通过异步方式执行,Redis提供了多种数据结构来实现消息队列,总结三种,本文详细介绍Re... 目录1 Redis消息队列1.1 List 结构1.2 Pub/Sub 模式1.3 Stream 结

Linux命令之firewalld的用法

《Linux命令之firewalld的用法》:本文主要介绍Linux命令之firewalld的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux命令之firewalld1、程序包2、启动firewalld3、配置文件4、firewalld规则定义的九大

MySQL索引的优化之LIKE模糊查询功能实现

《MySQL索引的优化之LIKE模糊查询功能实现》:本文主要介绍MySQL索引的优化之LIKE模糊查询功能实现,本文通过示例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录一、前缀匹配优化二、后缀匹配优化三、中间匹配优化四、覆盖索引优化五、减少查询范围六、避免通配符开头七、使用外部搜索引擎八、分

Java程序进程起来了但是不打印日志的原因分析

《Java程序进程起来了但是不打印日志的原因分析》:本文主要介绍Java程序进程起来了但是不打印日志的原因分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java程序进程起来了但是不打印日志的原因1、日志配置问题2、日志文件权限问题3、日志文件路径问题4、程序

Linux之计划任务和调度命令at/cron详解

《Linux之计划任务和调度命令at/cron详解》:本文主要介绍Linux之计划任务和调度命令at/cron的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux计划任务和调度命令at/cron一、计划任务二、命令{at}介绍三、命令语法及功能 :at

Android实现悬浮按钮功能

《Android实现悬浮按钮功能》在很多场景中,我们希望在应用或系统任意界面上都能看到一个小的“悬浮按钮”(FloatingButton),用来快速启动工具、展示未读信息或快捷操作,所以本文给大家介绍... 目录一、项目概述二、相关技术知识三、实现思路四、整合代码4.1 Java 代码(MainActivi

Linux下如何使用C++获取硬件信息

《Linux下如何使用C++获取硬件信息》这篇文章主要为大家详细介绍了如何使用C++实现获取CPU,主板,磁盘,BIOS信息等硬件信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录方法获取CPU信息:读取"/proc/cpuinfo"文件获取磁盘信息:读取"/proc/diskstats"文