当前位置: 首页 > news >正文

linux 内核数据包处理中的一些坑和建议

1、获取IP头部

iph = ip_hdr(skb);

struct sk_buff {

......

sk_buff_data_t transport_header; /* Transport layer header */

sk_buff_data_t network_header; /* Network layer header */

sk_buff_data_t mac_header; /* Link layer header */

......

}

1)__netif_receive_skb()在进入三层处理前就对network_header进行了设置。

2)ip_rcv()中详细的检查保证了IP头部到netfilter后是完整的。

3)netfilter可以尽情使用ip头部。

2、获取tcp头部

错误1:

tcph = tcp_hdr(skb);

陷阱:

netfilter的钩子点是属于TCP/IP协议栈的三层流程中,而四层的TCP头部此时还没有正确获取,只是初始化为IP头部的值,无法直接使用。

错误2:

tcph = (char *)iph + (iph->ihl << 2);

陷阱:

数据包可能是非线性的

         

改进:

tcpoff = skb_network_offset(skb) + (iph->ihl << 2);

tcph = skb_header_pointer(skb, tcpoff, sizeof(_tcph), &_tcph);

if (tcph == NULL)

return;

skb_network_offset(struct skb_buff *skb)

计算三层头部相对于skb->data的偏移

void * skb_header_pointer(struct sk_buff *skb, int offset, int len, void *buffer)

从skb的指定偏移取制定长度的数据,如果要取的数据位于线性区,直接返回其开始指 针,否则,则拷贝到buffer中,并将buffer指针返回。

3、打印IP信息

printk("%pI4 %d -----> %pI4 %d len: %d  ID: %d\n",

&iph->saddr,

ntohs(tcph->source),

&iph->daddr,

ntohs(tcph->dest),

ntohs(iph->tot_len),

ntohs(iph->id));

注意要点:

1) IP地址输出

Ipv4:%pI4   %pi4

IPv6:%pI6   %pi6

2) MAC地址

%pM   %pm

3)字节序的转换

ntohs()   ntohl()  htons()   htonl()

__const_ntohl()   __const_ntohs()    __const_htonl()   __const_htons()

区别:__const_*()是编译时处理的。

4、获取TCP负载

风险:

payload = (char *)tcph + tcph->doff * 4;

陷阱1:

数据包可能是非线性的,同TCP头部。

陷阱2:

TCP头部数据有可能是被篡改过的,tcph->doff如果很大怎么办?

改进1:

tcplen = skb->len - tcpoff;

if (tcph->doff*4 < sizeof(struct tcphdr) || tcplen < tcph->doff*4)

{

printk("Bad tcp.\n");

return NF_ACCEPT;

}

if (skb_is_nonlinear(skb))

{

printk("Nonlinear skb.\n");

return NF_ACCEPT;

}

payload = (char *)tcph + tcph->doff * 4;

payload_len = tcplen - tcph->doff * 4;

if (payload_len == 0)

return NF_ACCEPT;

接口介绍:

int skb_is_nonlinear(struct sk_buff *skb)

判断skb的数据是否是非线性的

改进2:

char payload_buf[1500];

tcplen = skb->len - tcpoff;

if (tcph->doff*4 < sizeof(struct tcphdr) || tcplen < tcph->doff*4)

{

printk("Bad tcp.\n");

return NF_ACCEPT;

}

payload_len = tcplen - tcph->doff * 4;

if (payload_len == 0)

return NF_ACCEPT;

if (payload_len > sizeof(payload_buf))

return NF_ACCEPT;

payload = skb_header_pointer(skb, tcpoff + tcph->doff*4, payload_len, payload_buf);

if (payload == NULL)

return NF_ACCEPT;

改进3:

tcplen = skb->len - tcpoff;

if (tcph->doff*4 < sizeof(struct tcphdr) || tcplen < tcph->doff*4)

{

printk("Bad tcp.\n");

return NF_ACCEPT;

}

if (skb_ linearize(skb))

{

printk("Can not linearize skb.\n");

return NF_ACCEPT;

}

payload = (char *)tcph + tcph->doff * 4;

payload_len = tcplen - tcph->doff * 4;

if (payload_len == 0)

return NF_ACCEPT;

接口介绍:

int skb_ linearize (struct sk_buff *skb)

将skb线性化

5、解析数据

1)判断数据包内容

风险1:

if (payload[0] != 'G' || payload[1] != 'E' || payload[2] != 'T')

风险2:

if ((payload[0] == 'G' && payload[1] == 'E' && payload[2] == 'T') && payload_len == 3)

陷阱:

如果payload的长度只有1个字节怎么办?

改进:

if (payload_len < 3 || payload[0] != 'G' || payload[1] != 'E' || payload[2] != 'T')

2) 查找数据包中的某个字符串

风险:

host = strstr(payload, "Host: ");

陷阱:

可能会越界,数据包不一定是以'\0'结束。

改进:

host = strnstr(payload, "Host: ", payload_len);

if (host == NULL)

return ;

一定要使用这一系列的函数:

strnchr

strncpy

strncat

strncmp

strnicmp

strnlen

memcpy

3)移动指向数据包的指针

风险:

host = strnstr(payload, "Host: ", payload_len);

if (host == NULL)

return ;

host = host + sizeof("Host: ") - 1;

/*

* deal with host

*/

陷阱:

查找的字符串有可能是数据包的最后一部分。

改进:

host = strnstr(payload, "Host: ", payload_len);

if (host == NULL)

return ;

host = host + sizeof("Host: ") - 1;

if (host >= (payload + payload_len))

return;

/*

* deal with host

*/

4)数据包操作

错误:

u32 len;

len = payload_len - 512;

if (len <= 0)

return;

memcpy(buf, payload, len);

陷阱:

无符号数的强制类型转换,u32类型永远都是大于等于0的,当payload_len小于512 时,判断就会不生效。

改进:

u32 len;

if (payload_len <= 512)

return;

len = payload_len - 512;

memcpy(buf, payload, len);

或者

int len;

len = payload_len - 512;

if (len <= 0)

return;

memcpy(buf, payload, len);

5)

风险:

int len = payload[1];

memcpy(buf, &payload[2], len);

陷阱:

可能是异常数据包,offset不是你想要的

正确做法:

nt len = payload[1];

if (len >= payload_len - 2)

return;

memcpy(buf, &payload[2], len);

综述:数据包处理要时刻保持警醒,它可能不是你想象的样子!

相关文章:

linux 内核数据包处理中的一些坑和建议

1、获取IP头部 iph ip_hdr(skb); struct sk_buff { ...... sk_buff_data_t transport_header; /* Transport layer header */ sk_buff_data_t network_header; /* Network layer header */ sk_buff_data_t mac_header; /* Link layer header */ ...... } 1&#xff0…...

C++ 的衰退复制(decay-copy)

目录 1.什么是衰退复制&#xff08;decay-copy&#xff09; 1.1.推导规则 1.2.LWG issue 929 1.3.想象中的 decay_copy 2.decay-copy 与 auto 2.1.为什么引入衰退复制 2.2. 成为 C 23 的语言特性 3.应用场景 4.总结 1.什么是衰退复制&#xff08;decay-copy&#xff0…...

vue-cli 5接入模块联邦 module federation

vue-cli 5接入模块联邦 module federation 模块联邦概念实现思路配置遇到的问题: 模块联邦概念 模块联邦由webpack 5最先推出的,让应用加载远程的代码模块来实现不同的Web应用共享代码片段.模块联邦分为两个角色,一个是生产者,一个是消费者.生产者暴露代码供消费者消费 (用一个…...

【Rust自学】3.6. 控制流:循环

3.6.0. 写在正文之前 欢迎来到Rust自学的第三章&#xff0c;一共有6个小节&#xff0c;分别是: 变量与可变性数据类型&#xff1a;标量类型数据类型&#xff1a;复合类型函数和注释控制流&#xff1a;if else控制流&#xff1a;循环&#xff08;本文&#xff09; 通过第二章…...

【第八节】git与github

目录 前言 一、 远程仓库概述 二、 创建、配置、连接推送远程仓库 2.1 在 GitHub 上创建仓库 2.2 生成 SSH Key 2.3 验证 SSH 连接 2.4 本地初始化仓库 2.5 推送本地仓库到远程 三、 管理远程仓库 3.1 查看远程仓库 3.2 提取远程仓库更新 3.3 推送更新到远程仓库 …...

win如何访问Linux数据库(本地)

对于数据库的学习&#xff0c;我们都是在localhost主机上进行操作&#xff0c;当我们在Linux系统上安装数据库时&#xff0c;我们就有了尝试在win上去访问Linux上的数据库的想法。 数据库中的用户&#xff1a; 我们都知道数据库中顶级的用户为root&#xff0c;在做创建用户的联…...

Windows设置所有软件默认以管理员身份运行

方法一、修改注册表 winr打开运行&#xff0c;输入“regedit”打开注册表&#xff1b; 打开此路径“计算机HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionPoliciesSystem”&#xff1b; 在右侧找到“EnableLUA”&#xff0c;将其值改为0&#xff0c;重启电脑。 …...

前端 计算发布时间(如“1小时前”、“3天前”等)

这样效果&#xff0c;在c端比较常见&#xff0c;通过前端也可以处理 代码如下&#xff1a; // 计算 小时timeAgo(createTime) {// 将 createTime 字符串转换为 Date 对象 const createDate new Date(createTime);const now new Date();const diffInSeconds Math.floor((now…...

shardingjdbc 4.0.0 seata分布式事务Failed to fetch schema问题

报错 12-18 15:18:35.931 [ERROR] [i.s.r.d.s.s.cache.AbstractTableMetaCache:63 ] [traceId:][spanId:] - get table meta of the table wh_stock_log error: Failed to fetch schema of xxx java.sql.SQLException: Failed to fetch schema of wh_stock_logat io.seata.r…...

罗德与施瓦茨NRT2功率反射仪,NRT2通过式功率计

罗德与施瓦茨NRT2功率反射仪NRT2 通过式功率计 描述 定向/通过式功率传感器在线测量正向和反向功率。在安装、维修和监控发射机、天线和射频发生器时&#xff0c;需要进行这些测量。R&SNRT系列由R&SNRT2功率反射计及各种R&SNRT Zxx定向功率传感器。 由于其测量功…...

QLineEdit限制输入固定字节数(UTF-8编码)

setMaxLength(int)只能用来限制输入的字符个数 QLineEdit *editor new QLineEdit(parent); editor->setMaxLength(32); 1、如果是单字节字符&#xff0c;如数字&#xff0c;字母等&#xff0c;字符数正好等于字节数 2、如果是多字节字符&#xff0c;UTF8编码时&#xff0…...

基于ubuntu的mysql 8.0安装教程

文章目录 1.查看版本2.切换到root账户3.下载安装包4.问题的解决5.查看是否解压成功6.安装我们的发布包7.更新包的内容8.下载mysql9.查看mysql的状态10.设置开机自启动11.登录mysql 公司里面的mysql根本不会出现在windows操作系统上面&#xff0c;下面我们演示的就是如何在ubunt…...

K8s ConfigMap的基础功能介绍

在 Kubernetes 中&#xff0c;ConfigMap 是一种用于管理配置信息的资源对象&#xff0c;它允许你将 配置信息与代码解耦&#xff0c;方便管理和更新应用配置&#xff0c;而无需重新构建镜像或重启服务。 ConfigMap 的功能 存储配置信息&#xff1a; 可以以 键值对 的形式存储配…...

Linux——Shell

if 语句 格式&#xff1a;if list; then list; [ elif list; then list; ] ... [ else list; ] fi 单分支 if 条件表达式; then 命令 fi 示例&#xff1a; #!/bin/bash N10 if [ $N -gt 5 ]; then echo yes fi # bash test.sh yes 双分支 if 条件表达式; then 命令 else 命令…...

armsom产品编译烧录Linux固件

1、开发环境及工具准备 Rockchip Linux 软件包&#xff1a;linux-5.10-gen-rkr4 主机&#xff1a; 安装VMware搭建虚拟机&#xff0c;版本为Ubuntu 20.04 (硬盘容量大于100G&#xff09; 安装远程连接工具MobaXterm&#xff08;可连接虚拟机方便文件传输&#xff09; 2、S…...

VSCode:Markdown插件安装使用 -- 最简洁的VSCode中Markdown插件安装使用

VSCode&#xff1a;Markdown插件安装使用 1.安装Marktext2.使用Marktext 本文&#xff0c;将在Visual Studio Code中&#xff0c;安装和使用Markdown插件&#xff0c;以Marktext插件为例。 1.安装Marktext 打开VSCode&#xff0c;侧边栏中找到扩展模块(或CtrlShiftX快捷键)&am…...

AI 行业发展趋势:科技创新引领未来变革

在当今数字化时代,人工智能(AI)行业正以前所未有的速度蓬勃发展,深刻地改变着我们的生活、工作和社会格局。从基础技术的突破到广泛的应用场景拓展,AI 展现出了一系列令人瞩目的发展趋势,预示着一个充满无限可能的未来。 一、技术创新持续突破 模型规模与性能提升 AI 模…...

FB爆款打法实操经验总结

在进行Facebook广告投放时&#xff0c;有效的预算控制、素材测试、广告效果评估和lookalike受众的管理是至关重要的。通过科学的方法和策略&#xff0c;您可以在竞争激烈的市场中实现更好的业绩。 01 预算控制 测试阶段的广告不稳定性&#xff1a;在投放广告的初期&#xff0c…...

微信小程序TTS解决方案

微信小程序原生语音合成 API&#xff08;基础且简单&#xff09; 介绍&#xff1a;微信小程序提供了基础的语音合成能力。通过wx.createInnerAudioContext()等相关API&#xff0c;可以实现简单的语音播放功能。不过它主要是用于音频播放&#xff0c;对于完整的文本到语音&#…...

centos stream 8下载安装遇到的坑

早在2020年12月。CentOS 官方发文宣称&#xff1a;“CentOS项目的未来是 CentOS Stream 明年我们会将重点从CentOS Linux 转移到CentOS Stream 它紧随当前 RHEL 版本之前。CentOS Linux 8 作为 RHEL 8 的重建&#xff0c;将于 2021 年底结束。CentOS Stream 在该日期之后继续&a…...

计算机网络——期末复习(1)背诵

背诵 交换机与路由器&#xff1a;交换机连接同一子网&#xff0c;利用帧中的目的物理地址转发帧&#xff0c;工作在数据链路层&#xff1b;路由器连接不同子网&#xff0c;利用IP数据报中的目的IP地址转发IP数据报&#xff0c;工作在网络层。五层的任务&#xff1a;&#xff0…...

AORO M6 Pro单北斗防爆终端全面国产化,关键技术不再“卡脖子”

全球科技竞争日益激烈&#xff0c;核心技术自主创新已成为国家发展的战略基石。面对关键技术被“卡脖子”的风险&#xff0c;中国科技企业正加速推进信息技术应用创新战略&#xff0c;力求在关键领域实现自主可控。遨游通讯推出的一款融合单北斗、鸿蒙系统、5G国产芯片的防爆终…...

ubuntu 卸载 MySQL

1. 卸载 MySQL 1.1 停止 MySQL 服务 首先&#xff0c;停止 MySQL 服务&#xff1a; sudo systemctl stop mysql 1.2 卸载 MySQL 包 使用 apt-get 命令卸载 MySQL 包&#xff1a; sudo apt-get remove --purge mysql-server mysql-client mysql-common mysql-server-core-* my…...

6、基于SpringBoot的网上购物系统

摘 要 随着我国经济的飞速发展&#xff0c;人们的生活速度明显加快&#xff0c;在餐厅吃饭排队的情况到处可见&#xff0c;近年来由于新兴IT行业的空前发展&#xff0c;它与传统餐饮行业也进行了新旧的结合&#xff0c;很多餐饮商户开始通过网络建设订餐系统&#xff0c;通过专…...

AMS1117芯片驱动电路·降压芯片的驱动电路详解

编写不易&#xff0c;仅供学习&#xff0c;请勿搬运&#xff0c;感谢理解 AMS1117驱动电路 很常用的一种LDO降压芯片&#xff0c;LDO(Low Dropout Regulator)降压芯片是线性稳压器&#xff0c;这种IC因为内部集成的不是开关电路&#xff0c;只能将输入与输出的电压差值通过内部…...

数据仓库工具箱—读书笔记02(Kimball维度建模技术概述02、事实表技术基础)

Kimball维度建模技术概述 记录一下读《数据仓库工具箱》时的思考&#xff0c;摘录一些书中关于维度建模比较重要的思想与大家分享&#x1f923;&#x1f923;&#x1f923; 第二章前言部分作者提到&#xff1a;技术的介绍应该通过涵盖各种行业的熟悉的用例展开&#xff08;赞同…...

SAP ABAP-日期格式问题 SAP内部错误,反序列化JSON字符串时发生异常 值 20241215 不是根据 ABAP 的 XML 格式的有效日期

SAP ABAP-日期格式问题 SAP内部错误,反序列化JSON字符串时发生异常 值 20241215 不是根据 ABAP 的 XML 格式的有效日期 在SAP内部用 YYYYMMDD没有问题 外部传入参数...

Linux-ubuntu点LED灯C语言版

​ 一&#xff0c;C语言点灯 1.寄存器配置 设置为SVC模式&#xff0c;复用寄存器设置GPIO1-IO003,设置电气属性&#xff0c;设置为输出模式。 2.软件 汇编语言对模式设置&#xff0c;并且将堆栈指针指向主程序&#xff1a; .global _start_start: /*设置为svr模式 */mrs …...

ASP.NET|日常开发中数据集合详解

ASP.NET&#xff5c;日常开发中数据集合详解 前言一、数组&#xff08;Array&#xff09;1.1 定义和基本概念1.2 数组的操作 二、列表&#xff08;List<T>&#xff09;2.1 特点和优势2.2 常用操作 三、字典&#xff08;Dictionary<K, V>&#xff09;3.1 概念和用途…...

Pytest-Bdd vs Behave:选择最适合的 Python BDD 框架

Pytest-Bdd vs Behave&#xff1a;选择最适合的 Python BDD 框架 Pytest BDD vs Behave&#xff1a;选择最适合的 Python BDD 框架BDD 介绍Python BDD 框架列表Python BehavePytest BDDPytest BDD vs Behave&#xff1a;关键区别Pytest BDD vs Behave&#xff1a;最佳应用场景结…...