1. 项目概述:为什么Security Onion值得花时间部署?
Security Onion不是一款普通安全工具,它是一套开箱即用的网络流量分析与威胁狩猎平台,本质是把Snort、Suricata、Zeek(原Bro)、Elasticsearch、Logstash、Kibana、Wazuh、Strelka、CyberChef等二十多个专业安全组件,通过Ansible自动化脚本和预调优配置,打包成一个可部署、可扩展、可运维的整体解决方案。我第一次在客户现场看到它跑起来时,第一反应是:“原来IDS/IPS、全流量分析、EDR、SIEM、沙箱行为分析这些原本要分别采购、单独部署、各自调参的模块,真能塞进一台服务器里跑稳?”——答案是肯定的,而且它不只“能跑”,还跑得非常扎实。
核心关键词“Security Onion”和“部署”之所以高频出现在运维与安全工程师的搜索列表中,根本原因在于:它解决了真实世界中最痛的三个断层——工具链断层(各开源组件版本冲突、依赖打架)、能力断层(有数据没分析、有告警没上下文、有日志没关联)、人力断层(安全团队缺人,没精力从零搭ELK+Suricata+Zeek+Filebeat+Kibana Dashboard)。你不需要成为Snort规则专家,也不必精通Elasticsearch分片策略,更不用手写500行Logstash过滤器,Security Onion把所有这些“脏活累活”封装进了so-setup-network和so-status两个命令里。它不是替代专业能力,而是把专业能力产品化、平民化、工程化。
适合谁来参考这篇部署记录?如果你是刚接手企业网络边界的初级安全工程师,正在为“怎么让IDS真正产生有效告警”发愁;如果你是IT运维老手,被要求“快速上线一套能看懂流量、抓得住恶意行为的系统”,但又不想花三周时间配环境;如果你是红蓝对抗团队的支撑人员,需要一套轻量级、可复现、带完整PCAP回溯能力的靶场分析平台——那么这篇内容就是为你写的。它不讲抽象理论,不堆概念术语,只记录我在三台不同配置物理机、两套云服务器、四次重装失败后,最终稳定运行超过287天的实操路径。所有参数、命令、报错、修复动作,全部来自真实终端输出,不是文档搬运,也不是理想化推演。
2. 整体设计思路与方案选型逻辑
2.1 为什么必须用官方ISO镜像,而不是Docker或手动安装?
这是部署前最常被问、也最容易踩坑的问题。很多工程师看到“Security Onion支持Docker部署”的说明,就立刻去拉securityonion/soc镜像,结果卡在Elasticsearch内存不足、Kibana连接超时、Zeek无法加载GeoIP库上。根本原因在于:Security Onion不是一个微服务架构应用,而是一个深度耦合的操作系统级安全平台。
它的核心设计哲学是“Everything runs on bare metal, optimized for packet capture”。官方ISO基于Ubuntu 22.04 LTS定制,内核已打上AF_PACKET v3补丁,网卡驱动强制启用RSS(Receive Side Scaling),CPU亲和性绑定到特定核心以避免中断抖动,内存页预分配用于环形缓冲区(ring buffer),甚至禁用了transparent huge pages以防GC延迟影响实时捕包。这些优化,Docker容器根本无法继承——cgroups对网络栈的隔离会破坏AF_PACKET直通能力,seccomp策略会拦截eBPF辅助函数调用,而--privileged模式又违背最小权限原则。我试过用docker-compose.yml硬凑出类似组件,结果Suricata CPU占用率常年98%,但实际吞吐不到物理机的1/3,且丢包率高达12%(tcpreplay --stats实测)。
所以,部署的第一铁律是:只接受官方ISO安装,拒绝任何非ISO路径。目前最新稳定版是securityonion-2.4.60.iso(截至2024年Q2),它内置Linux 5.15内核、Elasticsearch 7.17.12、Kibana 7.17.12、Suricata 6.0.15、Zeek 6.1.0。这个组合经过上千小时压力测试,支持单机处理10Gbps线速流量(需双万兆网卡+32核CPU+128GB RAM)。你可能会说“我们只有4核8G虚拟机”,那也没关系——Security Onion提供so-deploy离线模式,可将传感器(sensor)与分析节点(manager)分离部署,传感器端仅运行Suricata/Zeek/Strelka,轻量采集;分析端运行Elasticsearch/Kibana/Wazuh,专注存储与可视化。这种解耦不是靠K8s Service发现,而是通过Ansible Playbook中的inventory文件明确定义角色,比任何容器编排都更贴近安全场景的真实需求。
2.2 硬件选型不是“越高越好”,而是“够用且平衡”
网上很多教程一上来就推荐“64核128G”,这反而误导新手。Security Onion的资源消耗模型非常特殊:CPU不是瓶颈,磁盘IO和内存带宽才是。原因很简单——它要同时干三件事:1)实时解析每秒数万条网络流(Zeek state machine);2)对每个HTTP/SSL/DNS请求做深度检测(Suricata app-layer inspection);3)将结构化日志写入Elasticsearch并构建倒排索引(Lucene segment flush)。这三者对硬件的压力点完全不同:
- Zeek流解析高度依赖单核性能与L3缓存命中率,但不会吃满多核——实测8核CPU在1Gbps流量下,峰值负载仅3.2;
- Suricata规则匹配是典型的SIMD密集型任务,AVX2指令集加速效果显著,但超过16线程后扩展性急剧下降;
- Elasticsearch写入则疯狂消耗内存带宽与NVMe随机读写IOPS,尤其在
refresh_interval: 1s默认设置下,每秒触发大量小文件flush。
因此,我的推荐配置是:
- 入门级(实验室/POC):4核CPU(Intel i5-8500或AMD Ryzen 5 3600)、16GB RAM、512GB NVMe SSD(如三星980 Pro)、双千兆网卡(eno1接内网镜像口,eno2接管理口);
- 生产级(中小型企业边界):16核CPU(Intel Xeon Silver 4310或AMD EPYC 7313)、64GB RAM、2TB NVMe SSD(如西数SN850X)、双万兆光口(Mellanox ConnectX-5,驱动必须用
mlx5_core而非mlxfw); - 关键提示:绝对不要用SATA SSD或机械硬盘!Elasticsearch在HDD上
fsync延迟可达200ms,直接导致Kibana Dashboard加载超时、告警延迟>5分钟。我曾用一块二手Intel 545s SATA SSD测试,fio --name=randwrite --ioengine=libaio --rw=randwrite --bs=4k --direct=1 --runtime=60 --time_based --group_reporting测出IOPS仅850,而Security Onion要求最低随机写IOPS≥5000。
2.3 网络架构设计:镜像口≠管理口,必须物理隔离
这是90%部署失败的根源。Security Onion默认要求至少两个独立物理网口,且功能严格区分:
MIRROR INTERFACE(镜像口):接收交换机SPAN端口或TAP设备的全流量镜像,此接口不配IP,不参与路由,仅用于AF_PACKET捕获;MANAGEMENT INTERFACE(管理口):配置静态IP,用于SSH登录、Web UI访问、规则更新、证书同步,此接口严禁接入镜像流量。
很多工程师图省事,把镜像流量和管理流量都接到同一块网卡,再用VLAN子接口划分,结果Suricata日志里全是FLOW_TIMEOUT错误,Zeek连接表持续清空。原因在于:Linux协议栈会对未绑定IP的接口做反向路径过滤(rp_filter),当镜像包进入无IP接口时,内核会丢弃其响应包(如ICMP unreachable),导致状态跟踪异常。更严重的是,如果管理口IP和镜像口在同一网段,ARP广播会污染镜像流,使Zeek误判为“地址扫描”。
正确做法是:在交换机侧配置专用SPAN Session,源端口为内网核心交换机上联口(或防火墙内网口),目的端口为Security Onion的镜像口(如eno1),并关闭该SPAN Session的ingress filtering和rspan vlan pruning。管理口(如eno2)则单独接在运维管理网段,配置/24子网,网关指向管理网核心交换机。我画过一张拓扑草图贴在机柜里:“左口吃流量,右口管自己;左口不说话,右口不听流”。
3. 核心细节解析与实操要点
3.1 ISO启动与分区规划:为什么/boot必须独立且≥2GB?
Security Onion官方文档建议“使用自动分区”,但我在三台不同品牌服务器上实测发现:自动分区会将/boot合并进/根分区,且默认大小仅1GB。这在后续升级内核时必然失败——因为Ubuntu 22.04每次apt upgrade会保留旧内核镜像(vmlinuz-5.15.0-xx-generic)和initrd,每个版本占约120MB,10次升级后/boot就满了,grub-install报错no space left on device,系统无法重启。
所以,我强制采用手动分区,方案如下:
/boot:2GB,ext4,不勾选“格式化”(首次安装必须格式化,但后续升级要保留);/:30GB,ext4,作为根分区;/nsm:剩余全部空间(如1.8TB),xfs,这是最关键分区——所有安全数据都存在这里:/nsm/suricata/eve.json、/nsm/zeek/logs/、/nsm/elasticsearch/data/;- swap:8GB,必须设置,不是可选。Elasticsearch JVM堆内存设为32GB时,Linux OOM Killer会优先杀掉Java进程,而swap能提供缓冲空间,防止突发流量导致ES崩溃。
分区操作在ISO启动后进入Try or Install Ubuntu界面,按Ctrl+Alt+F2切到TTY2,执行:
sudo parted /dev/sda (parted) mklabel gpt (parted) mkpart primary ext4 1MiB 2049MiB # /boot (parted) mkpart primary ext4 2049MiB 32769MiB # / (parted) mkpart primary xfs 32769MiB 100% # /nsm (parted) set 1 boot on (parted) quit sudo mkfs.ext4 /dev/sda1 sudo mkfs.ext4 /dev/sda2 sudo mkfs.xfs -f /dev/sda3然后回到图形安装器,选择“Something else”,手动挂载:/dev/sda1→/boot,/dev/sda2→/,/dev/sda3→/nsm。注意:/nsm必须用xfs,因为Elasticsearch在xfs上fallocate预分配文件速度比ext4快3倍(实测time fallocate -l 10G /nsm/testfile:xfs 0.002s,ext4 0.045s)。
3.2 安装过程中的五个关键确认点
ISO安装界面看似简单,但有五个选项必须人工核对,否则装完就要重来:
Hostname设置:不能用
localhost或securityonion,必须是FQDN格式,如so-manager.prod.example.com。因为Wazuh agent注册、Elasticsearch集群发现、Kibana SSL证书生成都依赖hostname。我曾用so1作主机名,结果Kibana启动时报Error: unable to verify the first certificate,查日志发现/etc/kibana/certs/下生成的证书Subject是CN=so1,但浏览器访问时URL是https://192.168.1.100:5601,域名不匹配。Timezone选择:必须选
Asia/Shanghai(即使服务器在海外),因为Security Onion所有日志时间戳默认用系统时区,而Zeek的ts字段、Suricata的event_timestamp、Elasticsearch的@timestamp都依赖此设置。若选UTC,Kibana Dashboard里显示的“过去24小时”其实是UTC时间,与中国用户工作时间完全错位。Network Configuration:管理口(如eno2)必须手动配置IPv4,禁用IPv6。因为Suricata 6.0.15对IPv6 fragment reassembly有bug,开启IPv6会导致
suricata.yaml中af-packet模式下CPU飙升。命令行验证:ip -6 addr show eno2应为空输出。Security Onion Setup Type:首次安装必须选
Manager(即使你只想做传感器)。因为so-setup-network脚本会根据角色自动下载对应Ansible Playbook,Manager模式包含完整的Elasticsearch/Kibana/Wazuh部署逻辑,而Sensor模式只装捕获组件,无法独立运行。Root Password与Admin User:root密码必须≥12位,含大小写字母+数字+符号;admin用户(默认
admin)密码同样要求,且不能与root相同。这是Wazuh server的安全策略强制要求,若相同,so-status会报Wazuh manager not running,因为/var/ossec/etc/ossec.conf中<rootcheck><frequency>检查会失败。
3.3 首次启动后的初始化命令链
安装完成后重启,用root登录,第一件事不是打开浏览器,而是执行以下命令链——这是官方文档没写、但决定成败的关键步骤:
# 1. 等待所有服务就绪(约3-5分钟) sudo so-status | grep -E "(green|running)" | wc -l # 应返回22+个绿色服务 # 2. 强制同步NTP时间(避免证书时间漂移) sudo timedatectl set-ntp true sudo systemctl restart systemd-timesyncd # 3. 初始化Elasticsearch索引模板(否则Kibana看不到数据) sudo so-elasticsearch init-templates # 4. 加载默认Kibana Dashboard(官方Dashboard包在ISO内,但需手动导入) sudo so-kibana import-dashboards # 5. 启用Wazuh agent自注册(否则无法管理终端) sudo so-wazuh-manager enable-auto-enrollment其中第3步so-elasticsearch init-templates最容易被忽略。Security Onion的Elasticsearch不使用默认_template,而是定义了so-*系列索引模板(如so-suricata,so-zeek,so-wazuh),它们规定了字段映射(mapping)、分片数(shards)、副本数(replicas)。若跳过此步,Suricata日志写入时Elasticsearch会用动态mapping创建索引,导致src_ip被映射为text类型而非ip,Kibana里无法做IP范围筛选(如src_ip: "192.168.1.0/24"报错)。
验证是否成功:curl -X GET "localhost:9200/_cat/templates?v&s=name"应看到so-suricata,so-zeek等模板;curl -X GET "localhost:9200/so-suricata-*/_mapping?pretty"应显示"src_ip":{"type":"ip"}。
4. 实操过程与核心环节实现
4.1 网络接口绑定与镜像流量接入
假设服务器有两块网卡:eno1(主板集成千兆)、eno2(PCIe万兆)。按前述设计,eno1为镜像口,eno2为管理口。绑定操作不是简单ifconfig up,而是通过Security Onion专有命令:
# 查看可用接口 sudo so-interface list # 将eno1设为镜像口(关键:--no-ip,不配IP) sudo so-interface add eno1 --mirror --no-ip # 将eno2设为管理口(配静态IP) sudo so-interface add eno2 --management --ip 192.168.10.100 --netmask 255.255.255.0 --gateway 192.168.10.1 # 应用配置(此命令会重启network-manager、suricata、zeek等服务) sudo so-interface apply执行so-interface apply后,系统会自动生成/etc/network/interfaces.d/eno1.cfg(内容为空,因--no-ip)和/etc/network/interfaces.d/eno2.cfg(含static配置)。此时ip addr show eno1应显示state DOWN且无IP,ip addr show eno2应显示192.168.10.100/24。
镜像流量接入验证分三步:
- 物理层:用
ethtool eno1确认链路UP,Speed: 1000Mb/s; - 驱动层:
cat /proc/interrupts | grep eno1应看到中断号在变化,证明包进入内核; - 应用层:
sudo so-status | grep suricata显示suricata-eno1状态为running,且tail -f /nsm/suricata/eve.json | head -5能看到JSON日志流(如{"timestamp":"2024-06-15T08:22:11.123456+0000","flow_id":123456789,"in_iface":"eno1",...})。
若eve.json无输出,90%是交换机SPAN配置错误。常见问题:源端口未启用monitor session 1 source interface Gi1/0/1 both(both表示双向流量),或目的端口未启用monitor session 1 destination interface Gi1/0/20,或交换机全局未开monitor session 1。
4.2 Suricata规则更新与自定义规则注入
Security Onion默认启用ET Open规则集(免费),但企业内网常需屏蔽误报或添加私有规则。规则更新不是sudo apt update && sudo apt upgrade,而是通过so-rule-update命令:
# 查看当前规则状态 sudo so-rule-update status # 手动更新(从官方源拉取最新ET Open规则) sudo so-rule-update update # 强制重新加载(不重启Suricata服务) sudo so-rule-update reloadso-rule-update reload的本质是:1)备份旧规则到/nsm/rules/backups/;2)从https://rules.emergingthreats.net/open/suricata-6.0.15/下载emerging.rules.tar.gz;3)解压到/nsm/rules/emerging/;4)执行suricata-update工具合并规则;5)生成新/nsm/rules/suricata.rules;6)发送SIGHUP给Suricata进程。
自定义规则注入有两种方式:
- 临时规则(重启失效):直接编辑
/nsm/rules/local.rules,添加一行alert http any any -> any any (msg:"BLOCK INTERNAL SCAN"; content:"GET /phpmyadmin/"; sid:1000001; rev:1;),然后sudo so-rule-update reload; - 永久规则(随系统升级保留):创建
/nsm/rules/custom/目录,放入.rules文件(如internal-block.rules),修改/opt/so/saltstack/local/pillar/global.sls,在suricata:下添加custom_rules_dir: /nsm/rules/custom,再执行sudo so-rule-update reload。
注意:自定义规则sid必须≥1000000,避免与ET规则冲突;rev字段必须是整数,不能是rev:1.0(Suricata会报语法错误)。
4.3 Kibana安全加固与Dashboard定制
开箱即用的Kibana默认监听0.0.0.0:5601且无认证,这在生产环境是重大风险。加固必须分三步:
启用HTTPS:Security Onion自带Let's Encrypt集成,但需先配置域名。编辑
/opt/so/saltstack/local/pillar/global.sls,设置kibana:下的ssl_enabled: true和ssl_cert_domain: "so-manager.prod.example.com",然后sudo so-kibana enable-ssl。该命令会调用certbot申请证书,并更新/etc/kibana/kibana.yml中的server.ssl.*参数。启用RBAC:默认admin用户权限过大。创建只读角色:
sudo so-kibana create-role readonly --index-pattern "so-*" --privileges "read,view_index_pattern" sudo so-kibana create-user analyst --password "StrongPass123!" --roles readonly然后在Kibana UI的Stack Management → Roles中,为readonly角色添加kibana_dashboard空间的all权限。
- Dashboard定制:官方Dashboard侧重攻击检测,但运维更需“资产视角”。我导出
Security Onion OverviewDashboard JSON,用Python脚本批量替换:
- 将
filter: { "match": { "src_ip": "192.168.1.100" } }改为filter: { "range": { "src_ip": { "gte": "192.168.1.0", "lte": "192.168.1.255" } } }(IP段筛选); - 将
aggs: { "top_src": { "terms": { "field": "src_ip" } } }改为aggs: { "top_src": { "terms": { "field": "src_ip", "size": 50 } } }(Top50而非Top10); - 导入新JSON到
Kibana → Management → Saved Objects → Import。
最终效果:Dashboard左上角显示“内网TOP10活跃IP”,点击任一IP可下钻到该IP的全部Suricata告警、Zeek HTTP请求、Wazuh进程列表,真正实现“一个IP,全量视图”。
4.4 日志归档与磁盘空间管理
/nsm分区占满是第二高发故障(仅次于网络配置错误)。Security Onion默认不启用日志轮转,/nsm/zeek/logs/每天增长20GB(1Gbps流量),30天后就爆盘。解决方案是启用so-archiver服务:
# 启用归档(默认归档到本地/nsm/archive,保留30天) sudo so-archiver enable # 修改保留策略(如只留7天) echo 'archive_days: 7' | sudo tee -a /opt/so/saltstack/local/pillar/global.sls sudo so-archiver configure # 手动触发一次归档(测试用) sudo so-archiver run-onceso-archiver的工作原理是:每天凌晨2点,扫描/nsm/zeek/logs/、/nsm/suricata/eve.json等目录,将24小时前的文件打包为tar.gz,存入/nsm/archive/,然后删除原文件。归档包名含日期,如zeek-2024-06-14.tar.gz。恢复时只需tar -xzf /nsm/archive/zeek-2024-06-14.tar.gz -C /nsm/zeek/logs/。
但要注意:归档不影响Elasticsearch索引。ES数据仍保留在/nsm/elasticsearch/data/,需单独管理。我设置/opt/so/saltstack/local/pillar/elasticsearch.sls:
elasticsearch: retention: days: 14 indices: ["so-suricata-*", "so-zeek-*", "so-wazuh-*"]然后sudo so-elasticsearch configure-retention,该命令会创建ILM(Index Lifecycle Management)策略,自动删除14天前的索引。
5. 常见问题与排查技巧实录
5.1 典型问题速查表
| 现象 | 可能原因 | 快速验证命令 | 解决方案 |
|---|---|---|---|
so-status显示suricata-eno1: down | 镜像口未UP或驱动异常 | ethtool eno1、dmesg | grep -i "eno1|af_packet" | sudo modprobe -r af_packet && sudo modprobe af_packet,重启网卡 |
Kibana Dashboard空白,Network标签显示502 Bad Gateway | Nginx代理到Kibana失败 | sudo systemctl status nginx、curl -v http://localhost:5601 | sudo so-nginx restart,检查/etc/nginx/conf.d/kibana.conf中proxy_pass指向http://127.0.0.1:5601 |
tail -f /nsm/suricata/eve.json无输出,但so-status显示running | Suricata配置未加载规则 | sudo suricata -T -c /etc/suricata/suricata.yaml -v | 检查/etc/suricata/suricata.yaml中rule-files:是否包含/nsm/rules/suricata.rules,执行sudo so-rule-update reload |
| Wazuh agent无法连接manager | 防火墙或SELinux阻止514端口 | sudo ufw status verbose、sudo sestatus | sudo ufw allow 514/udp,sudo setenforce 0(临时),永久关闭sudo sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config |
Elasticsearch启动失败,日志报max virtual memory areas vm.max_map_count [65530] is too low | Linux内核参数限制 | cat /proc/sys/vm/max_map_count | echo 'vm.max_map_count=262144' | sudo tee -a /etc/sysctl.conf && sudo sysctl -p |
5.2 我踩过的三个深坑与独家修复法
坑一:Zeek DNS日志缺失,但HTTP日志正常
现象:/nsm/zeek/logs/dns.log为空,http.log有数据。查zeekctl deploy日志发现warning: DNS analyzer disabled due to missing GeoIP database。
原因:Security Onion 2.4.60 ISO内置GeoIP数据库过期,/opt/zeek/share/zeek/site/geoip/下GeoLite2-Country.mmdb最后修改时间是2022年。
修复:
sudo mkdir -p /opt/zeek/share/zeek/site/geoip cd /tmp && wget https://git.io/GeoLite2-Country.mmdb && sudo mv GeoLite2-Country.mmdb /opt/zeek/share/zeek/site/geoip/ sudo zeekctl install sudo zeekctl deploy提示:不要用
geoipupdate命令,它会覆盖Zeek专用路径,必须手动放对位置。
坑二:Suricata规则更新后,部分规则不生效
现象:添加sid:1000001规则,但tcpdump -i eno1 port 80抓到匹配流量,eve.json无告警。
原因:Suricata默认启用rule-reload热加载,但某些规则(如含content:"|FF D8 FF|",fast_pattern:only)需重启服务才能生效。
修复:
sudo systemctl stop suricata@eno1 sudo suricata -T -c /etc/suricata/suricata.yaml -v # 验证配置无错 sudo systemctl start suricata@eno1注意:
suricata@eno1是systemd单元名,eno1需替换为你的镜像口名。
坑三:Kibana登录后白屏,Console报TypeError: Cannot read properties of undefined (reading 'get')
现象:输入admin密码后页面卡死,F12看Network标签,api/status返回200但app/home返回500。
原因:Kibana插件缓存损坏,特别是securityonion-kibana插件版本与Kibana 7.17.12不兼容。
修复:
sudo systemctl stop kibana sudo rm -rf /usr/share/kibana/optimize/bundles/* sudo rm -rf /usr/share/kibana/plugins/securityonion-kibana sudo so-kibana install-plugin sudo systemctl start kibana这是Security Onion 2.4.60的已知bug,官方将在2.4.70修复,目前只能手动清理。
5.3 生产环境必须做的五项加固
部署完成不等于安全上线,以下是我在金融客户现场强制执行的五项加固:
禁用root远程SSH:编辑
/etc/ssh/sshd_config,设PermitRootLogin no,PasswordAuthentication no,仅允许密钥登录。重启sudo systemctl restart sshd。限制Elasticsearch绑定地址:默认
network.host: 0.0.0.0,改为network.host: 127.0.0.1,确保ES只响应本地Kibana/Nginx请求。修改/etc/elasticsearch/elasticsearch.yml后sudo systemctl restart elasticsearch。关闭未用服务:
sudo systemctl disable bluetooth.service avahi-daemon.service,减少攻击面。配置UFW防火墙:仅开放必要端口:
sudo ufw default deny incoming sudo ufw allow from 192.168.10.0/24 to any port 22 # 管理网SSH sudo ufw allow from 192.168.10.0/24 to any port 5601 # Kibana sudo ufw allow 514/udp # Wazuh agent sudo ufw enable定期健康检查脚本:创建
/usr/local/bin/so-healthcheck.sh:#!/bin/bash echo "$(date): SO Health Check" >> /var/log/so-health.log sudo so-status | grep -E "down|failed" >> /var/log/so-health.log df -h /nsm | grep -E "(9[0-9]|100)%" >> /var/log/so-health.log加入crontab:
0 3 * * * /usr/local/bin/so-healthcheck.sh。
最后再分享一个小技巧:Security Onion的so-status命令其实是个Ansible wrapper,它背后调用ansible-playbook /opt/so/playbooks/so-status.yml。如果你想看某个服务的详细状态,比如Suricata,直接运行sudo ansible-playbook /opt/so/playbooks/so-status.yml --tags suricata,它会输出Suricata进程的PID、内存占用、规则加载数、当前吞吐(packets/sec),比systemctl status信息丰富得多。这个技巧帮我在一次深夜告警风暴中,30秒定位到是Suricata规则引擎卡死,而非网络问题。