====================== 与Snort的差异 ======================

本文档旨在重点介绍Suricata与Snort在规则及规则编写方面的主要区别。

若无特别说明,以下描述均针对Suricata。一般情况下,对Snort的引用特指2.9版本分支。

10.51. 自动协议检测

  • Suricata自动检测以下应用层协议:

    • dcerpc

    • dnp3

    • dns

    • http

    • imap(默认仅检测;不解析)

    • pop3(默认仅检测;不解析)

    • ftp

    • modbus(默认禁用;最小化探测解析器;可能导致误报)

    • smb

    • smb2(引擎内部默认禁用)

    • smtp

    • ssh

    • tls(支持SSLv2、SSLv3、TLSv1、TLSv1.1和TLSv1.2)

  • 在Suricata中,协议检测通常与端口无关(多数情况下)。而Snort需要通过配置端口才能使 http_inspect 等预处理器生效。

    • Suricata的yaml配置中,某些应用层协议默认会指定特定目标端口(如DNS)

    • 可在任意端口检测流量,无需担心Snort中可能存在的性能影响

  • 若流量被Suricata识别为HTTP,无论规则中指定何种端口,http_* 缓冲区都会被填充并可用。

  • 使用 http_* 缓冲区时不必显式检查HTTP协议(即 alert http ...),但仍建议这样做。

  • 若需检测合法(支持的)应用层协议流量且不限定特定端口,规则应写为 alert <协议> ... 并将端口设为 any。例如检测HTTP流量且不限端口时:

    Snort规则示例:

    alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS ...
    

    Suricata对应写法:

    alert http $HOME_NET -> $EXTERNAL_NET any ...
    

    或:

    alert tcp $HOME_NET any -> $EXTERNAL_NET any (app-layer-protocol:http; ...
    

10.52. urilen 关键字

  • urilen 的范围界定: - Snort为闭区间(包含边界值) - Suricata为开区间(不包含边界值)

    示例:urilen:2<>10 - Snort解释:"URI长度≥2且≤10" - Suricata解释:"URI长度>2且<10"

  • Suricata 默认作用于**标准化**缓冲区 - 使用 ,raw 指定原始缓冲区 - 如:urilen:>20,raw;

  • Snort 默认作用于**原始**缓冲区 - 使用 ,norm 指定标准化缓冲区 - 如:urilen:>20,norm;

10.53. http_uri 缓冲区

10.54. http_header 缓冲区

  • 结尾差异: - Snort的 http_header 包含分隔HTTP头与体的CRLF CRLF(0x0D 0x0A 0x0D 0x0A) - Suricata仅包含最后一个头的CRLF - 需匹配缓冲区末尾时,建议使用 http_raw_header、相对 isdataat``(如 ``isdataat:!1,relative)或PCRE(性能较差)

  • Suricata的 http_raw_header 会像Snort一样包含CRLF CRLF结尾

  • 头部差异: - Snort在服务端响应的 http_header 中包含*前导*CRLF(客户端请求无此行为) - Suricata在请求/响应的 http_header 中均不包含前导CRLF

  • 标准化差异: - Suricata会规范化HTTP头行,确保冒号(':')后只保留一个空格(0x20) - Snort仅当冒号后存在空格(非制表符)时才进行规范化

  • 重复头处理: - 标准化缓冲区(http_header)会按顺序用", "连接重复头的值 - 示例请求:

    GET /test.html HTTP/1.1
    Content-Length: 44
    Accept: */*
    Content-Length: 55
    
    • http_header 中的结果:

      Content-Length: 44, 55
      
  • Cookie头特殊处理: - http_header 不包含'Cookie'和'Set-Cookie'头(移至 http_cookie 缓冲区) - http_raw_header 仍包含这些头 - Snort启用 enable_cookie 时会保留头名称和CRLF

  • 其他HTTP专用缓冲区(如 http_user_agenthttp_host)不会被移除

  • 服务端响应检测时,http_* 缓冲区的匹配应置于 file_data 之前,除非使用 pkt_data 重置指针

10.56. 新增HTTP关键字

Suricata支持Snort不具备的HTTP关键字,如 http_user_agenthttp_hosthttp_content_type

完整列表见 HTTP 关键词

10.57. byte_extract 关键字

  • Suricata支持从 http_* 缓冲区(含 http_header)提取字节(Snort中可能异常)

  • 提取的变量必须在同一缓冲区使用,否则值为0(Snort允许跨缓冲区使用)

  • 建议对使用 byte_extractbyte_test 的规则进行正反测试

10.58. byte_jump 关键字

  • 允许使用 byte_extractbyte_math 的变量作为 nbytes

10.59. byte_math 关键字

  • 支持 dce 作为字节序值或独立关键字(等效于 endian dce

  • 拒绝单条规则中重复的关键字(如 byte_math: endian big, endian little

  • 接受 rvalue 值为0至uint32最大值(Snort拒绝0值)

  • 除数为0时永不匹配

10.60. byte_test 关键字

  • 允许使用 byte_extract 变量作为 nbytes

10.61. isdataat 关键字

  • rawbytes 语法支持但无效

  • 绝对检查:偏移量小于检测缓冲区大小时成功(与Snort相同)

  • 相对检查差异: - Suricata:偏移量≤缓冲区大小时成功 - Snort:偏移量<缓冲区大小时成功 - 示例(匹配末尾无数据):

    • Snort:isdataat:!0,relative;

    • Suricata:isdataat:!1,relative;

  • 检测缓冲区范围: - Snort通常检查数据包/分段(某些预处理器例外) - Suricata绝对检查针对数据包/重组流 - Suricata相对检查基于前次内容匹配的缓冲区

  • 示例规则(匹配URI末尾".exe"):

    alert http $HOME_NET any -> $EXTERNAL_NET any (msg:".EXE File Download Request"; flow:established,to_server; content:"GET"; http_method; content:".exe"; http_uri; isdataat:!1,relative; priority:3; sid:18332111;)
    

10.62. 相对PCRE

  • Suricata支持在标准化缓冲区中使用相对PCRE(如 content:".php?sign="; http_uri; pcre:"/^[a-zA-Z0-9]{8}$/UR";

  • Snort不允许将相对选项('R')与其他缓冲区选项(如'U')组合使用

10.63. tls* 关键字

除TLS协议识别外,Suricata还支持: - 证书磁盘存储 - 证书有效期验证 - SHA1指纹匹配 - 证书字段匹配(包括版本、Subject、Issuer、SNI等)

详见 SSL/TLS 关键词

10.64. dns_query 关键字

  • 设置检测指针至DNS查询(类似 file_data 的"粘性缓冲区")

  • 使用 pkt_data 重置指针

  • 详见 DNS 关键词

10.65. IP信誉与 iprep 关键字

10.66. Flowbits

10.67. flowbits:noalert;

  • Suricata中 noalert;flowbits:noalert; 等效

10.68. 否定内容匹配特例

  • Snort中,当检测起始点超出缓冲区时,否定内容匹配永不返回真 - 示例HTTP请求:

    POST /test.php HTTP/1.1
    Content-Length: 9
    
    user=suri
    
    • 此规则片段在Snort中永不匹配,Suricata正常匹配:

      content:!"snort"; offset:10; http_client_body;
      

10.69. 文件提取

10.70. Lua脚本

  • 通过 lua 关键字调用脚本访问数据包/负载/HTTP缓冲区等

  • 提供Snort不具备的灵活能力

  • 详见 lua-detection

10.71. 快速模式

  • 差异要点: - Suricata默认区分大小写(除非设置nocase) - Suricata不自动截断快速模式(Snort受 max-pattern-len 限制) - Suricata允许所有 http_* 缓冲区用于快速模式 - fast_pattern:only 语法支持但实际忽略 - Hyperscan算法可显著提升性能

  • 详见 Suricata 快速模式匹配机制详解fast_pattern

10.72. 流检测限制

  • Suricata严格区分数据包级(如 dsizeflags)和流级(如 http_*)关键字

  • 特殊协议值: - tcp-pkt:仅检测TCP包 - tcp-stream:仅检测重组流

  • Snort对此限制较宽松

10.73. 警报生成

  • Snort通过 event_queue 限制每包/流的警报数

  • Suricata内置硬限制为15条警报(不可配置)

10.74. 缓冲区参考表

(完整表格内容请参照原文格式,此处从略)