1. 为什么选择Wazuh搭建开源安全监控平台
1.1 从一台被入侵的测试机说起
几年前我负责维护一批对外提供服务的测试服务器,某天发现其中一台机器的CPU占用率长期跑满,登录上去一看,有个陌生进程在疯狂往外发包。查了半天日志,发现攻击者是通过一个弱口令SSH进来的,而整个过程我居然毫无感知——没有告警、没有记录、没有阻断。那次之后我开始认真找一套能落地的开源安全监控方案,试过ELK自己拼、试过OSSEC、也试过商业SIEM的社区版,最后长期留下来的就是Wazuh。
Wazuh这个东西,简单说就是一套开源的安全监控平台,它把SIEM(安全信息与事件管理)和XDR(扩展检测与响应)这两件事揉在了一起。它能干的事情包括:主机入侵检测(HIDS)、日志采集与分析、文件完整性监控(FIM)、漏洞检测、合规基线检查、恶意软件检测,以及基于规则的告警和主动响应。最关键的是,它完全开源,部署成本低,一台普通的Ubuntu服务器就能跑起来。
这篇文章适合谁看?如果你是刚接触安全运维的工程师,想给自己的服务器加一层"监控网";或者你是中小团队的运维,预算有限但又需要一套能看得见攻击面的系统;再或者你只是对开源安全工具感兴趣,想动手搭一套玩玩——那这篇内容应该能帮你少走不少弯路。我会从零开始,把安装、配置、规则编写、告警联动这些环节都拆开讲,尽量做到你照着做就能跑起来。
1.2 Wazuh的架构到底长什么样
很多人第一次接触Wazuh会被它的组件名搞晕,我先用大白话把架构捋一遍。Wazuh整体是C/S架构,核心分三块:
- Wazuh Agent:装在被监控的主机上,负责采集日志、监控文件变化、执行基线检查,然后把数据发给Server。它很轻量,资源占用低,Windows、Linux、macOS都能装。
- Wazuh Server:也就是管理端,负责接收Agent上报的数据,用规则引擎做分析匹配,触发告警。它内部又包含wazuh-manager(核心分析引擎)和wazuh-indexer(负责存储和检索,本质是OpenSearch的定制版)。
- Wazuh Dashboard:Web界面,用来查看告警、做可视化、管理Agent和规则。它基于OpenSearch Dashboards改造。
数据流向是这样的:Agent采集 → Server分析 → Indexer存储 → Dashboard展示。理解这条链路很重要,后面排查问题的时候,你得知道数据卡在哪一环。
提示:Wazuh 4.x版本之后,官方把Elastic Stack换成了OpenSearch,所以如果你看的是老教程里提到Elasticsearch,那是4.0之前的架构,别混用。
1.3 为什么推荐在Ubuntu上部署
热词里Ubuntu相关的内容占了很大比例,这不是偶然。Wazuh官方对Ubuntu的支持是最好的,文档全、社区案例多、踩坑少。我自己的生产环境用的是Ubuntu 22.04 LTS,这个版本长期支持到2027年,稳定性和软件源都很成熟。
选Ubuntu还有几个实际好处:一是apt包管理装依赖方便,Wazuh官方也提供apt源,一条命令就能装;二是Ubuntu Server资源占用低,2核4G的虚拟机就能跑起单机版Wazuh;三是网上关于Ubuntu的教程多,遇到网络配置、SSH连接、环境变量这类问题,搜一下基本都有答案。
如果你手上只有Windows机器,可以先装个VMware或者VirtualBox,再装Ubuntu虚拟机来练手。虚拟机安装Ubuntu的流程这里不展开,重点提醒一句:给虚拟机至少分配4GB内存和50GB磁盘,Wazuh的Indexer比较吃资源,配置太低跑起来会卡。
2. 部署前的环境准备与关键决策
2.1 硬件与系统参数怎么定
在动手之前,先把资源算清楚,不然装到一半发现内存不够会很尴尬。Wazuh官方给的最低配置和推荐配置差距挺大,我整理了一个对照表,你可以根据自己的场景选:
| 组件 | 最低配置 | 推荐配置 | 说明 |
|---|---|---|---|
| CPU | 2核 | 4核以上 | Indexer对CPU敏感 |
| 内存 | 4GB | 8GB以上 | 低于4GB Indexer容易OOM |
| 磁盘 | 50GB | 100GB以上 | 日志存储吃空间 |
| 系统 | Ubuntu 20.04 | Ubuntu 22.04 LTS | 22.04支持周期更长 |
这里有个坑要提前说:Wazuh Indexer底层是Java写的(OpenSearch),默认堆内存会占用物理内存的一半。如果你给虚拟机分配4GB内存,Indexer可能直接吃掉2GB,再加上Manager和Dashboard,系统会非常紧张。我的建议是测试环境至少8GB内存,生产环境按Agent数量往上加。
还有一个容易被忽略的点是文件句柄数。Wazuh在高负载下会打开大量文件描述符,Ubuntu默认的ulimit可能不够。部署前先改一下:
# 查看当前限制 ulimit -n # 临时调整 ulimit -n 65535 # 永久生效,编辑 /etc/security/limits.conf,追加: * soft nofile 65535 * hard nofile 65535改完记得重新登录才生效。这个细节很多教程都不提,但实际跑起来Agent一多,句柄数不够会导致Manager莫名其妙丢数据。
2.2 网络与主机名配置要点
Wazuh各组件之间靠网络通信,主机名和IP配置错了,后面Dashboard连不上Indexer是常见问题。我习惯在部署前先把这几件事做掉:
第一,设置静态IP。Ubuntu Server 22.04用netplan管理网络,配置文件在/etc/netplan/下面。编辑对应的yaml文件,把dhcp4改成no,然后手动指定addresses、gateway4、nameservers。改完执行sudo netplan apply。这一步是为了避免IP变动导致Agent失联。
第二,配置hosts解析。如果你打算用主机名而不是IP来配置组件,就在/etc/hosts里加上映射:
# /etc/hosts 192.168.1.100 wazuh-server第三,确认主机名规范。Wazuh Agent注册时会用主机名做标识,如果主机名是localhost或者重复,管理起来会很乱。用hostnamectl set-hostname wazuh-server改一下。
注意:如果你在虚拟机里做实验,网络模式建议选桥接而不是NAT,这样局域网内其他机器也能访问Dashboard。NAT模式下外部访问需要额外做端口转发,比较麻烦。
2.3 系统更新与依赖安装
正式装Wazuh之前,先把系统更新到最新,避免依赖冲突:
sudo apt update sudo apt upgrade -y sudo apt install -y curl apt-transport-https lsb-release gnupg这几个依赖里,curl用来下载安装脚本,apt-transport-https让apt支持https源,gnupg用来导入Wazuh的签名密钥。别小看这几步,我遇到过因为缺gnupg导致添加源失败的案例。
另外,如果你之前装过Docker或者改过系统源,建议先确认一下/etc/apt/sources.list没有异常条目。Ubuntu环境变量配置错误、源混乱是新手常见问题,装Wazuh前保持系统干净能省很多事。
3. 单机版Wazuh的完整安装实操
3.1 用官方脚本一键部署
Wazuh官方提供了一个安装助手脚本,能自动完成Indexer、Server、Dashboard的安装和证书生成。这是最省事的方式,适合快速搭建测试环境。整个过程分两步:
第一步,下载并运行安装脚本:
curl -sO https://packages.wazuh.com/4.7/wazuh-install.sh curl -sO https://packages.wazuh.com/4.7/config.yml第二步,编辑config.yml,配置各节点的IP和密码。单机版的话,把hosts里所有节点都指向同一台机器的IP:
nodes: indexer: - name: node-1 ip: "192.168.1.100" server: - name: wazuh-server ip: "192.168.1.100" dashboard: - name: wazuh-dashboard ip: "192.168.1.100"然后执行安装:
sudo bash wazuh-install.sh --generate-config-files sudo bash wazuh-install.sh --wazuh-indexer node-1 sudo bash wazuh-install.sh --start-cluster sudo bash wazuh-install.sh --wazuh-server wazuh-server sudo bash wazuh-install.sh --wazuh-dashboard wazuh-dashboard这一串命令跑下来大概需要10到20分钟,取决于机器性能和网络。安装完成后,脚本会输出Dashboard的访问地址和默认账号密码,一定要把密码记下来,后面登录要用。
提示:安装过程中如果卡在"Waiting for Wazuh indexer to be ready",多半是内存不够导致Indexer启动失败。先
free -h看下内存,再systemctl status wazuh-indexer看服务状态。
3.2 安装后的服务检查清单
脚本跑完不代表万事大吉,我习惯按下面的清单逐项确认:
# 检查三个核心服务状态 systemctl status wazuh-indexer systemctl status wazuh-manager systemctl status wazuh-dashboard # 检查端口监听 ss -tlnp | grep -E '9200|55000|443'正常情况下,Indexer监听9200,Manager监听55000和1514/1515,Dashboard监听443。如果哪个端口没起来,对应的服务肯定有问题。
再验证一下集群健康状态:
curl -k -u admin:你的密码 https://192.168.1.100:9200/_cluster/health?pretty返回的status应该是green或者yellow。yellow在单节点环境下是正常的,因为副本分片没法分配;如果是red,说明有分片损坏,得查Indexer日志。
3.3 首次登录Dashboard要做的几件事
浏览器访问https://192.168.1.100,用安装时给的账号登录。第一次进去建议先做三件事:
第一,改默认密码。默认密码是脚本生成的随机串,虽然复杂但不好记,可以在Dashboard的Security里改,或者用wazuh-passwords-tool.sh批量改。
第二,检查Agent列表。默认情况下Server本机会作为一个Agent注册进来,在"Agents"页面应该能看到一个状态为Active的条目。如果显示Never connected,说明Agent和Manager之间的通信有问题,重点查1514端口和防火墙。
第三,看一眼默认规则触发的告警。Wazuh自带了几千条规则,装完就会有一些基础告警,比如SSH登录失败。在"Security events"里能看到这些数据,说明整条链路是通的。
4. Agent部署与日志接入实战
4.1 在Linux主机上装Agent
Server搭好了,接下来就是往被监控的主机上装Agent。Ubuntu上装Agent很简单,先添加Wazuh的apt源:
curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | gpg --no-default-keyring --keyring gnupg-ring:/usr/share/keyrings/wazuh.gpg --import chmod 644 /usr/share/keyrings/wazuh.gpg echo "deb [signed-by=/usr/share/keyrings/wazuh.gpg] https://packages.wazuh.com/4.x/apt/ stable main" | tee /etc/apt/sources.list.d/wazuh.list apt update然后安装Agent并指定Manager地址:
WAZUH_MANAGER="192.168.1.100" apt install wazuh-agent装完启动服务:
systemctl daemon-reload systemctl enable wazuh-agent systemctl start wazuh-agent回到Dashboard的Agents页面,应该能看到新注册的主机。如果没出现,先看Agent日志/var/ossec/logs/ossec.log,常见原因是Manager地址填错或者防火墙挡了1514端口。
4.2 自定义日志采集配置
Wazuh默认会采集一批系统日志,但实际业务中我们往往需要监控特定的应用日志。配置入口在Agent的/var/ossec/etc/ossec.conf,用<localfile>标签定义:
<localfile> <log_format>syslog</log_format> <location>/var/log/nginx/access.log</location> </localfile> <localfile> <log_format>json</log_format> <location>/var/log/myapp/app.log</location> </localfile>log_format要跟日志实际格式匹配,syslog格式的用syslog,JSON格式的用json,纯文本用command配合脚本解析。改完配置重启Agent生效。
这里有个经验:别一股脑把所有日志都接进来。日志量太大会拖垮Indexer,也会让告警淹没在噪音里。我的做法是先明确要检测什么,比如"监控Nginx的404和500"、"监控应用日志里的ERROR关键字",然后只接相关的日志文件。
4.3 文件完整性监控(FIM)配置
FIM是Wazuh的招牌功能之一,能监控指定目录下文件的增删改。配置同样在ossec.conf里:
<syscheck> <frequency>43200</frequency> <directories check_all="yes" realtime="yes">/etc,/usr/bin,/usr/sbin</directories> <directories check_all="yes" realtime="yes">/var/www/html</directories> <ignore>/etc/mtab</ignore> </syscheck>frequency是扫描间隔(秒),realtime开启实时监控。check_all会检查文件大小、权限、属主、MD5、SHA1等属性。
注意:
realtime模式依赖inotify,监控目录太多会消耗大量文件句柄。生产环境建议只对关键目录开实时监控,其他目录用定时扫描。
5. 规则编写与告警调优
5.1 理解Wazuh的规则结构
Wazuh的规则是XML格式,核心逻辑是"匹配日志 → 触发规则 → 产生告警"。一条最简单的规则长这样:
<rule id="100001" level="10"> <decoded_as>myapp</decoded_as> <match>ERROR</match> <description>应用日志出现ERROR关键字</description> </rule>id是规则编号,自定义规则建议从100000开始,避免和官方规则冲突。level是告警级别,0到15,数字越大越严重。decoded_as指定解码器,match是匹配内容。
规则文件放在Manager的/var/ossec/etc/rules/目录下,改完用/var/ossec/bin/wazuh-logtest测试,这个工具能模拟日志输入,看规则是否命中,非常实用。
5.2 写一条检测SSH暴力破解的规则
SSH暴力破解是最常见的攻击方式,Wazuh自带规则能检测单次失败,但连续失败需要自定义。我写一条基于频率的规则:
<rule id="100100" level="12" frequency="8" timeframe="120"> <if_matched_sid>5710</if_matched_sid> <same_source_ip /> <description>检测到SSH暴力破解,来源IP: $(srcip)</description> <mitre> <id>T1110</id> </mitre> </rule>这条规则的意思是:120秒内,同一个源IP触发了8次规则5710(SSH登录失败),就告警。mitre标签关联MITRE ATT&CK框架,方便做威胁分析。
写完规则后,用wazuh-logtest测试:
/var/ossec/bin/wazuh-logtest # 输入模拟日志 Failed password for root from 192.168.1.200 port 22 ssh2如果规则命中,会显示匹配的规则ID和告警级别。测试通过后重启Manager生效。
5.3 告警降噪的实用技巧
规则写多了,告警会爆炸。我总结了几个降噪手段:
- 用
ignore排除已知无害的日志。比如某些健康检查产生的404,直接在规则里忽略。 - 调整
level。不是所有异常都值得半夜叫醒你,把低风险事件的级别调低。 - 用
frequency和timeframe做聚合。单次失败不告警,连续多次才告警。 - 配置告警抑制。Wazuh支持在
ossec.conf里设置<alerts><log_alert_level>,低于这个级别的告警不记录。
我自己的经验是,新规则上线后先观察一周,看告警量是否合理,再决定要不要调整阈值。一上来就把级别设得很高,结果天天被误报轰炸,最后反而没人看告警了。
6. 常见问题排查与避坑实录
6.1 Agent显示Never connected怎么办
这是新手遇到最多的问题。排查顺序如下:
| 排查项 | 检查方法 | 常见原因 |
|---|---|---|
| 网络连通性 | ping Manager_IP | 网络不通 |
| 端口开放 | telnet Manager_IP 1514 | 防火墙拦截 |
| Manager地址 | 看ossec.conf里<address> | 地址填错 |
| Agent密钥 | 看/var/ossec/etc/client.keys | 密钥未注册 |
| 服务状态 | systemctl status wazuh-agent | 服务未启动 |
我遇到过最隐蔽的一次是Manager的1514端口只监听了IPv6,Agent用IPv4连不上。解决办法是在Manager的ossec.conf里显式指定<local_ip>为IPv4地址。
6.2 Indexer内存不足导致服务崩溃
Wazuh Indexer默认堆内存是物理内存的一半,如果机器内存小,很容易OOM。调整方法在/etc/wazuh-indexer/jvm.options:
-Xms2g -Xmx2g把这两个值改成固定大小,比如2GB。注意Xms和Xmx要设成一样,避免动态调整带来的性能抖动。改完重启Indexer。
如果还是频繁崩溃,就得考虑加内存或者把Indexer单独部署到另一台机器上。
6.3 Dashboard登录后一片空白
有时候能登录,但页面加载不出来,多半是Dashboard和Indexer之间的连接有问题。检查/etc/wazuh-dashboard/opensearch_dashboards.yml里的opensearch.hosts配置,确认指向正确的Indexer地址和端口。另外看Dashboard日志/var/log/wazuh-dashboard/,里面会有具体的报错信息。
还有一种情况是浏览器缓存问题,换个无痕窗口试试。这个坑我踩过,排查了半天发现是缓存。
6.4 规则不生效的排查思路
写完规则没反应,按这个顺序查:
- 规则文件是否放在正确目录,权限是否正确(属主
wazuh,权限660) - 规则ID是否和已有规则冲突
- 用
wazuh-logtest测试是否命中 - Manager是否重启
- 日志是否真的被采集到了(看
/var/ossec/logs/archives/)
提示:
wazuh-logtest是排查规则问题的神器,一定要熟练使用。它能显示日志经过解码器、规则匹配的完整过程,比瞎猜高效得多。
7. 从单机到分布式的扩展思路
单机版跑通之后,如果Agent数量上来了,就得考虑分布式部署。基本思路是把Indexer做成集群(至少3个节点),Manager也可以多节点做负载均衡,Dashboard单独部署。这样任何一台机器挂了,整个系统还能继续工作。
扩展的时候有几个关键点:一是证书要重新生成,集群节点之间的通信需要证书互信;二是配置文件里的节点列表要同步更新;三是负载均衡,Agent上报的数据要能分发到不同的Manager。
我自己的环境是3台Indexer + 2台Manager + 1台Dashboard,支撑了大概200个Agent,运行了一年多比较稳定。资源上每台Indexer给了8GB内存,Manager给了4GB,Dashboard给了2GB。
对于中小团队来说,如果Agent数量在50以内,单机版完全够用,不用急着上分布式。先把规则和告警调优做好,比堆硬件更有价值。
最后分享一个我踩过的坑:别在Wazuh Server本机上装太多其他服务。我曾经把Server和一台测试用的Web服务放一起,结果Web服务被攻击时产生的日志把Wazuh的磁盘写满了,导致Indexer无法写入。后来把Wazuh单独隔离到一台机器上,问题再没出现过。安全监控平台本身也需要被保护,这个道理说起来简单,做起来容易忘。