凡是自己动手装过 Wazuh 的人大概率都经历过那种“照着官方文档一步步走最后还是挂了”的烦躁。我先后在 CentOS Stream、Debian 12 和一套内网隔离环境里部署过 Wazuh 4.x从索引器到 Dashboard 再到 agent 全链路踩了个遍——有些坑官方文档写了但没往死里强调有些坑干脆是文档没提、全靠日志一行一行喂出来的。这篇不做安装文档的翻译只聊那些真正让人想摔键盘的地方。刚准备从零开始装 Wazuh 的或者已经装了一半正在疯狂搜报错的都值得花十分钟扫一遍。文章里所有命令都基于 Wazuh 4.7 系列其他版本大同小异。1. 装之前先搞清楚 Wazuh 的骨架别让架构选择变成第一个坑1.1 三大组件各管什么Wazuh 不是单个程序而是一组服务。把这三个组件的关系在脑子里过一遍后面所有报错你都能迅速定位到“是哪一层出了问题”。Wazuh Indexer基于 OpenSearch 的分布式搜索分析引擎负责所有日志和告警事件的索引与存储。agent 的数据经过 manager 加工后最终落到这里。Wazuh Manager系统大脑和中枢负责接收 agent 上报的数据运行规则引擎做威胁检测、文件完整性监控FIM、漏洞扫描等并把结果写入索引器。Wazuh Dashboard挂在索引器上的可视化界面用户在这里查告警、看仪表盘、配规则本质上是 OpenSearch Dashboards 的定制发行版。数据流向是 agent → manager → indexer → dashboard。所以装完之后出问题排查方向也基本是从左往右或者从右往左二分。很多新手看到一个“Indexer connection refused”就慌了实际上问题可能出在 manager 到 indexer 的证书验证上跟 agent 一点关系都没有。1.2 资源规划官方文档没写透的底线官方文档给的最低配置是 2 核 4GB这里我得说实话这个配置拉起来做功能演示没问题但让它持续跑十几个 agent 的 FIM 事件内存会非常紧张系统 OOM 是迟早的事。我自己用 4GB 机器做过压力测试OpenSearch 的 JVM heap 默认按物理内存的 50% 分配4GB 机器上 JVM 能分到 2GB再叠加 manager、dashboard 和系统本身基本就是贴着天花板跑。部署方式CPU内存磁盘适合场景一体机测试2 核4GB30GB个人实验、少于 20 台 agent一体机生产4 核8GB100GB小团队内网、50 台左右 agent分布式每节点 2 核以上每索引器节点 8GBSSD100 台以上 agent 或对可用性有要求磁盘这块经常被忽略。OpenSearch 的索引默认保留策略下一台 agent 一天的日志量可能在 50~200MB 之间波动如果 agent 数量上来了30GB 系统盘大概两三周就满。装之前先在磁盘规划上留出余量数据目录最好单独挂一块盘。我个人建议至少 100GB 起步后面讲索引生命周期的时候还会详细说。2. 环境准备阶段翻车率最高的三个点2.1 vm.max_map_count一个参数决定 OpenSearch 生死这个参数是 Linux 内核层面限制单个进程能拥有的内存映射区域数量。OpenSearch 底层依赖 Lucene索引文件和内存映射密切相关默认的 65530 远远不够官方要求至少 262144。如果你没改这个值启动 OpenSearch 时日志里会出现类似这样的错误[1] bootstrap checks failed [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]然后整个服务就会启动失败。这个报错信息其实非常明确但我见过不少人是直接journalctl -u wazuh-indexer翻到这段日志然后一脸懵的因为它出现在“OpenSearch 启动器”的日志里而不是服务主日志里。修改方式是一行命令加一个持久化配置sysctl -w vm.max_map_count262144 echo vm.max_map_count262144 /etc/sysctl.conf sysctl -p改完之后记得用sysctl vm.max_map_count确认一下。这个坑在 CentOS 7、Ubuntu 22.04 上都存在属于必踩项目我后来写自动化脚本时会先把这一步前置检查掉。2.2 swap 与内存锁内存够但就是起不来第二个高发问题是memory locking requested for opensearch process but memory is not locked。原因是你开启了bootstrap.memory_lock: true这是官方推荐的生产配置要求 OpenSearch 的进程内存全部锁在物理内存里不允许换页到 swap。但如果系统没有给该进程足够的 memlock 上限启动就会失败。解决办法是调整 limitsecho opensearch soft memlock unlimited /etc/security/limits.conf echo opensearch hard memlock unlimited /etc/security/limits.conf改完需要重新登录或者重启服务生效。这里有个细节如果你用 systemd 管理 OpenSearch还需要确认服务单元文件里的LimitMEMLOCK没有被显式设置成有限值否则/etc/security/limits.conf不生效。还有一个反向场景有些人看到内存紧张就主动开了 swap 想“帮忙”这反而会让 OpenSearch 性能雪崩。索引和搜索请求一旦触发换页响应时间会从毫秒级跳到秒级。正确的思路是保证物理内存充足同时用bootstrap.memory_lock锁住内存别让内核把 OpenSearch 的页换出去。2.3 JDK别自己装 JavaWazuh Indexer 和 Wazuh Dashboard 都会自带配套的 JDK安装路径通常在/usr/share/wazuh-indexer/jdk和/usr/share/wazuh-dashboard/jdk根本不需要你在系统层面安装 Java。但你如果之前为了跑其他应用装过 OpenJDK 并设置了JAVA_HOME环境变量麻烦就来了。服务启动时会优先读取JAVA_HOME一旦指向了系统自带的 JDK 版本而版本又不匹配 OpenSearch 的要求就会出现奇怪的类加载错误或者直接起不来。最典型的是UnsupportedClassVersionError但很多人不会想到是 JDK 版本的问题。解决办法很简单在启动 Wazuh 相关服务之前先检查当前环境变量echo $JAVA_HOME如果在/etc/profile或~/.bashrc里设置了要么注释掉要么在启动脚本里显式指定OPENSEARCH_JAVA_HOME/usr/share/wazuh-indexer/jdk。一般来说干净环境里不需要做任何 Java 配置这也是我推荐“系统里不要多装 JDK”的原因——少一个变量少一个坑。3. 仓库安装的连环坑GPG、镜像源和系统版本3.1 yum/apt 源配置的正确姿势Wazuh 官方仓库在配置时有一个容易被忽略的先决条件必须先导入 GPG 密钥。如果你是照着官方文档操作通常会执行rpm --import https://packages.wazuh.com/key/GPG-KEY-WAZUH但很多人贪快直接把 repo 文件写进/etc/yum.repos.d/wazuh.repo就yum install结果报public key not installed。这时候再倒回去导入密钥yum 的缓存里可能还残留旧状态还需要yum clean all才能继续。repo 文件内容本身很简单[wazuh] gpgcheck1 gpgkeyhttps://packages.wazuh.com/key/GPG-KEY-WAZUH enabled1 nameEL-$releasever - Wazuh baseurlhttps://packages.wazuh.com/4.x/yum/ protect1Debian/Ubuntu 系则要稍微注意下签名文件路径Wazuh 提供的 deb 仓库配置脚本会自动处理手动配置的话要确认signed-by路径写对否则 apt-get update 会出现NO_PUBKEY的警告甚至直接拒绝安装。3.2 版本对齐一个组件掉队全家报错Wazuh 各组件之间的版本耦合比很多开源项目都紧。Indexer、Manager、Dashboard 三个包的主版本必须一致4.6 的 manager 配 4.7 的 indexer 不是“应该也能用”的事而是真的会报证书验证失败、API 请求 404 之类的问题。还有 OpenSearch 的版本它是被 Wazuh Indexer 锁定的不要手痒去手动升级 OpenSearch否则 Wazuh 的插件直接不加载。我遇到过一个比较隐蔽的版本坑机器上之前装过其他版本的 Wazuh 包重新安装时 yum 只更新了 managerDashboard 还停留在旧版本。结果登录 Web 界面的时候浏览器一直报证书错误查了半天发现是 Dashboard 和 indexer 的证书 CN 不匹配本质上是版本差异导致默认证书配置路径发生了变化。装之前建议用yum list wazuh-manager或者apt-cache policy wazuh-manager看一下仓库里的版本号规划好再动。多组件部署时尽量用官方提供的wazuh-install.sh辅助脚本统一装它会自动处理版本对齐和证书分发比自己手动挨个装省心太多。4. 索引器初始化证书、bootstrap 和集群配置4.1 bootstrap checks 失败的典型场景OpenSearch 启动前会做一系列 bootstrap 检查前面提到的vm.max_map_count和内存锁是其中两项。除此之外比较常见的还有文件描述符数量不够[1]: max file descriptors [4096] for opensearch process is too low, increase to at least [65535]解决方式依然是在 limits 里面加echo opensearch soft nofile 65535 /etc/security/limits.conf echo opensearch hard nofile 65535 /etc/security/limits.conf还有max number of threads检查在 systemd 单元配置或者 limits.conf 里调整nproc。这些检查项都属于“一次性配置”但在容器化环境里特别容易翻车——很多人用 Docker 跑 Wazuh 索引器容器里默认的 ulimit 是继承守护进程的如果不显式加上docker run --ulimit nofile65535:65535 --ulimit memlock-1:-1 ...bootstrap 检查就是过不了。换句话说容器并没有帮你省掉这些内核参数配置它只是把坑挪了个位置。4.2 证书生成工具的命名坑Wazuh 的通信安全完全建立在节点证书之上而证书生成工具wazuh-certs-tool.sh依赖一个config.yml文件里面的节点名必须和你后续集群配置里的node.name完全一致。我见过的最典型报错是ERROR: Could not find the node name wazuh-indexer-01 in the config.yml file原因是用户在/etc/hostname里设置了wazuh-indexer-01但config.yml里写的是wazuh-indexer。证书生成了也白生成因为你拿到的证书 CN 和节点名对不上集群之间互相验证永远失败。一个很关键的实操经验生成证书之前先用hostname命令确认机器当前的主机名然后决定是用它还是用固定名字。一旦生成了证书后续改主机名会导致所有证书验证失败因为 OpenSearch 会校验证书 CN 和节点名。别问我为什么知道——我有一台测试机改了主机名之后整个集群的证书要重新生成所有 agent 重新注册。如果需要重来正确的清理方式是rm -rf /root/wazuh-certs bash /usr/share/wazuh-indexer/bin/wazuh-certs-tool.sh -A注意-A是重新生成全部证书-a只生成 admin 证书。这两个参数大小写不一样功能完全不同我就在这上面栽过一次。4.3 初始化密码存好 wazuh-passwords.txt用wazuh-install.sh一键安装时脚本会在最后生成一个wazuh-passwords.txt里面是 admin 和所有内部用户的初始密码。这个文件的丢失几乎是灾难性的虽然可以用工具重置但过程繁琐。值得注意如果你在命令行执行过wazuh-passwords-tool.sh -a它会重新随机生成所有密码并覆盖输出文件。实操中我建议安装完成的第一件事就是把wazuh-passwords.txt拷贝到安全的地方例如密码管理器或者内网加密存储里。要是真的丢了重置 admin 密码的方式是/usr/share/wazuh-indexer/plugins/opensearch-security/tools/wazuh-passwords-tool.sh -u admin -p 你的新密码执行后还要用securityadmin.sh重新加载安全配置或者直接重启 wazuh-indexer 服务让配置生效。这里有个小细节改完密码后Dashboard 那边如果还缓存着旧 session会一直报 401这时候清一下浏览器 Cookie 或者用无痕窗口重新登录就行不用慌。5. 管理器和 Dashboard 联调端口、SELinux 和登录异常5.1 端口检查的一份命令清单装完所有服务第一件事不是打开浏览器而是检查端口是否都在监听。Wazuh 用到的端口如下端口协议用途1514TCP/UDPagent 与 manager 通信1515TCPagent 注册enrollment55000TCPauthd 注册服务可选443TCPDashboard Web 界面9200TCPIndexer REST API 与节点间通信检查命令ss -lntup | grep -E 1514|1515|55000|443|9200如果发现某些端口没监听先看服务状态systemctl status wazuh-manager systemctl status wazuh-indexer systemctl status wazuh-dashboard三者的启动顺序其实是有讲究的先索引器再 manager最后 dashboard。如果索引器还没起来 manager 就启动manager 会反复重试连接索引器日志里全是ERROR: Could not connect to indexer的刷屏。这不算致命错误有时候索引器启动慢过几分钟 manager 自己就会连上但如果你是第一次装很容易被这个错误误导去查 manager 的配置文件。防火墙方面CentOS 系用 firewalldUbuntu 系用 ufw。注意 1514 默认同时监听 TCP 和 UDP放行时要两个协议都放否则 agent 可能能注册但通信不稳定。5.2 SELinux 导致的“假网络故障”在 RHEL/CentOS 系上装 WazuhSELinux 是一个绕不开的坑。很多人的第一反应是直接关闭 SELinux这确实能解决问题但不是最佳实践。如果你不想在安全审计时被问到“为什么把 SELinux 关了”建议用最小化放行的方式。最常见的现象是所有服务都正常启动端口也在监听但 Dashboard 访问后端 API 一直失败或者 manager 无法向索引器写入数据。journalctl里能看到Permission denied但网络层面用curl localhost:9200又完全是通的。这几乎就是 SELinux 的 httpd 网络访问策略在捣乱。针对 Dashboard 的放行命令是setsebool -P httpd_can_network_connect 1这个布尔值允许 Apache/OpenSearch Dashboards 进程发起对外网络连接。如果你嫌麻烦非要关 SELinux改完/etc/selinux/config后一定要reboot不要以为setenforce 0就够了——有些服务在启动时读取的是 SELinux 的永久配置重启一次能少很多奇奇怪怪的权限问题。5.3 Dashboard 访问与登录异常Dashboard 默认通过https://服务器IP:443访问因为用的是自签名证书浏览器第一次访问会提示“连接不是私密连接”这是正常现象点高级继续访问即可。但如果你在内部 CA 环境或者需要正式使用时建议用wazuh-cert-tool生成一个包含 Dashboard 节点 IP 或域名的证书否则每次打开浏览器都要多一次点击运维体验很糟。登录时用adminwazuh-passwords.txt里的密码。如果提示Invalid credentials先检查密码文件里 admin 那行的密码是否在安装时被其他脚本改过。我见过有用户在执行wazuh-passwords-tool.sh -a之后把/root/wazuh-install-files下的旧密码文件反复复制混淆了其实是新旧两套密码弄岔了。如果你改了主机名之后 Dashboard 界面出现证书错误修复思路不是去改 Dashboard 配置而是重新生成整个节点证书链并重启服务。我在 4.2 里说过Wazuh 的证书和主机名强绑定这个设计在安全上是对的但也意味着改主机名这件事在 Wazuh 环境里是“重活”动之前要想清楚。6. Agent 注册失败的完整排查链路6.1 从 agent 端逐层排查Agent 注册失败是安装踩坑的重灾区而且这类问题有一个特点官方文档的安装命令看起来很简单但真实网络环境和文章里的假设差距很大。先把 agent 的安装命令写出来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新建 apt 源后安装WAZUH_MANAGER192.168.1.100 WAZUH_AGENT_NAMEweb-server WAZUH_AGENT_GROUPlinux apt-get install wazuh-agent安装完成后 agent 不会自动启动需要手动systemctl enable --now wazuh-agent然后立刻检查两个东西/var/ossec/etc/ossec.conf里的serveraddress是否指向了 manager 的正确地址以及/var/ossec/logs/ossec.log里有没有ERROR: Invalid address之类的信息。我遇到过一种很隐蔽的情况agent 安装时设置的WAZUH_MANAGER是内网 IP但 agent 机器上配了 hosts 解析把主机名指向了公网 IP导致 agent 连上了错误的地址。检查顺序应该是先确认配置文件里的地址 → 再确认 DNS 解析结果 → 最后抓包确认实际连接的 IP。6.2 从 manager 端反向检查如果 agent 端日志显示连接失败转头去 manager 上看日志tail -f /var/ossec/logs/ossec.log常见的几个报错对应关系如下manager 日志报错原因解决方向Could not connect to authdmanager 的 1515 端口未监听或防火墙拦截检查 wazuh-manager 服务状态和防火墙agent key already existsclient.keys 里有重复条目用 manage_agents 删除旧 keyERROR: Invalid key手动添加的 key 格式不对检查 key 的 base64 部分是否完整无任何日志agent 根本没到 manager网络不通检查 1514 端口连通性还有一个非常经典的坑agent 端wazuh-control status显示running但 manager 里就是看不到这个 agent。这时候先看 agent 的 ossec.log 是否有Connected to the server如果没有说明它还在反复重试。然后再确认 manager 端的client.keys文件里是否有这个 agent 的条目cat /var/ossec/etc/client.keys如果 agent 能注册、能连上但 manager 看不到多半是注册完之后 agent 还在用旧的 key 通信重启一下 agent 服务一般就能解决。6.3 注册方式的选择自动注册 vs 手动添加Wazuh 支持两种 agent 注册方式。第一种是自动注册依靠 authd即 1515/55000 端口agent 安装时传入 manager 地址authd 会自动为它生成 key。第二种是手动添加 key在 manager 上执行/var/ossec/bin/manage_agents输入A添加 agent然后提取生成的 key在 agent 端执行/var/ossec/bin/manage_agents输入I导入 key。两种方式在中小规模环境里都很常用但自动注册在大规模部署中是唯一可行的方案因为手动添加几百台 agent 的效率实在太低了。个人更推荐自动注册。需要注意如果 agent 和管理器之间有防火墙必须确保 1515 端口开放。另外自动注册时如果 agent 传了WAZUH_AGENT_GROUP参数manager 上必须有对应的 group 配置文件否则注册会失败。7. 装完之后磁盘和索引的运维警钟7.1 索引磁盘长得比想象中快安装成功之后的第一个星期往往是蜜月期但第二个星期开始磁盘告警就来了。OpenSearch 的索引大小和 agent 数量、日志量直接相关。我的一套测试环境5 台 agent 跑了 10 天索引数据加上副本占用了大概 8GB——如果不做任何清理策略一个月就是 24GB 起步。生产环境 50 台 agent 的话这个数字还会成倍增长。检查磁盘和索引的命令df -h curl -sk https://localhost:9200/_cat/indices?v -u admin:你的密码_cat/indices输出能看到每个索引的store.size和docs.count。默认情况下Wazuh 会为每天的告警和事件创建独立的索引索引名的日期后缀能帮你快速定位哪一天的数据量异常大。7.2 ISM 策略把删除动作自动化OpenSearch 自带的 Index State ManagementISM可以实现索引的自动滚动和删除Wazuh 默认配置里其实带了一套策略但很多人在测试环境里没在意等磁盘满了才想起去看。生产环境我建议自己定义一套更激进的保留策略比如只保留 30 天数据超过就删除。创建 ISM 策略的简单示例{ policy: { description: Wazuh index retention, default_state: hot, states: [ { name: hot, actions: [], transitions: [ { state_name: delete, conditions: { min_index_age: 30d } } ] }, { name: delete, actions: [ { delete: {} } ], transitions: [] } ] } }然后用curl把它应用到索引模板上。这一步需要在索引模板里指定ism.policy_id否则策略不会自动生效。如果嫌手动配置麻烦Wazuh Dashboard 的 “Indexer Management” 界面里也可以可视化管理 ISM 策略操作路径比较直观。还有一个容易被忽略的点索引副本。单节点部署时OpenSearch 默认还是会尝试给索引分配副本但因为没有第二个数据节点副本状态会是黄条。如果完全不打算扩容可以把副本数显式调成 0能省一半磁盘curl -sk -X PUT https://localhost:9200/*/_settings?expand_wildcardsall \ -u admin:你的密码 \ -H Content-Type: application/json \ -d {index.number_of_replicas: 0}注意通配符*和expand_wildcards参数否则系统索引会被挡在外面。这个操作对磁盘空间的节约立竿见影但代价是失去数据副本保护适合明确只有单节点的环境。8. 写在最后给准备入坑 Wazuh 的人几条保命建议几轮踩坑下来我最大的感受是Wazuh 的文档在“标准流程”上写得足够好但现实环境永远比标准流程多两个变量——版本、以及内核参数。所以最后分享几条靠踩坑换来的经验。第一装之前先把/etc/sysctl.conf、/etc/security/limits.conf、防火墙和 SELinux 四件事全部过一遍这四块的排查成本远比装完之后的任何问题都低。第二所有证书、密码文件生成后立刻备份尤其wazuh-passwords.txt和/root/wazuh-certs否则后面任何一个证书问题都要从整个信任链重新做起。第三生产环境不要手动升级 OpenSearch 或者 Wazuh 的单个组件版本对齐是三位一体的原则破坏一次就是全家重装的代价。另外还想补充一点日志是你的第一排查工具。/var/ossec/logs/ossec.log、journalctl -u wazuh-indexer、Dashboard 的configure.log这三份日志能覆盖 90% 的问题定位。遇到报错先看日志再搜文档比直接复制搜索到的命令要靠谱得多。Wazuh 的排错链路上日志永远比网上的“一句话答案”更有话语权。
