開始之前
需要準備什麼
- 一台有網路的機器,有 Python 3 與
pip(Linux、macOS、Windows 皆可)—— 最省事的是一台有 Docker 的 Linux。 - 把一個檔案(約 10 MB)搬到 manager 的方法:USB 隨身碟、經跳板機
scp等。 - Wazuh Manager 的 root 權限;叢集環境是 master 節點。worker 與 agent 都不用裝。
先在 manager 上記下兩件事
Wazuh Manager Python 套件是依 Python 版本與 CPU 編譯的,所以打包內容必須與它們相符:
/usr/bin/python3 -V
uname -m
服務是以 /usr/bin/python3 執行,所以要看的是它的版本 —— 例如
Python 3.9.25 → 3.9,以及 x86_64。manager 上不需要安裝 pip。
X.Y.Z 代表你選的版本(不含開頭的 v)。
install.sh --offline 從 v1.19.0 之後的版本開始提供;v1.19.0 以前請用
手動步驟。1. 製作安裝包
下載程式
有網路的機器
VER=X.Y.Z
curl -fsSLO https://github.com/jasoncheng7115/jt-wazuh-mgr/archive/refs/tags/v$VER.tar.gz
tar xzf v$VER.tar.gz # 產生 jt-wazuh-mgr-$VER/
GitHub 產生的壓縮檔裡,目錄名稱是 jt-wazuh-mgr-X.Y.Z(沒有 v)。
下載 Python 套件(wheel)—— 建議做法
有網路的機器 用與 manager 相同的 Python 版本執行 pip download。最簡單的方式是開一個用完即丟的容器;
把 3.9 換成 manager 的版本:
docker run --rm -v "$PWD":/w -w /w python:3.9-slim \
pip download --only-binary=:all: -r jt-wazuh-mgr-$VER/requirements.txt -d jt-wazuh-mgr-$VER/wheels
在一台與 manager 相同作業系統版本的機器上執行同樣的 pip download 也可以。
--only-binary=:all: 讓缺少 wheel 的情況在這裡(有網路的機器上)就失敗,而不是到了 manager 才發現。
容器使用的是執行它那台機器的 CPU;若要在 x86 機器上替 ARM 的 manager 準備,請用下一則的做法。
沒有 Docker:替另一個 Python 版本下載
有網路的機器 pip 可以下載給非自己版本使用的 wheel:
python3 -m pip download -r jt-wazuh-mgr-$VER/requirements.txt "importlib-metadata>=3.6" \
--only-binary=:all: --implementation cp --python-version 3.9 \
--platform manylinux2014_x86_64 --platform manylinux_2_17_x86_64 \
-d jt-wazuh-mgr-$VER/wheels
--python-version填第一步記下的 manager 版本。- ARM 的 manager(
aarch64)改寫成manylinux2014_aarch64與manylinux_2_17_aarch64。 - 不要拿掉
"importlib-metadata>=3.6"。這種模式下 pip 是用自己的 Python 判斷條件式相依, 因此會漏掉 Flask 只在 Python 3.9 才需要的套件 —— 結果在 3.9 的 manager(RHEL 9、Rocky/Alma 9、 Amazon Linux 2023、Wazuh manager 容器)上安裝會停在No matching distribution found for importlib-metadata。對其他版本沒有影響。
wheels/ 目錄只放一種 Python 版本。若各台 manager 的 Python 版本不同,
每個版本各做一份安裝包。打包
有網路的機器
tar czf jt-wazuh-mgr-$VER-offline.tar.gz jt-wazuh-mgr-$VER
sha256sum jt-wazuh-mgr-$VER-offline.tar.gz > jt-wazuh-mgr-$VER-offline.tar.gz.sha256
2. 在 manager 上安裝
複製、核對、解壓、安裝
Wazuh Manager 把兩個檔案都複製過去(例如放在 /root),再以 root 執行:
cd /root
sha256sum -c jt-wazuh-mgr-X.Y.Z-offline.tar.gz.sha256
tar xzf /root/jt-wazuh-mgr-X.Y.Z-offline.tar.gz -C /root
bash /root/jt-wazuh-mgr-X.Y.Z/install.sh --offline
解壓一律加 -C,安裝腳本一律用完整路徑執行;這樣結果就不會取決於你當下所在的目錄。
--offline 做了什麼
- 從解壓出來的目錄把程式、規則套件目錄清單、圖示、服務設定檔與
uninstall.sh複製到/opt/jt-wazuh-mgr。不執行curl、不執行apt/dnf、不連 PyPI。 config.yaml只在還不存在時才寫入。- 把
wheels/裡的 Python 套件裝進/opt/jt-wazuh-mgr/vendor,絕不寫入系統 Python: 有 pip 時用pip install --no-index,沒有 pip 時直接解開適用於此 Python 的 wheel(wheel 就是 zip)。 先裝在vendor.new,確認可以匯入後才替換,所以安裝包有問題時,原本可用的那份不會被動到。 - 安裝
/etc/systemd/system/jt-wazuh-mgr.service、啟用並啟動服務,兩秒後再確認它仍在執行。
wheel 放在別處時:install.sh --offline --wheels /path/to/wheels。
3. 驗證
從系統本身把結果讀回來,不要只看安裝腳本的輸出
Wazuh Manager
grep __version__ /opt/jt-wazuh-mgr/lib/__init__.py # 應為你安裝的版本
systemctl is-active jt-wazuh-mgr # active
curl -ks -o /dev/null -w '%{http_code}\n' https://127.0.0.1:5000/login # 200
journalctl -u jt-wazuh-mgr -n 20 --no-pager # 上面任何一項不對時看這裡
接著開啟 https://YOUR_WAZUH_MANAGER_IP:5000,以 Wazuh API 使用者登入(不要用 Dashboard 自己的
wazuh-wui 帳號)。若上面的 curl 回 200、瀏覽器卻連不上,請在 manager 的防火牆開放 TCP 5000。
4. 升級
同樣的安裝包,換成新版本
- 有網路的機器 依步驟 1,替新的
X.Y.Z做一份安裝包。 - Wazuh Manager 備份目前的安裝與服務設定檔:
tar czf /root/jt-wazuh-mgr-backup-$(date +%F).tar.gz -C /opt jt-wazuh-mgr cp /etc/systemd/system/jt-wazuh-mgr.service /root/jt-wazuh-mgr.service.bak-$(date +%F) - Wazuh Manager 解開新版本並執行它的安裝腳本:
tar xzf /root/jt-wazuh-mgr-X.Y.Z-offline.tar.gz -C /root bash /root/jt-wazuh-mgr-X.Y.Z/install.sh --offline - Wazuh Manager 依步驟 3 驗證 —— 版本一定要從
/opt/jt-wazuh-mgr讀回來, 然後在瀏覽器按 Ctrl+Shift+R 重新整理。
升級會保留什麼、取代什麼
| 保留 | config.yaml;--ssl-auto 產生的憑證(ssl_cert.pem、
ssl_key.pem);wazuh_agent_mgr.log;你放在
/etc/systemd/system/jt-wazuh-mgr.service.d/ 的 drop-in;已安裝到 manager 的規則套件
(/var/ossec/etc/...,安裝狀態在 /var/ossec/etc/jt-packs/)。 |
|---|---|
| 取代 | 程式檔案、/opt/jt-wazuh-mgr/packs 裡的規則套件目錄清單、圖示、
/etc/systemd/system/jt-wazuh-mgr.service,以及安裝包有 wheel 時的 vendor/。 |
規則套件另外從「規則套件」分頁更新:它會標出目錄清單版本比 manager 上已安裝版本新的套件, 並在變更任何東西之前先列出計畫。更新後請在所有節點重新載入規則集。
若新版的 requirements.txt 與已安裝的相同
(diff /opt/jt-wazuh-mgr/requirements.txt /root/jt-wazuh-mgr-X.Y.Z/requirements.txt),
可以不帶 wheel:沒有 wheels/ 目錄時,只要現有的 vendor/ 還能匯入,安裝腳本就會保留它。
不過每次都帶著 wheel 比較單純。
5. 退回
回到步驟 4 的備份
Wazuh Manager 把失敗的版本移到旁邊而不是直接刪掉,之後還能檢查:
systemctl stop jt-wazuh-mgr
mv /opt/jt-wazuh-mgr /opt/jt-wazuh-mgr.failed
tar xzf /root/jt-wazuh-mgr-backup-YYYY-MM-DD.tar.gz -C /opt
cp /root/jt-wazuh-mgr.service.bak-YYYY-MM-DD /etc/systemd/system/jt-wazuh-mgr.service
systemctl daemon-reload
systemctl start jt-wazuh-mgr
grep __version__ /opt/jt-wazuh-mgr/lib/__init__.py
把 YYYY-MM-DD 換成備份檔名裡的日期。舊版恢復執行後,/opt/jt-wazuh-mgr.failed 就可以刪除。
手動步驟(不使用 --offline)
適用於 v1.19.0 以前,或想看清楚每一步時
Wazuh Manager 這就是 install.sh --offline 做的事,逐步寫出來。以 root 執行,先依步驟 2
解開安裝包(升級時還要先做步驟 4 的備份):
VER=X.Y.Z
SRC=/root/jt-wazuh-mgr-$VER
DST=/opt/jt-wazuh-mgr
mkdir -p "$DST"
cp -r "$SRC"/wazuh_agent_mgr.py "$SRC"/create_api_user.py "$SRC"/requirements.txt \
"$SRC"/lib "$SRC"/packs "$SRC"/images "$SRC"/jt-wazuh-mgr.service "$SRC"/uninstall.sh "$DST"/
[ -f "$DST/config.yaml" ] || cp "$SRC/config.yaml" "$DST/" # 絕不覆蓋你的設定
rm -rf "$DST/vendor.new"
接著把 Python 套件裝進 vendor.new,以下擇一:
# a) manager 上有 pip
python3 -m pip install --no-index --find-links "$SRC/wheels" --target "$DST/vendor.new" -r "$DST/requirements.txt"
# b) 沒有 pip:wheel 就是 zip
mkdir "$DST/vendor.new"
for w in "$SRC"/wheels/*.whl; do python3 -m zipfile -e "$w" "$DST/vendor.new"; done
確認可以匯入才替換,然後(重新)啟動服務:
PYTHONPATH="$DST/vendor.new" /usr/bin/python3 -c 'import flask, yaml, requests, rich, tabulate' \
&& rm -rf "$DST/vendor" && mv "$DST/vendor.new" "$DST/vendor"
cp "$DST/jt-wazuh-mgr.service" /etc/systemd/system/
systemctl daemon-reload
systemctl enable jt-wazuh-mgr
systemctl restart jt-wazuh-mgr
再依步驟 3 驗證。
wheel 與 Python 版本不符時
No matching distribution found
ERROR: No matching distribution found for PyYAML>=6.0 The wheels in /root/jt-wazuh-mgr-X.Y.Z/wheels do not cover requirements.txt for Python 3.12.wheel 是替另一個 Python 版本或 CPU 下載的。安裝腳本會在動到 vendor/ 與重啟服務之前停下,
所以執行中的版本照常運作(程式檔案已經複製過去,下次重啟時生效)。請再確認一次 /usr/bin/python3 -V
與 uname -m,替那個版本重做 wheels/ 目錄(步驟 1),再執行一次安裝腳本
—— 或是退回。
若缺的是 importlib-metadata,代表 wheel 是用 --python-version 的做法下載、卻少了那個額外參數;
見步驟 1。
wheel 無法在 Python 3.x 匯入
The wheels in ... do not import on Python 3.9 (missing, or built for another Python version).同樣的原因,出現在沒有 pip 的 manager 上:編譯型套件(PyYAML、MarkupSafe、charset-normalizer)的檔名帶有 Python 版本,
例如 cp39,只有相符的才會被使用。請替 manager 的版本重做 wheel。
Python 版本太新,PyPI 上還沒有 wheel
非常新或少見的 Python 版本,PyPI 上可能還沒有對應的編譯好的 wheel,--only-binary=:all:
會在有網路的機器上就失敗。這時在一台與 manager 相同作業系統版本、相同 Python 版本的機器上自己產生 wheel
(沒有現成 wheel 的套件會從原始碼建置,可能需要編譯器):
python3 -m pip wheel -r jt-wazuh-mgr-$VER/requirements.txt -w jt-wazuh-mgr-$VER/wheels
改用發行版的套件
若 manager 有內部的套件鏡像站,也可以用發行版自己的套件。裝好之後,安裝包裡不放 wheels/,
安裝腳本會因為這些模組已經能匯入而繼續:
apt install python3-flask python3-yaml python3-requests python3-rich python3-tabulate # Debian / Ubuntu
requirements.txt 要求 Flask 2.3 以上;選這條路之前,先確認發行版提供的版本
(apt-cache policy python3-flask)。
規則套件在離線環境
安裝、更新與移除規則套件都不需要網路:套件就附在工具裡,從「規則套件」分頁安裝。可能需要連線的是部分套件裝好之後要做的事。這些套件的部署說明都有一步「管理端無法連外時」(或針對被監控主機的對應步驟),裡面有確切的指令。
| 套件 | 需要連線的部分 | 離線做法 |
|---|---|---|
jt-ioc、jt-malware-hash | 威脅情資來源,由 master 下載 | 在可連外的電腦執行更新程式,把快取複製到 master,以 --skip-download 執行;排程改用 --reload-if-stale 停掉下載。 |
jt-php | php.net 的發行資料 | 在別處下載發行資料檔,複製到 etc/jt-packs/offline/php/,以 --source file://… 讀取。 |
jt-runtime-vuln | CISA KEV 清單;Node.js、Python、OpenVPN 發行資料 | 同上,每個來源各有 file:// 選項。 |
jt-alert-digest | Teams、Slack、Discord、Telegram、LINE | 郵件(內部 SMTP 轉送)、Zulip、Mattermost 與通用 webhook 在內網即可;雲端管道經 https_proxy,或不要設定。 |
jt-web | 只有選用的 Cloudflare 封鎖 | 設定 proxy=,或不要啟用;nginx 封鎖離線可用。 |
jt-container-vuln | Trivy 映像與弱點資料庫,在每台 Docker 主機上 | 複製到內部 registry,讓掃描程式指向它。 |
jt-docker、jt-vc-portal | Docker 主機上的 Python docker 函式庫 | 內部套件鏡像,或在可連外的電腦 pip download。 |
jt-portable-detect、jt-linux-integrity | 主機上的 Sysmon(Windows)與 auditd(Linux) | 複製 Sysmon64.exe 過去;auditd 從內部鏡像安裝。 |
jt-ucs、jt-synology、jt-jitsi | 被監控伺服器上的一個套件或映像 | 內部套件庫、手動安裝套件,或內部 registry。 |
| 其他套件 | 不需要 |
不會被套件更新洗掉的選項
工具每次安裝或更新套件都會重寫 /etc/cron.d/jt-<套件>,所以不要改那個檔。站台的選項改放在 /var/ossec/etc/jt-packs/<套件>.cron.local(root 擁有、其他人不可寫):<腳本>: <選項> 一行替該腳本加上選項,NAME=value 一行設定環境變數。工具每次寫入排程時都會套用;要立刻生效,在「規則套件」分頁開啟該套件、按「重寫排程」。worker 的排程是手動複製的,請在那裡加上同樣的選項。
# /var/ossec/etc/jt-packs/jt-ioc.cron.local
update-threat-ip-list.py: --reload-if-stale
# /var/ossec/etc/jt-packs/jt-alert-digest.cron.local
https_proxy=http://proxy.example.com:3128
no_proxy=localhost,127.0.0.1
離線副本不會自己變舊:每次安全性版本發布後請更新它;套件有 stale_hours 設定的,請設定它,匯入逾期時才會告警。
離線環境的其他注意事項
沒有網路時,哪些能用、哪些不能
- 所有與 Wazuh 互動的功能都能用:這個工具只使用 manager 自己的 API 與檔案。
- 規則套件從版本內附的目錄清單安裝。部分套件裝好之後要做的事可能需要連線,見規則套件在離線環境。
- 設定編輯器的語法上色是由你的瀏覽器從 cdnjs 載入的。取不到時編輯器照常可用,只是沒有顏色。
移除
離線環境直接可用:bash /opt/jt-wazuh-mgr/uninstall.sh。若希望被覆蓋的原始檔案被還原,
請先從「規則套件」分頁移除已安裝的套件。
遇到其他問題?請看安裝與升級疑難排解。