Suricata 介绍

Suricata 是一款强大的网络入侵检测和防御系统(NIDS/NIPS),且是开源的工具,拥有庞大的社区支持。suricata 支持对 HTTP 流量进行深度解析,包括抓取 HTTP 请求和响应的报头信息。除 http 流量外,suricata 还能解析多种协议如 ssh、ftp、dns、tcp等常见的通信协议。因此,使用 suricata 来捕获服务器的流量能够十分方便安全人员对流量进行审计分析。

问题解决

suricata 默认不会对 http 事件类型的流量输出请求体与响应体,则会让溯源工作缺失许多重要的信息。因此,本文重点解决 suricata 对 body 的解析与输出。

image-20251030113914302

首先打开 suricata.yaml 配置,修改 output -> eve-log -> http 的配置,配置记录 body(没有则直接新增,这段配置适配版本 suricata 7.x,怕出错请先备份 suricata.yaml)

outputs:
  - eve-log:
      types:
        - http:
            extended: yes     
            request-body: yes           # 记录请求体(POST/PUT 内容)
            response-body: yes          # 记录响应体(返回的 JSON/HTML 等)
            request-body-limit: 10KB    # 单个请求体最多记 10 kB(按需改)
            response-body-limit: 10KB   # 单个响应体最多记 10 kB(按需改)
            dump-all-headers: both

app-layer:
  # error-policy: ignore
  protocols:
         http:
           enabled: yes
           decompress-body: yes
      # 強制把 chunked body 重組
           response-body-chunked: yes
           request-body-chunked: yes
           http-body-minimal-inspect-percentage: 1
           http-body-fingerprint-limit: 50mb
           libhtp:
              default-config:
                personality: IDS
                request-body-limit: 10mb
                response-body-limit: 10mb

                request-body-minimal-inspect-size: 32kb
                request-body-inspect-window: 4kb
                response-body-minimal-inspect-size: 40kb
                response-body-inspect-window: 16kb
                # response body decompression (0 disables)
                response-body-decompress-layer-limit: 2
                # auto will use http-body-inline mode in IPS mode, yes or no set it statically
                http-body-inline: auto

然后需要修改一下源码,找到 suricata 项目目录下的 src 目录,然后修改 output-json-http.c 文件。

先备份 cp output-json-http.c output-json-http.c.bak

image-20251030114110854

新增一个函数,放到 static void EveHttpLogJSONBasic 函数之前(这段函数会处理 body 字段并确保对中文 utf-8 编码不会乱码)

/*自写的保留中文的函数*/
static void BodyUtf8String(JsonBuilder *js, Flow *f, uint64_t tx_id, const char *key)
{
    HtpState *htp_state = (HtpState *)FlowGetAppState(f);
    if (htp_state) {
        htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, htp_state, tx_id);
        if (tx) {
            HtpTxUserData *htud = (HtpTxUserData *)htp_tx_get_user_data(tx);
            if (htud) {
                HtpBody *body = NULL;
                if (strcmp(key, "http_request_body") == 0)
                    body = &htud->request_body;
                else if (strcmp(key, "http_response_body") == 0)
                    body = &htud->response_body;

                if (body && body->sb) {
                    const uint8_t *data;
                    uint32_t data_len;
                    uint64_t offset;
                    if (StreamingBufferGetData(body->sb, &data, &data_len, &offset) == 0)
                        return;

                    /* 直接当 UTF-8 字符串写,不转义中文 */
                    jb_set_string_from_bytes(js, key, data, data_len);
                }
            }
        }
    }
}

然后找到 static int JsonHttpLogger 函数,在 EveHttpLogJSON(jhl, js, tx, tx_id);后面新增两个函数调用,用来打印请求body与响应body

BodyUtf8String(js, f, tx_id, "http_request_body");
BodyUtf8String(js, f, tx_id, "http_response_body");

image-20251030114217906

准备事项完成后,重新编译安装 suricata

# 在suricata源码目录下
make -j$(nproc)
sudo make install
sudo systemctl restart suricata

然后尝试查看 eve.log 的 http 日志,现在有明文的响应体与请求体了,且不会中文乱码。

image-20251030114305316