Python&SO——SIEM架构与集成平台
本文最后更新于 77 天前,其中的信息可能已经有所发展或是发生改变。

Last Updated on 2026-05-11 by MarsRain

SIEM

SIEM(Security Information and Event Management,安全信息和事件管理系统)是一种用于实时监控、检测和响应安全事件的综合安全解决方案。它结合了SIM(Security Information Management,安全信息管理)SEM(Security Event Management,安全事件管理)的功能,帮助组织管理海量日志数据、识别潜在威胁,并自动化响应流程。SIEM 系统广泛应用于企业安全运维中,尤其在检测异常登录、入侵行为等方面


核心架构

1、数据采集层

  • 从各个来源收集日志和时间数据
  • 支持多种协议,如Syslog、SNMP、API、文件传输等。采集器部署在数据源端或集中式服务器上,确保数据传输

机制

通常采用push-pull混合:

Push模式由数据源主动发送日志,适合实时性

Pull模式由SIEM服务器定期拉取,适合云环境

在异常登录场景,采集Windows Event Logs 或 Linux auth.log 时,需要处理日志轮转(log rotation)以避免数据丢失

缺点:数据量庞大,需要压缩传输和过滤无关日志。Python中,可以利用logging模块pywin32处理Windows日志

2、数据标准化与解析层

  • 把不同格式的原始日志转化为统一的结构,便于后续解析
  • 提取关键字段,如时间戳、IP地址、用户ID、事件类型等
  • 过滤噪声日志,进行数据清洗,防止系统过载

机制

由于日志格式多样化(.json、CEF、Syslog),解析用正则或解析器。提取字段后,添加元数据(如事件ID、严重度、频率)

这一层和分析关联层高度绑定,同时会牵扯到一个危险度高的潜在攻击——APT

没有经过标准化的日志无法关联,高频的事件报告可以和APT关联起来,防止后续APT渗透内网造成严重财产损失

Python实现:用regrok-py库解析,统一schema如(“timestamp”:“…”;“event_type”:”…”;),方便团队查看和辨认

3、存储与索引层

  • 使用数据库存储日志数据,支持快速查询和归档
  • 数据可以按照时间序列存储,并添加索引方便快速检索

4、分析与关联层——核心引擎

  • 可以接入大模型,利用规则引擎、进行机器学习或行为分析检测异常
  • 规则关联:将多次登录失败和异常IP访问关联起来,判定为暴力破解
  • 事实分析:设置监控阈值,短时间内登录失败连续超过五次自动发送警报
  • 高级SIEM集成UEBA(User and Entity Behavior Analytics,用户和实体行为分析)来检测异常模式

规则引擎

简单规则用if-then;复杂用CEP(Complex Event Processing)如Esper

CEP(Complex Event Processing)

概念

Complex Event Processing(复杂事件处理)是一种实时处理技术,它从多个事件流(event streams)中检测复杂模式时间相关性因果关系趋势,而不是只看单个事件。 它关注“事件的组合与时序”,能识别出简单规则引擎无法发现的高阶威胁

典型代表工具:Esper(开源 Java CEP 引擎)、Apache Flink CEP、Drools Fusion、IBM Operational Decision Manager 等

主要作用

  • 实时产生“复杂事件”(synthesized event),用于触发高级告警
  • 检测多事件关联的复杂场景(例如:5 分钟内 3 次失败登录 + 来自同一 IP 的端口扫描 + 异常文件访问)
  • 支持时间窗口(sliding window、tumbling window)、序列模式(A 后跟 B 但不跟 C)、聚合(平均、最大、最小)、否定模式(某段时间内没有发生某事件)

示例场景

用户 A 正常工作时间从东京登录,突然在凌晨从俄罗斯 IP 登录,且 2 分钟内尝试访问 10 个敏感服务器 → CEP 可以用一条 EPL(Event Processing Language)语句检测这种跨时间、跨来源的模式

关联示例:192.168.xxx.xxx在五分钟内登录失败超过10次+端口扫描=高危告警

ML集成

用 UEBA 检测异常(如用户平时从 US 登录,突然从 RU,需基线模型)

概念 UEBA = User and Entity Behavior Analytics(用户与实体行为分析)。 它利用机器学习(而非固定规则)为每个用户、主机、IP、应用等实体建立动态行为基线(baseline),然后持续监控当前行为与基线的偏离程度,检测异常

核心机制

  1. 学习阶段:收集历史数据(登录时间、地点、访问资源、操作频率等),用 ML(如聚类、Isolation Forest、Autoencoder、统计模型)构建“正常”画像
  2. 检测阶段:实时打分(risk score),偏离基线越远分数越高
  3. 动态更新:基线会随时间缓慢演化(例如用户换了工作地点)

主要作用

  • 发现未知威胁(zero-day、慢速 APT、低速数据窃取、内部威胁)
  • 弥补规则-based 检测的盲区(规则写不全所有可能攻击)
  • 典型异常示例:
    • 用户平时只在美国工作时间从公司 VPN 登录,突然从俄罗斯 IP 凌晨登录
    • 财务人员突然大量下载 HR 目录文件
    • 服务器平时只跑 Web 服务,突然启动挖矿进程

实例

用户平时 9:00–18:00 从东京 IP 登录公司邮箱,突然 03:00 从俄罗斯 IP 登录 → UEBA 会给该行为打高风险分,生成异常事件,供第 5 层告警。

5、告警与响应层

  • 生成告警通知,例如发送邮件、SMS、后台票务系统
  • 支持自动化响应,例如封禁IP或脚本利用
  • 提供可视化界面报告——连接仪表盘,展示事件、历史趋势并合成相关报告

机制

告警分级(高危/中危/低危/无风险),集成SOAR自动化响应

概念 SOAR = Security Orchestration, Automation and Response(安全编排、自动化与响应)。 它是一个流程自动化平台,把安全工具(SIEM、EDR、防火墙、票务系统、邮件等)串联起来,通过预定义的playbook(剧本)自动或半自动执行响应动作

典型代表工具

  • 开源:TheHive + Cortex(分析器)、Shuffle、Demisto(现 Palo Alto XSOAR 的前身开源部分)
  • 商用:Splunk SOAR、Swimlane、IBM Resilient、ServiceNow SecOps 等

主要作用

  • Response:提供标准化的响应流程,减少人为错误,提高响应速度
  • Orchestration:把分散工具连成工作流
  • Automation:自动执行重复、低价值动作(查 VirusTotal、封 IP、创建 Jira ticket、隔离主机)

示例场景(TheHive 集成) SIEM 检测到暴力破解 → 自动触发 Shuffle/TheHive playbook:

  1. 通知 Slack/邮件 + 创建工单
  2. 查 AbuseIPDB / VirusTotal 评分
  3. 如果分数高 → 自动创建 TheHive Case
  4. 自动调用 Cortex Analyzer 分析 IP
  5. 自动通过 API 让防火墙封禁 IP

集成

Python可调用外部API(Slack for通知、iptables for封禁)

6、管理与合规层

  • 配置规则、用户访问控制、审计日志
  • 确保符合法规,法规包括且不限于GDPR、HIPAA

工作机制

SIEM采用闭环流程的工作机制:

  1. 采集与传输:数据源生成日志,采集器推送或拉取数据到中央服务器
  2. 处理与分析:日志进入管道,经过分析、标准化后进入规则引擎
    • 触发规则匹配时间会识别事件
    • 触发相关联事件会提升优先级
  3. 检测异常:针对异常登录,机制包括:
    • 阈值检测:1分钟内3次登录失败
    • 地理位置检查:登录IP不匹配历史位置
    • 行为基线:接入大模型学习历史浏览行为,比对当前行为和历史行为差异
  4. 告警生成:一旦检测到威胁,生成事件票据(Ticket),通知安全团队。严重事件可触发SOAR(Security Orchestration, Automation and Response)自动化响应。
  5. 回顾和优化:通过forensic分析历史数据,优化检测,减少误报(False Positives)
graph TB
A((采集与传输))
B[处理与分析]
C[检测异常]
D[告警生成]
E((回顾和优化))
A--推送到服务器-->B
B--日志进入管道-->C
C--规则匹配、阈值检测、行为匹配-->D
D--生成票据,告知团队-->E
E--模型学习、分析历史-->A

Python模块示例

现假设需要开发一个模块来监控Linux系统下的/var/log/auth.log文件,实时采集日志,检测异常登录,并通过邮件发送告警

这个实例使用Python标准库和少量内置模块(如re用于解析、smtplib用于邮件)采用文件尾随(tailing)机制模拟实时采集(类似linux的tail -f命令),避免依赖外部库

代码示例:

import re
import time
import smtplib
from email.mime.text import MIMEText # 用于构建邮件内容
from collections import defaultdict # 用于存储登录失败的时间戳列表
from datetime import datetime, timedelta # 用于处理时间窗口

# 配置参数
LOG_FILE = '/var/log/auth.log'  # 替换为实际日志路径(需读权限)
ALERT_THRESHOLD = 3  # 失败登录阈值
TIME_WINDOW = timedelta(minutes=1)  # 时间窗口
SMTP_SERVER = 'smtp.example.com'  # 替换为你的 SMTP 服务器
SMTP_PORT = 587 # 替换为你的 SMTP 端口
SENDER_EMAIL = 'alert@example.com' # 替换为你的发送邮箱
SENDER_PASSWORD = 'your_password' # 替换为你的发送邮箱密码
RECIPIENT_EMAIL = 'admin@example.com' # 替换为你的接收邮箱

# 正则表达式解析 sshd 登录日志(示例:Failed password for user from IP)
FAILED_LOGIN_PATTERN = re.compile(r'Failed password for (\w+) from ([\d.]+) port \d+ ssh2')
SUCCESS_LOGIN_PATTERN = re.compile(r'Accepted password for (\w+) from ([\d.]+) port \d+ ssh2')

class LoginTracker: # 追踪登录失败的类
    def __init__(self):
        self.failures = defaultdict(list)  # IP -> list of failure timestamps

    def process_log_line(self, line):
        failed_match = FAILED_LOGIN_PATTERN.search(line)
        if failed_match: # 如果匹配到失败登录
            user, ip = failed_match.groups()
            now = datetime.now() # 当前时间
            self.failures[ip].append(now) # 记录失败时间
            # 清理过期记录
            self.failures[ip] = [t for t in self.failures[ip] if now - t < TIME_WINDOW] # 保留时间窗口内的记录
            # 检查阈值
            if len(self.failures[ip]) >= ALERT_THRESHOLD:
                self.send_alert(ip, user, len(self.failures[ip]))
                self.failures[ip] = []  # 重置计数以避免重复告警

        success_match = SUCCESS_LOGIN_PATTERN.search(line)
        if success_match:
            user, ip = success_match.groups()
            print(f"Successful login: User {user} from {ip}")

    def send_alert(self, ip, user, count): # 发送告警邮件
        msg = MIMEText(f"Abnormal login detected: {count} failed attempts for user {user} from IP {ip}") # 邮件内容
        msg['Subject'] = 'Security Alert: Abnormal Login'
        msg['From'] = SENDER_EMAIL # 邮件发送者
        msg['To'] = RECIPIENT_EMAIL # 邮件接收者

        try: # 连接 SMTP 服务器并发送邮件
            server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT) # 连接 SMTP 服务器
            server.starttls() # 启用 TLS
            server.login(SENDER_EMAIL, SENDER_PASSWORD) # 登录 SMTP 服务器
            server.sendmail(SENDER_EMAIL, RECIPIENT_EMAIL, msg.as_string())
            server.quit()
            print("Alert sent successfully") 
        except Exception as e:
            print(f"Failed to send alert: {e}")

def tail_log_file(file_path): # 实时读取日志文件
    with open(file_path, 'r') as f:
        # 移动到文件末尾
        f.seek(0, 2) 
        while True:
            line = f.readline()
            if not line:
                time.sleep(0.1)  # 轮询间隔
                continue
            yield line.strip() # 返回新行

# 主函数
if __name__ == '__main__':
    tracker = LoginTracker()
    print("Starting log monitoring...")
    for line in tail_log_file(LOG_FILE): # 处理每一行日志
        tracker.process_log_line(line) # 解析日志行并更新登录状态

Python代码片段示例

SIEM的核心架构通常被描述为分层管道(pipeline)式结构,从逻辑上看,六层架构每层实现的模块分别独立运行后交给下一层,经过闭环流程实现记录、统一、存储、分析、响应、优化。但从实际系统运行中,这些层都是高度并行、异步、流式处理,即同一时刻成千上万各事件在不同层、不同节点同时被处理。下面将针对各层单独用代码举例解释:

数据采集层(Data Collection / Ingestion)

负责从各种源头实时/批量拉取或接收日志,典型的实现方式有:

文件tail、Syslog UDP/TCP接收、Beats/Filebeat、API polling等

数据标准化与解析层(Normalization & Parsing)

把原始日志转化成同一结构,提取关键字段

典型实现方式:正则/Grok/CEF/JSON schema映射

存储与索引层(Storage & Indexing)

把解析后的事件存下来,支持快速检索。

典型实现方式:Elasticsearch、OpenSearch、ClickHouse、PostgreSQL + TimescaleDB、SQLite(原型)。

分析与关联层(Analysis & Correlation)

核心检测引擎:规则匹配、阈值、时间窗口关联、简单 ML。

典型实现方式:规则引擎(Sigma)、CEP、状态机、ML 异常检测。

告警与响应层(Alerting & Response)

产生告警、通知、自动化动作。

典型实现方式:邮件、Slack/Webhook、SOAR 脚本、防火墙 API。

展示、管理与合规层(Visualization, Management & Compliance)

仪表盘、查询、报告、用户权限、审计、归档。

典型实现方式:Kibana/ Grafana、自定义 Flask/Dash 界面、RBAC。

Security Onion(SO)

SO是一个开源的网络安全监控、威胁检测与日志分析平台,常用于企业安全运营中心(SOC)、入侵检测、威胁狩猎和应急响应场景。该平台整合了多种安全工具,帮助安全团队集中采集、分析和告警网络流量、主机日志以及安全事件。

主要功能

从SIEM的核心架构出发不难理解SO的主要功能和运作方式:

1. 网络流量监控

Security Onion 可以接入镜像流量,例如交换机 SPAN 口、TAP 设备等,对网络数据包进行分析。它可以发现:

  • 端口扫描
  • 漏洞利用行为
  • 恶意软件通信
  • C2 回连
  • 横向移动
  • 异常 DNS 请求
  • 可疑 HTTP/HTTPS 行为
  • 数据外传行为

2.入侵检测

Security Onion 支持基于规则的入侵检测。常见检测引擎包括:

  • Suricata
  • Zeek
  • Sigma
  • YARA,部分场景使用
  • Elastic 相关查询规则

其中:

  • Suricata 偏重于基于签名的网络入侵检测
  • Zeek 偏重于网络行为分析和协议日志解析

3.日志集中分析

Security Onion 可以收集来自多种来源的日志,例如:

  • Windows 事件日志
  • Linux 系统日志
  • 防火墙日志
  • VPN 日志
  • DNS 日志
  • 代理服务器日志
  • EDR 或杀毒软件日志
  • 云平台日志
  • 应用系统日志

4.威胁狩猎

安全分析师可以通过 Security Onion 的界面查询网络和主机活动。可以追踪:

  • 某个 IP 访问了哪些域名
  • 某个主机是否连接过恶意 IP
  • 某个账户是否存在异常登录
  • 某个文件哈希是否出现过
  • 某个内网主机是否存在扫描行为
  • 攻击者是否进行了横向移动

5.告警管理

  • 查看告警详情
  • 关联上下文信息
  • 标记事件状态
  • 进行调查分析
  • 将事件升级为 Case
  • 对误报进行规则调整

左侧和SIEM的告警管理部分很相似,这也是博主称之为“集成式开源安全监控与威胁狩猎平台”的原因

部署方式

部署SO的时候,需要确认部署的环境和配置的高低,避免选择错误的部署方式导致时间成本增加和加大服务器的负荷。

  • standalone单机部署适合单服务器下的实验环境中。这样做的优点就是部署简单,迅速,不需要繁琐的配置步骤,只需要按照默认配置来设置即可。
  • Distributed分布式部署适合中大型企业中的生成环境,加强生产环境的安全。缺点显而易见,但是优点也很显著:扩展能力强,可以随时根据实际情况调整传感器和存储节点的数量。
  • Sensor传感器部署一般用在关键网络位置,通过镜像流量来监控数据传输。常见的位置就有互联网出口、服务区核心、数据核心交换区等。

简单的使用流程

SO上手也很容易,一个典型流程如下:

  1. 在关键网络位置部署 Sensor
  2. 接入镜像流量
  3. 采集主机和设备日志
  4. Suricata 检测恶意流量
  5. Zeek 生成网络协议日志
  6. Elastic 存储和索引日志
  7. Security Onion Console 展示告警
  8. 分析人员调查事件
  9. 根据结果调整规则或封堵威胁

部署流程示例

注:由于SO的配置脚本,该脚本检测到网卡,会自动触发repo强同步。如果内网配置不当,会出现DNS解析失败,导致无法从官方仓库securityonion.net拉取配置。所以在内网环境部署的时候,建议选择Airgap闭网环境进行部署。

本次示例是在Proxmox Virtual Environment(PVE)中部署,具体的实际情况请参考内网中的备注。在此只简单地阐述步骤流程。

1.导入

https://github.com/Security-Onion-Solutions/securityonion获取iso镜像文件,导入PVE,开机后会自动开启配置界面。具体如下:

这是前面选择了standalone部署➡Airgap离线安装➡输入账户后的界面,贴在此处仅供参考

2.配置

此时在内网单服务器环境中,选择Airgap闭网环境安装。后续的IP配置选择内网同网段下的指定IP作为网页前端即可。中间有任何不动的地方可以截图询问LLM。一定要记住打好snapshot,方便回退。SO的安装流程即使是离线依然需要花费至少30分钟!!!!!

后台的账密和页面前端的账密都需要记录,以免后续忘记导致再次回退,甚至重新安装。

3.登录

访问指定的IP,登录后即可设置监控节点。

问题排查1:结合ssh判断问题方向

背景交代

问题1:网络阻隔

在PVE后台确认了SO在正常运作后,尝试从Windows端宿主机(IP:10.10.1.131)登录SO页面管理端(IP:172.16.11.141),页面一直处于加载状态,等待响应后页面报错:

问题2:握手失败

在后台查询流量和日志的时候,由于PVE控制台的显示设置,无法查询完整的日志行,打算通过mobaxterm远程ssh终端,此时新的问题出现:

切换Hexhub来尝试连接,报错为握手失败:

排查流程

初步推测可能为后台so-firewall未放行,尝试手动添加本机IP:10.10.1.131

sudo so-firewall include analyst 10.10.1.131/32
sudo so-firewall apply

reboot

重启后尝试抓包查看info细则,在PVE的SO终端开启服务,等待数据通过,分别利用MobaXterm和cmd远连SO终端,返回抓包结果

再次在Windows端访问页面,依然失败。在cmd查看流量走向,查询日志

curl -vk https://172.16.11.141

确认了问题1问题2的具体原因:虽然显示的是握手失败导致通信失效,但机器在TCP层能通过,说明具体问题极大概率出现在跨网路径问题上面。后面加上账密认证,强制连接ssh:

返回结果显示:Windows直连SO是出现:

kex_exchange_identification: Connection closed by remote host
Connection closed by 172.16.11.141 port 22

说明问题不是 MobaXterm或者Hexhub,而是 Windows 到 SO 的连接链路异常

再通过ssh失败,查看日志 /var/log/secure

SO /var/log/secure 里出现:

kex_exchange_identification: read: Connection reset by peer
Connection reset by 10.10.1.131

证明从SO视角看,是Windows侧或中间路径主动重置连接

在PVE开启一台kali,尝试登录https://172.16.11.141,发现能够正常访问

依照这个思路,通过Kali作为跳板访问SO:

结果显示成功。证明:高概率是 Windows 到 172.16.11.0/24 跨网段路径问题

问题汇总

根据上述的结果,目前可以确定的是:

  • Security Onion 正常
  • Kali 到 Security Onion 正常
  • Windows 到 Security Onion 的直连异常
  • 异常发生在 SSH/TLS 握手阶段
  • 不是账号、密码、SO 服务或单一客户端问题
  • 问题应集中在 Windows 侧网络栈或 Windows 到 172.16.11.0/24 的跨网段路径

目前Windows端无法跨网段登录SO网页管理端的问题先暂时按下不表,这个问题相对于实际投入使用暂时构不成太大影响。

问题排查2:后台抓包检测数据监控是否正常运作

背景交代

进入页面管理后台,在Hunt的界面能看到已经出现部分数据包的抓取,里面也有相关的描述。说明正常功能的一部分已经可以运行

Hunt里过滤特定的组件,查看指定组件是否运行正常

event.dataset:zeek.conn
event.category:network

以上操作和返回结果都证明SO中内部组件通信流量运行正常,后续开始验证外部主机流量监控,查看是否能捕获到Kali、Windows、其他靶机等实际流量。

初次验证

依次查看:

1、查看SO当前网卡

ip -br a

2、看Zeek/Suricata实际监听接口

# 执行前先查看组件容器的名称,可能会和官方文档或本博客有出入

sudo docker inspect so-zeek | grep -i interface -A3 -B3
sudo docker inspect so-suricata | grep -i interface -A3 -B3
sudo grep -R "interfaces" /opt/so/saltstack/local/ 2>/dev/null

3、用tcpdump验证接口有无目标流量

如果不确定管理接口,可以对设定的两个监控接口(enp6s18、enp6s19)都进行监听。

结合以上三点,可以画出大概的监控链路:

graph TD
A[Kali/靶机流量]
B[PVE虚拟交换]
C[没有镜像到SO的监控口enp6s19/bond0]
D[Zeek/Suricata看不到真实实验流量]
A-->B-->C-->D

初步判断:目前SO是在运行,但Suricata/Zeek监听bond0,但实际应该监听enp6s19,而且此时bond0是DOWN,导致enp6s19没有收到镜像流量,PVE也没有把目标流量镜像给SO

二次验证

新开一个靶机(IP:172.16.11.213),再次开启enp6s19的监控接口。通过Kali(IP:172.16.11.147)ping靶机,观察返回结果:

证据明确:返回结果显示能明确看到Kali和SO之间的SSH/HTTPS流量(从enp6s18接口出入的流量),但是enp6s19(应该有流量的监控接口)没收到镜像流量。也和之前SO监听接口配置出错有关

结论:PVE没有把目标流量镜像到SO的监控口enp6s19

解决记录

1.流量复制

在PVE root终端里确认tap名称

ip link | grep tap
#在PVE上开启SO监控tap的混杂模式
ip link set tap25041404i1 promisc on

#在SO上开启tap的混杂模式
sudo ip link enp6s19 promisc on

把Kali流量镜像到SO监控口,在PVE root上执行

tc qdisc add dev tap25041401i0 clsact
tc filter add dev tap25041401i0 ingress matchall action mirred egress mirror dev tap25041404i1
tc filter add dev tap25041401i0 egress matchall action mirred egress mirror dev tap25041404i1

在SO中执行验证:

sudo tcpdump -ni enp6s19

然后再Kali上访问靶机(IP:172.16.11.213)

ping 172.16.11.213

出现返回结果,并且里面同时包含了ssh(10.10.1.131 -> 172.16.11.147 -> 172.16.11.141)和ping包(172.16.11.147 -> 172.16.11.213),说明监控流量已经进入SO监控口

2.调整检测接口

之前查到Suricata监听的事bond0接口,而且处于DOWN,先尝试临时将enp6s19 加入 bond0

sudo ip link set enp6s19 down
sudo ip link set enp6s19 master bond0

报错:Invalid argument,说明当前不能把enp6s19加入bond0,其中可能的原因有多种:

  • bond0 的 bonding 模式/状态不允许这样加
  • enp6s19 还被 NetworkManager 管理
  • Security Onion 的 bond0 是安装时生成的特殊配置,无法二次配置

更换另一种方式:把SO监控接口从bond0改成enp6s19

先确认Zeek/Suricata监听配置

sudo grep -R "bond0" /opt/so/saltstack/local/ 2>/dev/null

从返回结果分析

  • bond007是Suricata规则内容里的恶意域名,可以忽略
  • 真正的接口配置是这一行:
    /opt/so/saltstack/local/pillar/minions/so-yxwa_standalone.sls: interface: 'bond0'

应用配置修改

# 备份文件
sudo cp /opt/so/saltstack/local/pillar/minions/so-yxwa_standalone.sls /opt/so/saltstack/local/pillar/minions/so-yxwa_standalone.sls.bak

sudo vi /opt/so/saltstack/local/pillar/minions/so-yxwa_standalone.sls
# 清楚原先容器配置残留
sudo grep -R "INTERFACE=bond0\|interface: 'bond0'\|bond0" /opt/so/ 2>/dev/null | grep -v all-rulesets

# 重新应用Salt配置
sudo salt-call state.highstate

# 重启SO
sudo reboot

# 再次验证
sudo docker inspect so-suricata | grep -i interface -A3 -B3

返回结果说明修改成功

开始抓包验证:

在SO上开启:

sudo tcpdump -ni enp6s19 host 172.16.11.213

Kali上产生流量:

curl http://172.16.11.213

Hunt查询:

destination.ip:172.16.11.213

返回结果为成功,但响应时间会有延迟,延迟几十秒到几分钟都正常。后续查询尽量用Last 15 minutes

3.添加新接口

结合先前的跨网段问题和上述两个解决方案推断出:Windows curl靶机是成功的,只是SO“没看到”,因为PVE镜像范围不包含这条流量,这也说明Windows 到靶机的流量没有被 PVE 镜像到 SO 的 enp6s19。原因也大概率是:之前只镜像了 Kali 的 tap 口,没有镜像靶机的 tap 口或 PVE 上承载 Windows 入站流量的接口。

方案1.单个靶场解决,手动添加新VM的tap

因为Windows 访问靶机,流量最终一定会进入靶机网卡。所以只要镜像靶机的 tap,SO 就能看到。

先在PVE root上找到靶机VMID

ip link | grep tap

找到靶场(172.16.11.213)对应的tap,并在PVE上给靶场tap加镜像

tc qdisc add dev tap25041402i0 clsact
tc filter add dev tap25041402i0 ingress matchall action mirred egress mirror dev tap25041404i1
tc filter add dev tap25041402i0 egress matchall action mirred egress mirror dev tap25041404i1

# 再测试
sudo tcpdump -ni enp6s19 host 172.16.11.213 //SO中操作

# Windows执行
curl http://172.16.11.213
方案2.直接接入PVE链接外部网络的bridge/uplink

在PVE root终端操作:

tc qdisc add dev vmbr0 clsact
tc filter add dev vmbr0 ingress matchall action mirred egress mirror dev tap25041404i1
tc filter add dev vmbr0 egress matchall action mirred egress mirror dev tap25041404i1

验证

# 在SO开启流量抓包
sudo tcpdump -ni enp6s19 host 172.16.11.213

# Windows端cmd
curl http://172.16.11.213
ping 172.16.11.147
通过脚本避免手工添加新VM的tap

当前SO监控口固定是:tap25041404i1,写一个脚本,自动把所有目标VM的tap镜像过去,在PVE root上创建:

#!/bin/bash

SO_TAP="tap25041404i1"

for IFACE in $(ip -o link show | awk -F': ' '{print $2}' | grep -E '^tap[0-9]+i0$'); do
    if [ "$IFACE" = "$SO_TAP" ]; then
        continue
    fi

    echo "[+] mirror $IFACE -> $SO_TAP"

    tc qdisc del dev "$IFACE" clsact 2>/dev/null
    tc qdisc add dev "$IFACE" clsact

    tc filter add dev "$IFACE" ingress matchall action mirred egress mirror dev "$SO_TAP"
    tc filter add dev "$IFACE" egress matchall action mirred egress mirror dev "$SO_TAP"
done

# 授权
chmod +x /root/so-mirror.sh

# 执行
/root/so-mirror.sh

以后新靶机开机后,重新跑一次脚本即可。

全自动优化

每次新的VM开启都需要重新跑脚本,那就设计一个新的自动化脚本:systemd 定时自动扫描,新 VM 开机后自动加镜像

# PVE root机创建脚本
nano /root/so-mirror-auto.sh

#!/bin/bash

SO_TAP="tap25041404i1"
SO_VMID="25041404"

# 确认 SO 监控 tap 存在
ip link show "$SO_TAP" >/dev/null 2>&1 || exit 0

# 开启 SO 监控 tap 混杂模式
ip link set "$SO_TAP" promisc on 2>/dev/null

for IFACE in $(ip -o link show | awk -F': ' '{print $2}' | grep -E '^tap[0-9]+i[0-9]+$'); do

    # 跳过 SO 自己的监控口
    if [ "$IFACE" = "$SO_TAP" ]; then
        continue
    fi

    # 跳过 SO VM 的所有网卡,避免自镜像导致重复/回环
    if echo "$IFACE" | grep -q "^tap${SO_VMID}i"; then
        continue
    fi

    # 如果已经存在 clsact,说明处理过,跳过
    tc qdisc show dev "$IFACE" | grep -q "clsact" && continue

    echo "[+] Add mirror: $IFACE -> $SO_TAP"

    tc qdisc add dev "$IFACE" clsact
    tc filter add dev "$IFACE" ingress matchall action mirred egress mirror dev "$SO_TAP"
    tc filter add dev "$IFACE" egress matchall action mirred egress mirror dev "$SO_TAP"
done

# 授权
chmod +x /root/sp-mirror-auto.sh

# 运行
/root/so-mirror-auto.sh
------------------------------------------分割线---------------------------------------------
# 创建systemd service
nano /etc/systemd/system/so-mirror-auto.service

# 在so-mirror-auto.service
[Unit]
Description=Auto mirror VM tap traffic to Security Onion

[Service]
Type=oneshot
ExecStart=/root/so-mirror-auto.sh
------------------------------------------分割线---------------------------------------------
# 创建systemd timer
nano /etc/systemd/system/so-mirror-auto.timer

# 在so-mirror-auto.timer中输入
[Unit]
Description=Run SO mirror auto script periodically

[Timer]
OnBootSec=30
OnUnitActiveSec=10
Unit=so-mirror-auto.service

[Install]
WantedBy=timers.target
------------------------------------------分割线---------------------------------------------
# 启用
systemctl daemon-reload
systemctl enable --now so-mirror-auto.timer

# 查看状态
systemctl status so-mirror-auto.timer

# 查看日志 
journalctl -u so-mirror-auto.service -f

问题排查3:回滚导致flow过期

背景交代

在重启so后,如果so无法正常启动,可能会回滚到之前的snapshot。在确认当前的环境无法修复后,确认需要回滚。回滚结束后,确认so在正常运作,重新登录网页前端会发现如下问题:

在清除浏览器内置的cookie缓存后,再次刷新页面依然出现如上图的情况。证明原因如上:

  • SO与Kali时间不一致
  • SO的认证容器so-kratos/so-sec/so-nginx状态异常
  • 浏览器cookie存储异常

解决记录

1.SO与Kali时间不一致问题

当前已确认cookie缓存已清除却仍然登不上去网页前端,着手在SO后端解决时间不一致问题。这里的“时间不一致”指的是:访问 Security Onion 的客户端时间 和 Security Onion 服务器时间 差距过大。具体的返回结果如下图所示:

SO

Kali

直接在SO上执行:

sudo timedatectl set-ntp false
sudo hwclock --hctosys
timedatectl

# 如果 hwclock --hctosys 不生效,手动设置
sudo timedatectl set-ntp false
sudo timedatectl set-time "2026-05-06 10:40:00"
sudo hwclock -w
timedatectl

# 确认时间变成当前显示的时间后再继续
sudo docker restart so-kratos so-nginx so-soc

完成上述操作后重新在Kali浏览器打开页面前端

后续维持

# 如果是Airgap环境,建议SO保持sudo timedatectl set-ntp false
# 每次快照回滚后检查
timedatectl
文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇