suricata之日志截断

news2025/5/11 18:07:36

一、背景

在suricata的调试过程中,使用SCLogXXX api进行信息的输出,发现输出的日志被截断了,最开始以为是解析逻辑有问题,没有解析完整,经过排查后,发现SCLogXXX api内部进行了长度限制,最长2K。

OS:Ubuntu 22.04.5 LTS
IDE: vscode
Suricata: suricata 7.0.5

二、 问题复现

拷贝一个规则,将规则内容填充任意内容,使其达到2K以上
请添加图片描述

规则重复时,输出错误日志,日志截断
请添加图片描述

三、分析

3.1 源码实现

// src/util-debug.h
/* The maximum length of the log message */
#define SC_LOG_MAX_LOG_MSG_LEN 2048

// src/util-debug.c
void SCLogErr(int x, const char *file, const char *func, const int line, const char *module,
        const char *fmt, ...)
{
    if (sc_log_global_log_level >= x &&
            (sc_log_fg_filters_present == 0 ||
             SCLogMatchFGFilterWL(file, func, line) == 1 ||
             SCLogMatchFGFilterBL(file, func, line) == 1) &&
            (sc_log_fd_filters_present == 0 ||
             SCLogMatchFDFilter(func) == 1))
    {
        char msg[SC_LOG_MAX_LOG_MSG_LEN];
        va_list ap;
        va_start(ap, fmt);
        vsnprintf(msg, sizeof(msg), fmt, ap);
        va_end(ap);
        SCLogMessage(x, file, line, func, module, msg);
    }
}

从实现中可以看出,首先将数据格式化到一个局部临时变量中,再将临时变量输出。
而临时变量是一个2K的字符数组,因此需要输出的数据超过2K将被截断。

3.2 为啥需要临时变量

  1. 将可变参数格式化成一个字符串,需要一个存储空间
  2. 栈变量是线程安全的
  3. 简单通用

3.3 是否可以增加空间

可以增加SC_LOG_MAX_LOG_MSG_LEN的值,但是不推荐

  1. 每条日志大小一般都很小,2K已经满足90%以上的情况
  2. 栈变量太大,递归或深层调用可能会耗尽栈空间
// 栈默认大小(KB)
$ ulimit -s
8192 

// 栈最大上限,受系统内存限制
$ ulimit -Hs
unlimited

// glibc 中的默认值
$ getconf PTHREAD_STACK_MIN
16384

3.4 非要解决截断问题如何处理

man vsnprintf

The  functions snprintf() and vsnprintf() do not write more than size bytes (including the
       terminating null byte ('\0')).  If the output was truncated due to this  limit,  then  the
       return value is the number of characters (excluding the terminating null byte) which would
       have been written to the final string if enough space had been available.  Thus, a  return
       value of size or more means that the output was truncated.  

根据man手册的说明,可以判断vsnprintf的返回值,返回值超过2048时,可以动态申请空间,再次进行格式化

    char msg[SC_LOG_MAX_LOG_MSG_LEN];
    char *real_msg = msg;

    va_list ap;
    va_start(ap, fmt);
    int ret = vsnprintf(msg, sizeof(msg), fmt, ap);
    va_end(ap);

    if (ret > SC_LOG_MAX_LOG_MSG_LEN) { // 被截断
        real_msg = SCMalloc(ret+1); // 动态分配空间
        if (likely(real_msg != NULL)) {
            va_start(ap, fmt);
            vsnprintf(real_msg, ret+1, fmt, ap); // 重新格式化
            va_end(ap);
        } else {
            real_msg = msg; // 空间申请失败
        }
    }
    SCLogMessage(x, file, line, func, module, real_msg);
    if (real_msg != msg) {
        SCFree(real_msg);
    }

结果是依然被截断了,继续分析SCLogMessage实现

SCError SCLogMessage(const SCLogLevel log_level, const char *file, const unsigned int line,
        const char *function, const char *module, const char *message)
{
    char buffer[SC_LOG_MAX_LOG_MSG_LEN] = "";
 ...
    case SC_LOG_OP_IFACE_CONSOLE:
        if (SCLogMessageGetBuffer(ts, op_iface_ctx->use_color, op_iface_ctx->type, buffer,
                    sizeof(buffer),
                    op_iface_ctx->log_format ? op_iface_ctx->log_format
                                                : sc_log_config->log_format,
                    log_level, file, line, function, module, message) == 0) {
            SCLogPrintToStream((log_level == SC_LOG_ERROR)? stderr: stdout, buffer);
        }
        break;
            ...
    return SC_OK;
}

又一个buffer[SC_LOG_MAX_LOG_MSG_LEN], 再次被截断

3.5 为啥是两次格式化

请添加图片描述

第一次是将用户输入的信息格式化;
第二次增加额外信息(时间、函数名,行号等),可通过配置决定添加的信息
suricata.yaml

logging:
  default-log-format: "%D: %S:%l %M"

总结

日志截断问题的主要原因是日志内容经过两次格式化,且每次格式化都使用了固定大小的缓冲区。通过动态分配缓冲区,可以有效避免日志被截断的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2373316.html

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

相关文章

简易图片编辑工具,支持抠图和替换背景

软件介绍 Photo Retouch是一款由微软官方商店推出的免费图片处理软件,具有抠图、换背景、修复等功能,操作便捷且效率极高,非常值得尝试。 功能详解 这款软件提供五大功能,包括删除物体、快速修复、一键抠图、背景调整和裁剪…

Java Bean容器详解:核心功能与最佳使用实践

在Java企业级开发中,Bean容器是框架的核心组件之一,它通过管理对象(Bean)的生命周期、依赖关系等,显著提升了代码的可维护性和扩展性。主流的框架如Spring、Jakarta EE(原Java EE)均提供了成熟的…

Spring Security 深度解析:打造坚不可摧的用户认证与授权系统

Spring Security 深度解析:打造坚不可摧的用户认证与授权系统 一、引言 在当今数字化时代,构建安全可靠的用户认证与授权系统是软件开发中的关键任务。Spring Security 作为一款功能强大的 Java 安全框架,为开发者提供了全面的解决方案。本…

Selenium模拟人类行为,操作网页的方法(全)

看到有朋友评论问,用selenium怎么模仿人类行为,去操作网页的页面呢? 我想了想,这确实是一个很大的点,不应该是一段代码能解决的, 就像是,如果让程序模拟人类的行为。例如模拟人类买菜,做饭&am…

右值引用的剖析

引入:为什么要有右值引用? 右值引用的存在,就是为了解决左值引用解决不了的问题! 左值引用的问题: 我们知道,左值引用在做参数和做返回值都可以提高效率;但是有时候,我们无法用左…

高效Python开发:uv包管理器全面解析

目录 uv简介亮点与 pip、pip-tools、pipx、poetry、pyenv、virtualenv 对比 安装uv快速开始uv安装pythonuv运行脚本运行无依赖的脚本运行有依赖的脚本创建带元数据的 Python 脚本使用 shebang 创建可执行文件使用其他package indexes锁定依赖提高可复现性指定不同的 Python 版本…

【Linux系统编程】进程属性--进程状态

1.进程的状态 1.1进程的状态在PCB中就是一个变量 一般用宏来定义,例如: #define RUNNING 1 #define BLOCK 2 struct task_struct中的int status 1.2并行和并发 CPU执行代码,不是把进程代码执行完毕,才执行下一个&#xff0…

高精度之加减乘除之多解总结(加与减篇)

开篇总述:精度计算的教学比较杂乱,无系统的学习,且存在同法多线的方式进行同一种运算,所以我写此篇的目的只是为了直指本质,不走教科书方式,步骤冗杂。 一,加法 我在此讲两种方法: …

dify插件接入fastmcp示例

文章目录 1. 使用python完成mcp服务1.1 准备环境(python安装fastmcp)1.2 mcp服务端示例代码1.3 启动mcp服务端 2. dify接入2.1 安装MCP SSE和 Agent 策略(支持 MCP 工具) 插件2.2 dify agent插件配置mcp:2.3 mcp服务配置&#xff…

c++——二叉树进阶

1. 内容安排说明 二叉树在前面C数据结构阶段已经讲过,本节取名二叉树进阶是因为: 1. map和set特性需要先铺垫二叉搜索树,而二叉搜索树也是一种树形结构 2. 二叉搜索树的特性了解,有助于更好的理解map和set的特性 3. 二叉树中部…

基于flask+pandas+csv的报表实现

基于大模型根据提示词去写SQL执行SQL返回结果输出报表技术上可行的,但为啥还要基于pandas去实现呢? 原因有以下几点: 1、大模型无法满足实时性输出报表的需求; 2、使用大模型比较适合数据量比较大的场景,大模型主要…

PySide6 GUI 学习笔记——常用类及控件使用方法(常用类字体QFont)

文章目录 一、QFont常用方法二、常用方法总结1. 基础属性设置2. 高级样式控制3. 序列化与反序列化4. 字体信息获取 三、应用实例 字体类QFont用于设置界面控件上显示的字体,它包含字体名称、字体尺寸、粗体字、斜体字、删除线、上划线、下划线、字体间距等属性。 如…

宝塔服务安装使用的保姆级教程

宝塔介绍: 宝塔面板(BT Panel) 是一款 国产的服务器运维管理面板,主要用于简化 Linux/Windows 服务器的网站、数据库、FTP、防火墙等管理操作。它通过图形化界面(Web端)和命令行工具(bt 命令&a…

Linux平台下SSH 协议克隆Github远程仓库并配置密钥

目录 注意:先提前配置好SSH密钥,然后再git clone 1. 检查现有 SSH 密钥 2. 生成新的 SSH 密钥 3. 将 SSH 密钥添加到 ssh-agent 4. 将公钥添加到 GitHub 5. 测试 SSH 连接 6. 配置 Git 使用 SSH 注意:先提前配置好SSH密钥,然…

Java【网络原理】(5)深入浅出HTTPS:状态码与SSL/TLS加密全解析

目录 1.前言 2.正文 2.1状态码 2.2HTTP与HTTPS的关系 2.3SSL协议 2.3.1对称加密 2.3.2非对称加密 2.3.3中间人攻击 2.3.4校验机制 2.3.4.1证书 2.3.4.2数字签名 1. 数字签名的生成过程 2. 数字签名的验证过程 2.4TLS协议(握手过程) 3.小结…

【基础IO下】磁盘/软硬链接/动静态库

前言: 文件分为内存文件和磁盘文件。磁盘文件是一个特殊的存在,因为磁盘文件不属于冯诺依曼体系,而是位于专门的存储设备中。因此,磁盘文件存在的意义是将文件更好的存储起来,一边后续对文件进行访问。在高效存储磁盘…

SpringBoot项目容器化进行部署,meven的docker插件远程构建docker镜像

需求:将Spring Boot项目使用容器化进行部署 前提 默认其他环境,如mysql,redis等已经通过docker部署完毕, 这里只讨论,如何制作springboot项目的镜像 要将Spring Boot项目使用docker容器进行部署,就需要将Spring Boot项目构建成一个docker镜像 一、手动…

【小记】excel vlookup一对多匹配

一个学生报四门课,输出每个学生课程 应用概述操作预处理数据计数指令 COUNTIFS进行一对多匹配 vlookup 应用概述 应用场景:学生报名考试,需要整理成指定格式,发给考试院。 一个学生最多报考四门 格式实例:准考证号 …

LeetCode热题100 两数之和

目录 两数之和题目解析方法一暴力求解代码 方法二哈希代码 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 🐒🐒🐒 个人主页 🥸🥸🥸 C语言 🐿️🐿️🐿…

[春秋云镜] Brute4Road 仿真场景

文章目录 靶标介绍:知识点约束性委派攻击 外网redis主从复制base64提权 内网搭建代理wpcargo插件漏洞mssql弱口令SweetPotato提权远程桌面连接mimikatz抓取hash约束性委派攻击 参考文章 靶标介绍: Brute4Road是一套难度为中等的靶场环境,完成…