離線安裝與升級

適用於連不到 GitHub 與 PyPI 的 Wazuh Manager。在一台有網路的機器上做好一個壓縮檔 —— 程式本身加上它需要的 Python 套件 —— 搬過去,再從裡面執行安裝腳本。整個過程 manager 不會連任何網路。

開始之前

需要準備什麼

  • 一台有網路的機器,有 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。

選定版本。所有版本列在 GitHub Releases; 下文的 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. 有網路的機器 依步驟 1,替新的 X.Y.Z 做一份安裝包。
  2. 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)
  3. 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
  4. 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-phpphp.net 的發行資料在別處下載發行資料檔,複製到 etc/jt-packs/offline/php/,以 --source file://… 讀取。
jt-runtime-vulnCISA KEV 清單;Node.js、Python、OpenVPN 發行資料同上,每個來源各有 file:// 選項。
jt-alert-digestTeams、Slack、Discord、Telegram、LINE郵件(內部 SMTP 轉送)、Zulip、Mattermost 與通用 webhook 在內網即可;雲端管道經 https_proxy,或不要設定。
jt-web只有選用的 Cloudflare 封鎖設定 proxy=,或不要啟用;nginx 封鎖離線可用。
jt-container-vulnTrivy 映像與弱點資料庫,在每台 Docker 主機上複製到內部 registry,讓掃描程式指向它。
jt-docker、jt-vc-portalDocker 主機上的 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。若希望被覆蓋的原始檔案被還原, 請先從「規則套件」分頁移除已安裝的套件。

遇到其他問題?請看安裝與升級疑難排解。