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

相关文章

Security OAuth2 单点登录流程

单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登录时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一注销(single sign-off)就是指

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

linux-基础知识3

打包和压缩 zip 安装zip软件包 yum -y install zip unzip 压缩打包命令: zip -q -r -d -u 压缩包文件名 目录和文件名列表 -q:不显示命令执行过程-r:递归处理,打包各级子目录和文件-u:把文件增加/替换到压缩包中-d:从压缩包中删除指定的文件 解压:unzip 压缩包名 打包文件 把压缩包从服务器下载到本地 把压缩包上传到服务器(zip

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

ASIO网络调试助手之一:简介

多年前,写过几篇《Boost.Asio C++网络编程》的学习文章,一直没机会实践。最近项目中用到了Asio,于是抽空写了个网络调试助手。 开发环境: Win10 Qt5.12.6 + Asio(standalone) + spdlog 支持协议: UDP + TCP Client + TCP Server 独立的Asio(http://www.think-async.com)只包含了头文件,不依