ROAMSWITCH SERVER 1.10.6 · 最後更新:2026-09-26

RoamSwitch伺服器版操作手冊

云 VPS(AWS、GCP、Azure、Linode、DigitalOcean)、裸机数据中心和容器主机的官方安装、部署和操作参考。

1. 概述及要求

RoamSwitch 伺服器版是一個 無頭(零 GUI 依賴)自主防禦和完整性監控套件 ,專為暴露於公共互聯網的 Linux 伺服器而設計。

與基於 Wi-Fi 狀態動態切換設定檔的用戶端版本不同,伺服器版本強制執行 入站預設丟棄、關鍵路徑檔案完整性監控 (FIM)、預防性核心 LPE 緩解(Frag Gap)、eBPF 執行時威脅偵測、SSH 鎖定預防和自動多通道緊急警報(Telegram / LINE / Webhook)__X、SSH 鎖定。

零遙測原則(不傳送任何使用者資訊,預設的對外通訊只有接收簽章資料)
RoamSwitch 不會把您伺服器的 IP 位址、連接埠資訊、檔案雜湊、系統日誌與診斷結果傳送給廠商或雲端。常駐程式執行檔本身沒有內建 TLS / HTTP 用戶端。預設對外的通訊,除套件管理員的更新外,只有簽章資料的匿名取得(cve_kernel_map_updates_enabled,預設開啟)。取得的是核心 CVE 資料、Web 規則,以及在 Ubuntu 伺服器上用於作業系統套件 CVE 比對的 Ubuntu 套件 CVE 資料。roamswitch-updater 從 lafine.net 以 HTTPS GET 接收附 Ed25519 簽章的資料(簽章清單每天確認一次,CVE 資料本體約每 30 天一次,Web 規則只在清單版本更新時取得),不含查詢字串與 Cookie,能表明軟體身分的請求標頭只有固定的 User-Agent: RoamSwitch-Updater,也不會傳送任何有關本主機的資訊。可用 roamswitch server config set cve_kernel_map_updates_enabled false(或設定精靈、伺服器 TUI)關閉,關閉後稽核仍基於內建基準運作,但 Ubuntu 伺服器上的作業系統套件 CVE 比對會顯示「本機 CVE 資料未取得」。除此之外的對外通訊,僅限維運人員明確啟用的項目:通知(Telegram / LINE / Webhook)、npm 簽章驗證(npm_audit_signatures_enabled。僅在執行指令時),以及事件轉送(forward_enabled,預設關閉。§16)。事件轉送只會傳送到維運人員指定的自己組織的目的地(SIEM、syslog、Webhook),TLS 的 syslog 透過系統的 openssl 傳送,結構化 Webhook 透過 curl 子行程傳送。此外,Sensor 配對(sensor_pairing_enabled,預設關閉)與隨附的獨立工具 accessscope 的 LLM 串接(預設關閉;在命令列中僅當指定 --llm 時)也只有在維運人員啟用時才會對外連線。例外清單見 Server Edition 安全設計文件的 Zero Telemetry 一節。

系統需求

  • 支援的發行版:Ubuntu 22.04 / 24.04 LTS、Debian 12+、AlmaLinux / Rocky Linux / RHEL 9+、Fedora 39+、openSUSE Leap 15.5+、Raspberry Pi OS(64 位元)
  • 架構:x86_64 (amd64) 或 aarch64 (arm64)
  • Kernel:Linux 5.10+(建議nftables、cgroups v2、eBPF BTF)
  • Footprint:20–30 MB 駐留內存,空閒/正常工作負載期間 <0.1% CPU

2. 安裝步驟

使用官方簽署的儲存庫可確保透過標準系統套件管理器自動解決相依性並進行無縫更新。

2.1 APT(Ubuntu / Debian / Raspberry Pi 作業系統)

# 1. 註冊儲存庫簽署金鑰
curl -fsSL https://lafine.net/apt/roamswitch-archive-keyring.asc \
  | sudo gpg --dearmor -o /usr/share/keyrings/roamswitch-archive-keyring.gpg

# 2. 新增儲存庫
echo "deb [arch=amd64,arm64 signed-by=/usr/share/keyrings/roamswitch-archive-keyring.gpg] https://lafine.net/apt stable main" \
  | sudo tee /etc/apt/sources.list.d/roamswitch.list

# 3. 安裝
sudo apt update && sudo apt install roamswitch-server

2.2 DNF / RPM(Fedora / RHEL / AlmaLinux / Rocky Linux)

# 1. 匯入 GPG 金鑰
sudo rpm --import https://lafine.net/rpm/RPM-GPG-KEY-roamswitch

# 2. 新增儲存庫設定檔
sudo curl -fsSL -o /etc/yum.repos.d/roamswitch.repo https://lafine.net/rpm/fedora/roamswitch.repo

# 3. 安裝
sudo dnf install roamswitch-server

2.3 openSUSE(zypper)

sudo rpm --import https://lafine.net/rpm/RPM-GPG-KEY-roamswitch
sudo zypper addrepo https://lafine.net/rpm/opensuse/roamswitch.repo
sudo zypper refresh && sudo zypper install roamswitch-server
包互斥(衝突)
客戶端版本 (roamswitch) 和伺服器版本 (roamswitch-server) 聲明相互的套件衝突。在無頭伺服器環境中始終選擇 roamswitch-server。

3. 初始設定和服務驗證

3.1 服務狀態

安裝後,roamswitch-server.service 立即啟動並在系統引導時啟用。

sudo systemctl status roamswitch-server.service

3.2 互動式設定嚮導

使用以下指令啟動互動式設定精靈,以互動方式設定連接埠、維護來源 IP、通知管道與圍堵操作(按 Enter 採用各項預設值)。

sudo roamswitch server setup
  1. 連接埠:分別以逗號分隔輸入 SSH 維護連接埠(預設 22)與公開服務連接埠(預設 80,443)。
  2. 指定維護來源 IP:指定 SSH 跳板機或監控來源的 IP / CIDR(例如 203.0.113.50/32)。精靈中為必填項,不能留空。若要允許所有 IP 的 SSH,請輸入 ANYWHERE(此時隔離期間管理用 SSH 也會向全世界開放)。
  3. 通知管道設定:分別啟用 Telegram Bot、LINE Messaging API、通用 Webhook(Slack / Discord / Teams)。
  4. eBPF 重大事件時的回應:選擇 isolate(隔離主機)/ freeze(凍結該行程)/ alert_only(僅通知)。儲存後會確認發送測試通知並重新啟動服務。
  5. CVE 資料自動更新(預設 y):選擇是否讓容器隔離稽核所使用的核心 CVE 資料庫、Web 規則,以及在 Ubuntu 伺服器上用於作業系統套件 CVE 比對的 Ubuntu 套件 CVE 資料,從 lafine.net 匿名取得(簽章清單每天確認一次,CVE 資料本體約每 30 天一次,Web 規則只在清單版本更新時取得;僅 HTTPS GET,不含查詢字串與 Cookie,能表明軟體身分的請求標頭只有固定的 User-Agent: RoamSwitch-Updater,並驗證 Ed25519 簽章)。不會傳送任何有關本主機的資訊。這是伺服器版預設開啟的唯一對外通訊,選 n 即可停止(稽核本身仍會基於內建基準運作,但 Ubuntu 伺服器上的作業系統套件 CVE 比對會顯示「本機 CVE 資料未取得」)。如果現有的 server.conf 中已將其關閉,預設答案仍為 n。
  6. File Scan Guard 設定:設定是否為郵件中繼、共用資料夾、上傳目標啟用病毒掃描(§13)及目標目錄。可選功能,預設關閉。
  7. Resource Guard 設定:設定是否啟用偵測網路公開服務持續 RSS 增長(記憶體洩漏/DoS)或當機迴圈的資源耗盡防護。
  8. 常駐核心防護說明:顯示無需透過精靈、始終生效的核心防護功能清單,如入站預設拒絕、FIM、eBPF 整合等(無需輸入)。
  9. 調查代理協作(investigation)設定:設定是否將 eBPF 重大事件,或關鍵路徑 FIM/相依鎖定檔篡改偵測(均為僅通知判定時)的初步調查自動委託給外部 AI 代理 CLI(Claude Code / agy / Codex CLI / OpenCode,或自訂指令)(§10.1)。預設關閉。
Telegram Chat ID 注意事項
超級群組的 Chat ID 是以 -100 開頭的負數(例如 -1001234567890)。可在 curl -s "https://api.telegram.org/bot<token>/getUpdates" 回應中的 "chat":{"id":...} 欄位確認正確的值。

3.3 34項伺服器安全審計

sudo roamswitch status --server

對防火牆規則、Frag Gap 緩解、Yama LSM 限制、權限和 Docker 連接埠暴露執行即時 34 項檢查審核,產生 0-100 的安全評分和等級(S 到 C)。

為便於合規報告,每個檢查項目現在還會標註 NIST CSF 2.0 的功能/類別(適用時必定標註),以及在存在高置信度對應時的 CIS Controls v8 管控編號。

4. 防火牆和連接埠規則

設定檔 /etc/roamswitch/server.conf 為保護機密資訊,強制要求權限為 0600(僅 root 可讀寫)。格式為扁平的 key=value,形如 [network] 的區段標題列會被忽略。

# --- 防火牆 ---
ssh_ports=22                     # SSH 管理連接埠(緊急隔離時也保留)
allowed_ports=80,443             # 公開服務連接埠
whitelist_ips=203.0.113.10/32    # 維護來源 IP / CIDR(留空 = 全部允許,舊名 admin_source_ips 亦可)
protect_docker_ports=true        # DOCKER-USER 保護(阻止容器繞過防火牆)
preserve_ssh_on_isolation=true   # 緊急隔離時也保留 SSH 管理通道(設為 false 則完全阻斷)

# --- eBPF 執行時防護 ---
action_on_critical=isolate       # isolate | freeze(SIGSTOP+網路阻斷) | alert_only
ebpf_socket_path=/run/roamswitch/events.sock

# --- Egress / C2 阻擋與 DNS 黑洞 ---
egress_ip_blocklist_enabled=true # 預設 true。套件隨附的種子僅包含 JPCERT/CC 公布的 3 個攻擊伺服器;在安裝情報來源之前不會阻擋其他任何內容
metadata_watch_enabled=true      # 預設 true。非 root 程式/容器連線雲端中繼資料時通知(僅記錄、不阻斷;用於發現 SSRF)
metadata_watch_allow_users=      # 正常使用中繼資料服務的帳號(名稱或數字 ID,逗號分隔;root 一律豁免)
dns_sinkhole_enabled=false       # 預設 false(避免破壞內部 DNS/split-horizon 環境)
dns_sinkhole_provider=quad9      # quad9 | cloudflare | adguard | cleanbrowsing

# --- 容器隔離 CVE 資料(預設開啟) ---
cve_kernel_map_updates_enabled=true # 預設 true。預設開啟的唯一對外通訊(簽章的核心 CVE 資料、Web 規則,以及 Ubuntu 伺服器上的 Ubuntu 套件 CVE 資料;清單每天一次,CVE 資料本體約每 30 天一次;匿名‧僅接收‧驗證簽章)。設為 false 即停止

# --- 通知 ---
telegram_enabled=false
telegram_bot_token=
telegram_chat_id=
line_enabled=false
webhook_enabled=false
webhook_url=
webhook_block_private_addresses=false   # opt-in SSRF guard
webhook_allow_addresses=

# --- 系統 ---
language=ja
fim_check_interval_secs=300      # 舊名 scan_interval 亦可
isolation_hard_cap_secs=3600     # 高信賴度隔離進入降級模式前的秒數(0 = 維持到解除)

若直接編輯了設定,需重新啟動服務才會生效(roamswitch-server 不支援 reload):

sudo roamswitch server restart

4.1 依嚴重程度設定政策(guard.yaml,選用)

若僅靠 action_on_critical 無法滿足更精細的控制需求,可建立 /etc/roamswitch/guard.yaml(發布範本位於 /etc/roamswitch/guard.yaml.example)。若該檔案不存在,會依 server.conf 中的 action_on_critical 自動合成等效政策,不影響現有運作。

policies:
  on_warning:
    action: log_and_notify
  on_critical:
    server_action: isolate_process
    kill_process: true
    fallback_to_host_isolation_after_retries: 3   # 同一行程再次發生時自動升級為主機隔離
  on_emergency:
    action: isolate_host_all
    kill_process: true

server_safeguards:
  maintenance_ssh_ports: [22]
  safety_timer_secs: 300   # 低信賴度隔離自動復原前的秒數(0 為停用)。不適用於高信賴度隔離(見下文)

隔離的自動解除(依信賴度):如果僅靠固定計時器解除,會被只需等待的攻擊者突破。因此,隔離的觸發條件依信賴度分類。(1) 低信賴度(eBPF 的 Error / Warning 及以下、通用的連接埠異常等):經過較短的計時器(safety_timer_secs,預設 300 秒)後全部復原。(2) 高信賴度(金絲雀竄改、勒索軟體式的大量改寫、eBPF 的 Critical / Emergency / Alert、同一規則的重複升級):不會靜默復原。在較短的計時器之後仍會持續重新確認原因,僅在確認原因消失時才會附帶通知解除。如果無法確認、也沒有 ack,並達到上限(server.conf 的 isolation_hard_cap_secs,預設 3600 秒,0 = 無上限),則進入降級(DEGRADED)模式。(3) 降級模式:除維護 SSH 連接埠與白名單 IP 的管理路徑之外,新的通訊仍保持阻斷,絕不會因時間流逝而自動放開。解除的方式只有:重新確認原因消失、明確的 ack(降級期間的 ack 表示解除),或 sudo roamswitch emergency-restore。無論哪種隔離,管理路徑(maintenance_ssh_ports 與 whitelist_ips)以外的已建立連線(攻擊者已經建立的 C2 或反向 Shell 等)都會被阻斷。每次狀態轉換都會記錄到事件時間軸,並以 10 種語言發出通知。

sudo roamswitch server ack

roamswitch server ack 在 FULL 隔離期間會保持隔離嚴格不變並做出確認回應(視為維運人員已接手,停止進入降級或自動解除),在降級期間則會解除隔離。

4.2 Egress / C2 阻擋與 DNS 黑洞

設定 egress_ip_blocklist_enabled=true(預設)後,會透過 nftables 封鎖連往已知惡意 IP 的對外連線。情報來源優先使用 /var/lib/roamswitch/threatfeed/malicious_ips.txt(由更新機制管理),不存在時使用套件隨附的種子(/usr/share/roamswitch/threatfeed/);兩者擇一,不會合併。種子僅包含 JPCERT/CC 在 2026 年 10 月 15 日的報告(針對 Web 服務與 API 的攻擊)中公布的 3 個攻擊伺服器位址(210.149.87.120, 118.26.36.16, 69.10.51.162)。租用伺服器的位址可能被重新分配給他人,因此若正常的連線目的地被封鎖,請檢查該檔案中對應的行。

將 dns_sinkhole_enabled=true 設為啟用後,會強制透過過濾型 DNS 解析器(Quad9 / Cloudflare / AdGuard / CleanBrowsing)解析網域,阻擋對已知惡意網域的解析。因可能破壞內部 DNS 或 split-horizon 環境,預設值為 false。

metadata_watch_enabled가 켜져 있으면(기본), root가 아닌 프로그램이나 컨테이너가 클라우드 메타데이터 주소(169.254.169.254, 169.254.170.2, 100.100.100.200, fd00:ec2::254)에 새로 연결할 때만 nftables 테이블 inet roamswitch_metadata_watch가 커널 로그에 기록하고, 서버 데몬이 계정(컨테이너는 출발지 주소)별로 하루에 한 번 알립니다. 기록과 알림만 하며 차단하지 않습니다. 공격자가 자신의 서버 URL(302로 내부 주소에 전달)을 넘기는 수법에서는 접근 로그에 외부 URL만 남으므로, 두 번째 연결은 이 아웃바운드 통신에서만 볼 수 있습니다. 클라우드 역할을 정상적으로 쓰는 앱도 보고되므로 metadata_watch_allow_users에 계정을 넣어 제외할 수 있습니다(컨테이너는 제외 불가).

4.3 入站連接埠掃描偵測防護

透過將 nftables 日誌規則與 journald 進行比對,偵測在短時間內連線了大量不同連接埠的來源 IP(預設啟用)。高置信度的掃描來源可在一定時間內自動封鎖。與 RoamSwitch Sensor 一起使用時(與 §10.1 是不同的功能——已配對 Sensor 的全連接埠稽核探測會作為誤判對策被排除),Sensor 一側的 IP 會自動排除在外。

# --- 入站連接埠掃描偵測(預設啟用) ---
port_scan_detect_enabled=true              # false 表示停用
port_scan_detect_min_distinct_ports=15     # 連線到不少於此數量的不同連接埠時判定為掃描
port_scan_detect_window_secs=300           # 判定的統計視窗(秒)
port_scan_block_enabled=true               # 自動封鎖偵測到的掃描來源 IP
port_scan_block_duration_secs=600          # 自動封鎖的持續時間(秒)

可透過 roamswitch port-scan 指令查看偵測歷史。

4.4 DNS 通道偵測防護

僅針對本機自身送出的 DNS 流量(UDP/TCP 53 埠),透過專用的 NFQUEUE 進行檢查。凡標籤長度超過 40 位元組且夏農熵超過 3.8 的查詢,或查詢類型為 TXT/NULL 記錄的查詢,均視為可疑形態,且僅當最近 60 秒內此類查詢達到 10 次時才發出通知(同一條件下的重複通知設有 300 秒冷卻時間)。其目的是偵測 iodine、dnscat2 等 DNS 通道/資料外洩工具所特有的查詢模式。底層 nftables 規則帶有與其他 DNS 類防護相同的 bypass 旗標,因此即使本防護停止或無回應,也絕不會妨礙 DNS 網域解析。本功能僅用於通知,不會自動進行封鎖。與其他設定項相同,dns_tunnel_detect_enabled 的變更需重新啟動服務後才會生效。

# --- DNS 通道偵測(預設啟用) ---
dns_tunnel_detect_enabled=true              # false 表示停用

4.5 SSH 暴力破解防護

在 sshd 的登入失敗寫入日誌的瞬間讀取,並依來源位址計數(預設啟用)。達到設定次數(預設 600 秒內 6 次)的來源位址,會透過 nftables 的 inet roamswitch_sshguard 資料表,只丟棄其發往 SSH 連接埠的新連線。首次封鎖 1 小時,同一來源每再犯一次延長為 4 倍,上限 7 天。封鎖的同時,也會切斷該來源已建立到 SSH 的連線(刪除其 conntrack 項目,並新增一條丟棄回應方向封包的規則)。只有既沒有已驗證工作階段、也沒有公開金鑰登入成功紀錄、也不在豁免之列的來源才會被封鎖,且在切斷前會再確認一次,因此已驗證的工作階段與豁免的來源不會被切斷。不會向外部傳送任何資料,只在本機執行 journalctl、nft、loginctl 等指令。

日誌透過 journalctl -f 即時讀取。journald 會記錄寫入者行程,因此 sshd 以外寫入的行會被忽略。沒有 journald 的環境會追蹤 /var/log/auth.log 或 /var/log/secure,但只要是能使用 syslog 的本機使用者,就能偽造這些檔案中的行,導致第三方被封鎖;有 journald 的環境請保持 ssh_guard_log_source 的預設值 auto。計入的失敗包括密碼錯誤、不存在的使用者、報出使用者名稱後在驗證前中斷、超過嘗試次數,以及 PAM 驗證失敗。公開金鑰的失敗(Failed publickey)不計入,因為持有多把金鑰的合法用戶端每次都會產生。來源位址取自行尾的 from <IP> port <N>。攻擊者可以在使用者名稱中寫入任意字串,但寫入偽造的來源位址並不會讓第三方被封鎖。IPv6 以 /64 合併計數,封鎖也以 /64 為單位(若該 /64 含有閘道等必須保護的位址,則只封鎖來源的那一個位址)。

不會封鎖的對象包括:閘道、DNS 解析器、本伺服器自身、迴路位址、whitelist_ips、ssh_guard_allow、已通過驗證且目前仍開啟 SSH 工作階段的來源位址、最近 30 天內(ssh_guard_trust_key_days)以公開金鑰驗證成功過的來源位址(密碼登入成功不計),以及已配對的 Sensor。這些來源即使失敗次數累積,也只留下紀錄。私有位址不豁免,因為內部遭入侵的裝置同樣可能成為暴力破解的發動方。僅在驗證之前保持連線開啟的來源,同樣不豁免。

當 fail2ban(sshd 的 jail 已啟用)或 CrowdSec(firewall bouncer 正在執行)已在保護 sshd 時,為避免對同一位址重複封鎖,本防護會讓出封鎖,只做偵測與通知(ssh_guard_yield_to_fail2ban,預設 true)。ssh_guard_block_enabled=false 時同樣只偵測與通知。僅在以下情況通知:封鎖時(只偵測時為達到門檻時),以及失敗累積的來源位址登入成功時(嚴重。可能已被暴力破解成功,不會切斷工作階段)。不會為每一次失敗通知,1 小時內超過 10 個的來源位址會合併為一則通知。

以 roamswitch server bans 檢視封鎖清單(支援 --json;清單只有 root 能讀取,所以要加 sudo),以 sudo roamswitch server unban <IP | IPv6 的 /64 | --all> 解除。解除後,該來源位址的失敗計數也會清除。伺服器重新啟動後,封鎖會連同剩餘時間一併還原。roamswitch emergency-restore 不會解除 SSH 封鎖(恢復網路並不構成放回曾在猜測密碼的對象的理由);復原選單(roamswitch recover)與解除安裝則會連同整個資料表一併刪除。MCP 的 get_ssh_guard_incidents 為唯讀,沒有解除封鎖的工具。在 Server TUI 中,可於「事件」畫面的「SSH 暴力破解」檢視並解除封鎖(以 root 啟動時。§17)。

roamswitch server bans
sudo roamswitch server unban 203.0.113.9
sudo roamswitch server unban --all

設定項共有 10 個,都以 ssh_guard_ 開頭(§18.1)。例如以 sudo roamswitch server config set ssh_guard_max_failures 10 修改,生效需要執行 sudo roamswitch server restart。要停止整個防護,設定 ssh_guard_enabled=false;只偵測與通知,設定 ssh_guard_block_enabled=false。診斷(34 項)中的「SSH 暴力保護」,在本防護執行並進行封鎖時也會通過。

限制:只反覆產生公開金鑰失敗的嘗試不計入。分散在大量來源位址上的暴力破解依來源逐一計數,因此在某個來源達到門檻之前不會被阻止。根本的對策是停用密碼驗證,只允許公開金鑰驗證。

5. SSH 鎖定預防故障保護

由於防火牆配置錯誤而導致的意外鎖定是無法容忍的操作災難。 RoamSwitch 伺服器版包含多層保護措施:

  • 已建立/相關無條件透過:在規則重新載入期間,活動會話永遠不會被刪除。
  • Air-Gap 隔離時保留 SSH:即使在偵測到異常並緊急隔離的情況下,透過 preserve_ssh_on_isolation = true,僅維護 SSH 連接埠與管理來源 IP(whitelist_ips)的管理路徑會保持新建與已建立的通訊,無須現場處置即可調查原因並復原。除此之外的已建立連線(攻擊者已經建立的 C2、資料外送、反向 Shell)都會被阻斷。如果未指定管理來源(whitelist_ips 與 guard.yaml 中的允許項皆為空),隔離期間維護 SSH 連接埠仍會接受來自任意來源的新連線,伺服器啟動時會輸出警告。設為 preserve_ssh_on_isolation=false 時,SSH 也會一併阻斷。1.10.4 及之前的伺服器版存在缺陷,隔離規則會丟棄 SSH 的回應,因此隔離期間維運人員的 SSH 無法使用。該缺陷已在 1.10.5 修正。
  • Atomic nftables 載入並回滾:規則語法錯誤立即觸發零停機回滾到先前已驗證的規則集。

6.容器保護(Docker/Podman)

Docker 的預設行為會建立繞過標準主機防火牆的自訂 iptables 規則,將容器連接埠(例如 -p 8080:8080)直接暴露到網際網路。

當 protect_docker_ports=true(預設)時,RoamSwitch 會依照 Docker 的防火牆方式,使送往容器的流量除了目的為 ssh_ports 與 allowed_ports 中所含連接埠的之外,都無法從外部到達。在 iptables / iptables-nft 方式下,會在 DOCKER-USER 鏈的開頭插入檢查規則(除 IPv4 外,如果啟用了 Docker 的 IPv6,也會透過 ip6tables)。在 Docker 29 以上的原生 nftables 方式(不存在 DOCKER-USER)下,會在早於 Docker 鏈的 forward 掛鉤上建立專用的 inet roamswitch_docker_guard 資料表(一個 inet 資料表同時處理 IPv4 / IPv6)。判定依據是 DNAT 之前的原始目的連接埠(ctorigdstport),且只針對來自外部介面的通訊,因此不會影響容器發出的對外通訊與容器之間的通訊。可防止意外的開發用資料庫容器等被暴露到外部。

此防護具有冪等性,並且每分鐘自我修復一次。即使 dockerd 在 RoamSwitch 之後才啟動、Docker 重新啟動或重新載入導致規則被改寫、手動執行了 nft flush 或 nftables 資料表遺失,也會在不動到目前有效防護的前提下重新設定。

此外,監視 docker events 的即時防護會在使用 --privileged 啟動的容器,或掛載了 /var/run/docker.sock 的容器(容器逃逸風險)啟動後立即偵測並通知。另外,容器 exec 防護(container_exec_guard_enabled,預設開啟)會使用 YARA 檢查容器內執行檔的執行(即使執行後刪除檔案的規避手法,由於是從已開啟的檔案描述子讀取內容,同樣可以檢查)。該防護也會在啟動時替已經在執行的容器加上標記,並自動跟進新容器。兩者都只做通知,不會自動阻斷。也可在 Docker 29 上運作(1.11.1 起支援)。事件訂閱持續失敗時,重新連線的間隔會從 5 秒拉長到最長 5 分鐘。

7. 關鍵路徑檔案完整性監控(FIM)

使用 SHA-256 監控 150 多個重要檔案(/bin/login、/usr/bin/sudo、/usr/sbin/sshd 等重要執行檔,/etc/shadow、/etc/sudoers 等驗證設定,以及 systemd 單元)。

監控範圍不只是單一檔案。在重要目錄(/etc/pam.d、/etc/sudoers.d、/etc/ssh/sshd_config.d、/etc/cron.*、/etc/systemd/system、/etc/ld.so.conf.d、/etc/profile.d、/root/.ssh(known_hosts 除外))中,還會偵測是否出現了新檔案;所有可登入帳號的 authorized_keys、/etc/ld.so.preload(正常情況下不存在,出現即為本機 rootkit 的跡象)以及 RoamSwitch 自身的執行檔也在監控之列。snapd 自動產生的暫時單元(snap-*.mount 等)不在監控範圍內。新檔案偵測僅在包含此範圍的基準上有效,因此升級後請執行一次 sudo roamswitch fim update。以非 root 身分執行 fim verify 時無法讀取的檔案,會按「因無法讀取而略過」處理,而不是視為竄改。

7.1 手動哈希驗證

sudo roamswitch fim verify

7.2 事件驅動偵測(即時)

受監控檔案透過 fanotify(FAN_CLASS_NOTIF,寫入完成事件)被逐一監視,無需等待下一次週期性掃描,竄改發生的瞬間即會重新驗證雜湊。週期性掃描(預設 fim_check_interval_secs=300 秒間隔)仍會作為漏偵測事件的後備保障並存。把新檔案放到同一名稱之下的編輯(install、sed -i 等)也能偵測到,通知中會附上做出修改的行程與 SSH 登入(§7.5)。

7.3 作業系統更新時自動基線同步

在 Debian/Ubuntu 上,安裝套件時會自動設定 /etc/apt/apt.conf.d/99roamswitch-fim 的 DPkg::Post-Invoke 掛鉤。在 Fedora/RHEL/Rocky/AlmaLinux/openSUSE 上,監控 /var/lib/rpm 的 systemd.path 單元(roamswitch-fim-update.path)承擔相同職責。

在 Debian/Ubuntu 上,/etc/apt/apt.conf.d/99roamswitch-fim 附加一個 DPkg::Post-Invoke 掛鉤。透過 sudo apt upgrade 進行的合法軟體包更新會自動刷新 FIM 基線,從而消除誤報警報。

sudo roamswitch fim update

守護程式首次啟動並建立基準線時,若套件管理員(apt/dpkg、dnf/rpm、zypper 或 pacman)正在作業,會先等待其結束,最長 120 秒,再建立基準線。即使與 Apache 等在同一次 apt install 中安裝,dpkg 正在處理的暫存檔(如 *.dpkg-new)也不會進入基準線,因此不會在隨後的驗證中被誤判為竄改(1.11.18 及之後)。超過 120 秒仍未結束時,會記錄警告並照常建立基準線。

7.4 蜜罐憑證(Honeytokens)

守護行程啟動時,利用其以 root 權限執行的特性,在 /root 下冪等地部署三種誘餌憑證檔案(蜜罐憑證):.aws/credentials、.ssh/id_rsa、.docker/config.json。若該路徑已存在真實檔案,則絕不覆寫。背景監視行程透過 inotify 偵測對這些檔案的讀取存取,一旦偵測到即視為入侵後的憑證偵察行為(MITRE ATT&CK T1552:Unsecured Credentials),立即傳送 Critical 等級通知並記錄到事件時間軸。預設開啟,可以用設定項 honeytokens_enabled(設為 false 會停止部署和監視,已放置的誘餌會保留)和 honeytokens_home(部署位置,預設 /root)變更。截至 1.10.4 的發行套件未包含此功能所需的 roamswitch-honeytokens,因此以套件安裝的環境中該功能並未執行。自 1.10.5 起已隨附,伺服器版中 systemd 沙箱阻擋寫入 /root 的問題已在 1.10.10 修正。自 1.11.1 起,RoamSwitch 本身執行的 docker 指令,會以空的專用目錄(root 時為 /run/roamswitch/docker-config)作為 DOCKER_CONFIG 啟動,因此不會對誘餌 .docker/config.json 產生反應(在此之前,守護行程的監視或 roamswitch status --server 可能會讀取誘餌而誤報偵測)。其他程式讀取時,會和以往一樣偵測。

若偵測到對任一蜜罐憑證的實際存取,考量攻擊者可能進一步深入探查,RoamSwitch 會額外部署與之相關的新誘餌(例如:觸及 .aws/credentials 後會部署 .aws/config;觸及 .ssh/id_rsa 後會部署 .ssh/config;觸及 .docker/config.json 後會部署 .kube/config),每次觸發最多 2 個,全部觸發合計最多 6 個。若在事件調查期間發現 /root 下出現這些陌生檔案增多,屬於預期行為。

7.5 入侵路徑(誰、透過哪一次 SSH 登入做了修改)

在通知檔案變更的訊息(關鍵路徑 FIM 與鎖定檔 FIM)中,附上做出修改的行程(帳號、可執行檔、指令),以及該行程所屬的 SSH 登入(來源 IP 與連接埠、登入時間、驗證方式、公開金鑰指紋)(預設啟用,fim_intrusion_context_enabled)。讀到事件的當下,就會為寫入行程的 /proc/<pid>(可執行檔、使用者、loginuid、sessionid、cgroup、父行程鏈)拍下快照,因為 tee、sed 這類行程轉瞬即逝。已經結束而無法取得快照的行程,由執行記錄器(啟用時)的記錄補齊。與登入的關聯,優先使用 SSH 防護的工作階段表,沒有時則從 logind 與 journald 的 Accepted 行中查找。即使停用 SSH 防護也能運作。不會向外部傳送任何內容。

只信任核心回報的值:可執行檔取自 /proc/<pid>/exe(不是 argv[0]),登入取自 loginuid(登入時只設定一次,並會跨越 sudo、su 繼承)與 cgroup 的 session-N.scope,再加上父行程鏈。comm、命令列、環境變數這類行程自己可以改的值,只用於顯示,不用於判定。只是自稱 sshd 的行程,不會被當作 SSH 登入。通知會區分三種答案:找到了(來源、時間、驗證方式、金鑰);「沒有找到 SSH 登入」(查明是 systemd 服務、容器、本機登入工作階段或不屬於任何登入工作階段的行程);「無法查明登入路徑」(行程已不存在且執行記錄器中也沒有、logind 沒有回應、變更由定期掃描發現因而不知道行程,等等)。無法查明的情況,絕不會寫成「不是登入」。即使查詢失敗,通知也一定會發出。

/etc/ssh/sshd_config: modified
  行程: root(登入的帳號: admin) / /usr/bin/tee / 指令: tee /etc/ssh/sshd_config (pid 4121)
  SSH 登入: 這是 admin 於 2026-10-17 03:12:08 從 203.0.113.25:51544 登入的連線(認證: publickey, 金鑰 SHA256:AbCdEf0123456789)

/etc/sudoers: modified
  無法查明登入路徑(這是定期檢查發現的變更,不知道是哪個行程做的)

把新檔案放到同一名稱之下的編輯方式也能偵測到,例如 install、sed -i,以及同一目錄中的 cp 加 mv。依檔案設定的標記掛在 inode 上,所以這類編輯以前不會產生事件。現在,監視對象檔案所在的目錄也會被設定標記,同一目錄中另一個名稱的檔案被關閉時,幾毫秒後會重新查詢名稱。限制:在其他目錄寫好再用 mv 移入的檔案,要等定期掃描(fim_check_interval_secs)才會發現。這時不知道寫入的行程是誰,通知中也會如此說明。

除通知外,記錄還會保存在事件時間軸(類型 fim)與 /var/lib/roamswitch/fim_intrusions.json(僅 root 可讀,最新 100 筆)中。MCP 的 verify_fim 會以新增欄位 recentIntrusionContext 傳回(僅以 root 執行時)。是否遭竄改的判定不變。限制:停用執行記錄器且寫入行程極其短命時,無法得知可執行檔,此時會顯示父行程的可執行檔與命令列。持久化監視(persistence_watch)的通知不含行程資訊,因此不附帶入侵路徑。入侵路徑只顯示到做出修改的行程及其登入為止,入侵的入口本身(被利用的漏洞,或金鑰是如何被竊的)無法得知。要關閉,請設定 fim_intrusion_context_enabled=false。

8. eBPF 運行時防護和 Falco 集成

掛鉤內核空間 eBPF 事件 (Falco / Tetragon) 以偵測 Frag Gap 核心權限升級、容器逃逸和未經授權的反向 shell。

8.1 抗膨脹架構

為避免傳統資安工具中常見的「syslog 爆炸式膨脹」與「磁碟空間被佔滿」問題,RoamSwitch 透過 UNIX 網域通訊端 /run/roamswitch/events.sock 與 Falco 直接對接。該通訊端以僅 root 可用(0600)的方式建立,能寫入的只有以 root 執行的 Falco(無須額外的權限設定)。

  • 捆綁的 /etc/falco/config.d/99-roamswitch-optimized.yaml 將事件直接串流到守護程式中,磁碟 I/O 為零。Falco 的輸出在該設定中是透過 socat 傳給 socket 的,因此 Server Edition 的 deb / rpm 套件會把 socat 作為建議套件(Recommends)一併安裝(不使用 Falco 時則不需要)。
  • /etc/logrotate.d/roamswitch-falco 確保任何後備檔案輸出的每日乾淨輪替。

8.2 自主收容

一旦偵測到嚴重攻擊,RoamSwitch 會立即發出 SIGSTOP 來凍結違規進程 PID 並套用 nftables 氣隙隔離。

8.3 入侵證據自動保全(Forensic Evidence Capture)

當 eBPF 執行時防護執行了針對處理程序的圍堵操作(以 SIGSTOP 凍結並切斷網路)時,會自動建立證據保全包。依照 §4.1 的預設政策,Critical 等級事件會走此路徑;而對整台主機進行隔離的 Emergency 等級事件目前不會產生此類證據包。證據包內容包括:在預設路由介面上進行的、盡力而為的約 30 秒定界封包擷取(若未安裝 tshark,則僅跳過此項並記錄該情況),以及(在已知目標 PID 時)一份 /proc/<pid> 快照,包含 status、cmdline、maps、environ(名稱中包含 KEY/TOKEN/SECRET/PASSWORD 的值會被替換為 [REDACTED])、已開啟檔案描述符的連結目標清單,以及直至 PID 1 的祖先處理程序鏈。隨附有記錄了每個已取得檔案 SHA-256 雜湊值的 manifest.json,可供日後進行竄改驗證。

儲存位置為 /var/lib/roamswitch/incident-evidence/<時間戳>-<ID>/。證據包不會自動清除。為避免佔用磁碟空間,如需明確刪除超過保留期限(預設 30 天)的舊證據包,請執行:

sudo roamswitch-incident-capture prune [--keep-days N]

此外,您也可以在無需等待圍堵動作觸發的任意時刻手動取得快照:

sudo roamswitch-incident-capture snapshot [--pid PID] [--reason TEXT] [--json]

8.4 隔離速度的量測與警報通道的心跳檢測

eBPF 隔離的準確度與速度,取決於感測器(Falco 或 Tetragon)的規則。實際上,Falco 0.45.0 的標準規則(29 條)裡,沒有偵測主機上反向 Shell 的規則:針對反向 Shell 的規則只用於容器,其中一部分還會被 RoamSwitch 的 priority: warning 條件丟棄。RoamSwitch 不以規則本身的品質為前提,而是用三件事來彌補:量測隔離所花的時間、定期確認警報通道是否暢通,以及自己也偵測反向 Shell。

隔離延遲的量測:對每個 eBPF 事件,記錄從 Falco 偵測到常駐程式讀到警報的時間(detect_to_receive_ms)、從讀到警報到處置完成的時間(receive_to_action_ms,在隔離呼叫返回之後量測;主機 Air-Gap 則量到規則集載入完畢),以及兩者之和(detect_to_action_ms)。這些值會作為新增欄位出現在 ebpf_incidents.json 與 MCP 的 get_ebpf_incidents 中。隔離行程時的通知會附上一行「從偵測到處置 N 毫秒」。實測(Ubuntu 24.04 虛擬機,Falco 0.45.0,modern eBPF):從偵測到接收 1~2 毫秒,從接收到行程隔離加 SIGKILL 41~62 毫秒(合計 42~64 毫秒),主機 Air-Gap 合計 109 毫秒(在 150 毫秒的目標之內)。數值屬於該虛擬機。Tetragon 在接收時打時間戳,因此沒有 detect_to_receive_ms。

心跳檢測(ebpf_heartbeat_interval_secs。預設 600 秒,0 為停用,啟用時取 60~86400):套件內建 RoamSwitch 自己的 Falco 規則 96-roamswitch-heartbeat.yaml。常駐程式會定期開啟一個僅 root 可用的一次性路徑(/run/roamswitch/heartbeat/ 下的隨機名稱),並量測該規則的警報經由 Falco 輸出返回所需的時間。一次往返就能同時確認規則已載入、Falco 在執行、輸出通道暢通。只有連續兩次確認都沒有返回時(第一次之後 1 分鐘再確認一次),才會發出「規則未載入,或輸出未送達」的警告,且 24 小時內最多通知一次。心跳的記錄行會被直接丟棄,不進入隔離、通知、允許清單與事件記錄。不會向外部傳送任何內容。實測往返為 2~6 毫秒;移除規則後約 164 秒出現警告,恢復後約 75 秒回到正常。

狀態保存在 /var/lib/roamswitch/ebpf_heartbeat.json,由 MCP get_ebpf_incidents 的 heartbeat 欄位與診斷 K-04(eBPF 執行階段代理,診斷項目數仍為 34)讀取。即使 Falco 在執行,只要心跳沒有返回,K-04 就不合格。限制:確認的只是一條規則(open 系列系統呼叫)的往返,無法得知其他規則是否單獨損壞。在兩次確認的間隔(預設 10 分鐘)內損壞的部分,要到下一次確認才會發現。對 Tetragon 不執行。在 Falco 未執行或規則檔缺失的主機上,不做任何確認,也不發任何警告(停止由原有的通知負責)。Falco 每次確認都會向 syslog 寫一行警告(預設設定下每天 144 行)。

8.5 反向 Shell 偵測(RoamSwitch 內建)

不依賴 Falco 的規則,RoamSwitch 自己每 2 秒讀取一次 /proc,尋找標準輸入與標準輸出連到「本機向外部位址建立的同一條 TCP 連線」的 shell 與直譯器(sh、bash、python、perl、ruby、php、node 等)。bash -i >& /dev/tcp/…、python、perl、nc -e、socat exec: 都在偵測範圍內。只有連續兩次都看到的才會回報,且每個行程只報一次。預設只計算指向外部公開位址的連線;指向私有位址(RFC 1918、CGNAT、連結本地)的連線,只有設定 reverse_shell_watch_include_private=true 時才計入(因為 ssh 的 ProxyCommand、容器與本機開發中正常的情況很多)。不檢查迴環位址。由外部接入的連線(inetd 或 socat TCP-LISTEN 所 accept 的連線)也不在範圍內。實測(Ubuntu 24.04 虛擬機)中,bash 的 /dev/tcp、python、perl、nc -e、socat exec: 都在連線建立後約 2.4 秒被偵測到。ssh、帶 ProxyCommand 的 ssh、git over ssh 以及 nc 用戶端不會被偵測。

偵測結果會作為名為 RoamSwitch Reverse Shell 的 Critical 級 eBPF 事件,進入與 Falco 警報相同的通道(允許清單、通知冷卻、guard.yaml 依嚴重度的動作、事件記錄)。預設會隔離該行程並將其終止(kill)。root 所有的反向 Shell 無法依行程隔離,因此與其他 Critical 事件一樣,會一直進行到整台主機的 Air-Gap。如果擔心正常程式被誤判,有兩條退路:reverse_shell_watch_notify_only=true(作為 Warning 只發通知,不隔離也不 kill,預設 false),以及加入允許清單 sudo roamswitch server allowlist add "RoamSwitch Reverse Shell" <行程名稱>。設定鍵有三個:reverse_shell_watch_enabled(預設 true)、reverse_shell_watch_include_private(預設 false)、reverse_shell_watch_notify_only(預設 false)。

限制:偵測依名稱(行程名稱與可執行檔名稱)篩選,因此名稱不是 shell 或直譯器、卻把標準輸入輸出接到 socket 的自製二進位檔,無法被發現。經由迴環位址的連線(例如 ssh -R 的折返)和短於 2 秒的連線不在偵測範圍,主機行程空間中看不到的行程同樣無法偵測。此偵測僅限 Server Edition,Mac 與 Linux 用戶端版沒有。

9. 緊急警報(Telegram / LINE / Webhook)

當發生連接埠異常、FIM 篡改或 eBPF 遏制事件時,立即向外部通知通道發送警報:

[notifications]
language = ja
# Telegram:Bot Token 與 Chat ID
telegram_bot_token = "123456789:ABCdefGHIjklMNOpqrSTUvwxYZ"
telegram_chat_id = "-1001234567890"

# LINE:Messaging API 頻道存取權杖與使用者 ID
line_channel_access_token = "YOUR_LINE_ACCESS_TOKEN"
line_user_id = "U1234567890abcdef1234567890abcdef"

# 通用 Webhook(Slack、Discord、Teams、自建監控平台)
webhook_url = "https://hooks.slack.com/services/T00/B00/XXXXX"

即使未設定這些外部通知管道,已傳送的通知也會在本機保留最近1週。可透過 roamswitch notifications 查看。

拒絕向內部位址傳送 Webhook(選擇啟用):設定 webhook_block_private_addresses=true(預設 false = 維持原行為)後,若通知 Webhook 的目標是迴環、私有(10/8、172.16/12、192.168/16)、連結本機(169.254/16,含雲端中繼資料 169.254.169.254)、ULA(fc00::/7)或 CGNAT(100.64/10)位址(主機名稱則解析結果中有一個符合即可),就拒絕傳送,並將原因寫入記錄與 roamswitch notify-test 的錯誤。2130706433、0x7f.1 等其他寫法以及 IPv4-mapped IPv6 同樣會被辨識,且已驗證的位址會固定給 curl,可防止 DNS rebinding。內部 SIEM 等合法的內部目標以 webhook_allow_addresses=10.20.0.0/16,fd00::/8(以逗號分隔的 CIDR)放行。事件轉送 Webhook 有同樣的一組鍵 forward_webhook_block_private_addresses / forward_webhook_allow_addresses。即使此選項為 false,目標為雲端中繼資料位址時也會記錄警告(不會阻止傳送)。若設定了 HTTP Proxy 環境變數,解析與連線由 Proxy 完成,不在此檢查範圍內。

10.AI代理/MCP整合(模型上下文協定)

RoamSwitch 伺服器版包含 roamswitch-mcp,可讓 AI 代理程式(Claude、Gemini、Cursor)監控基礎設施健康狀況和狀態。

只讀安全保證
為了防止即時注入攻擊損害基礎設施,MCP 介面嚴格是唯讀的。 AI 代理無法透過 MCP 開啟連接埠、取消隔離或變更安全性配置。修復需要經過身份驗證的本地 TTY shell 存取權。

配置範例(`claude_desktop_config.json`)

{
  "mcpServers": {
    "roamswitch": {
      "command": "/usr/bin/roamswitch-mcp",
      "args": []
    }
  }
}

10.1 調查代理協作(investigation,將初步自動調查委託給 AI 代理)

§10 的 roamswitch-mcp 面向「人類透過 AI 用戶端發起的查詢」,而investigation 協作是另一種機制:由守護行程自身在偵測到事件時自主啟動外部 AI 代理 CLI。其對象是被判定為僅通知(未觸發自動隔離或行程凍結)的 eBPF 重大事件,以及關鍵路徑 FIM、相依鎖定檔篡改偵測。啟用後,守護行程會先產生本機啟發式一次判定報告(誤判可能性、依據、下一步調查建議),隨後附帶該報告以子行程方式啟動已設定的 AI 代理 CLI,委託其進行進一步調查與總結。預設關閉。

# 追加到 /etc/roamswitch/guard.yaml(與 server.conf 是不同的檔案)
investigation:
  enabled: true
  command: "claude"                 # "claude" | "agy" | "codex" | "opencode" | 任意自訂指令
  args: ["-p"]                      # 提示詞會自動作為末尾參數附加
  timeout_secs: 180

同樣內容也可在 sudo roamswitch server setup 的互動式精靈(§3.2 最後一步)中設定。可選擇 Claude Code(claude -p)/ agy(agy -p --dangerously-skip-permissions)/ Codex CLI(codex exec)/ OpenCode(opencode run)預設,或任意自訂指令。再次執行時會根據已儲存的設定自動選取對應預設。

關於提示詞注入的注意事項
investigation 聯動會把偵測事件的詳細內容(其中可能包含攻擊者可部分控制的行程名稱、檔案路徑等字串)截斷後,作為 JSON 字串放入 AI 代理的提示詞。做成 JSON 字串後,就無法利用換行和引號偽造分隔線或偽造的指令區。但這並不能消除字串內容被當作指令讀取的可能,因此代理不能以 root 身分執行:沒有指定一般使用者 run_as 的設定不會被精靈(CLI 和 TUI)儲存,常駐程式也不會啟動它。以略過權限確認的模式(如 --dangerously-skip-permissions)啟動工具,會提高惡意輸入使代理執行非預期操作的風險。選擇 agy 時,精靈會顯示此提示。在存在不可信日誌輸入路徑的環境中,建議使用不略過權限確認的工具設定。

在網路中斷期間(如 Air-Gap 觸發時等,相當於 isolate_host_all 的狀態)不會呼叫 investigation 協作。

11. CLI 指令備忘單

命令 特權 描述
sudo roamswitch status --server root 顯示 34 項伺服器安全診斷的分數與狀態(使用 --json 以 JSON 輸出相同內容)
sudo roamswitch ports root 審計開放的監聽埠和綁定的進程
sudo roamswitch fim verify root 驗證關鍵路徑系統檔案的 SHA-256 完整性
roamswitch notifications 使用者 顯示最近一週的通知歷程(所有已傳送的警示)(同樣支援 --json / --export 檔案)
sudo roamswitch server setup root 啟動互動式初始設定精靈
sudo roamswitch fim update root 刷新 FIM SHA-256 基線資料庫
sudo roamswitch server config set <key> <value> root 修改並儲存單一設定金鑰(清單見 §18)
sudo roamswitch emergency-restore 根 解除全部 eBPF/防火牆緊急隔離,恢復至初始基準
roamswitch port-scan 一般使用者 顯示入站連接埠掃描偵測防護(§4.3)的偵測歷史(來源 IP、是否自動封鎖及封鎖時長)
roamswitch sensor [key|list|pair|unpair|request-audit|results] 一般使用者/root 與 RoamSwitch Sensor 透過配對碼方式建立相互信任。使用 pair --addr <IP> --code <配對碼> --fingerprint <SHA-256> 進行配對(指紋為 Sensor 畫面上顯示的值),使用 repin 在 Sensor 重新產生憑證後更新固定值,使用 request-audit 請求主動弱點稽核(透過 results 取得結果)。需要 sensor_pairing_enabled: true(預設關閉)。詳情請參閱 Sensor 維運手冊
roamswitch server tui 一般使用者/root 啟動可操作全部功能的 TUI(一般使用者為唯讀,root 可進行全部操作。§17)
sudo roamswitch server ack root 對目前的緊急隔離做出確認回應(FULL 隔離期間維持嚴格隔離,降級期間則解除。§4.1)
roamswitch server ebpf 使用者 顯示 eBPF 執行階段防護目前的隔離狀態與已偵測事件的歷程
roamswitch server bans [--json] 一般使用者/root 顯示 SSH 暴力破解防護(§4.5)的狀態,以及目前被封鎖的來源位址(含剩餘時間)。支援 --json。封鎖清單只有 root 能讀取
sudo roamswitch server unban <IP | IPv6 /64 | --all> root 解除 SSH 暴力破解防護的封鎖,並清除該來源位址的失敗計數(IPv6 以 /64 指定,--all 解除全部)
sudo roamswitch server allowlist [list|add <rule> <process> [--exe <path>]|remove <rule> <process>] root 管理誤判的永久允許清單。加上 --exe 後會與執行檔的路徑綁定,無法透過偽造行程名稱來規避(僅依名稱登錄可被偽造,並會顯示警告)
roamswitch frozen [list|resume <PID>|resume all] 一般使用者/root 列出被防護以 SIGSTOP 凍結的行程,並在屬於誤判時解除(SIGCONT)。使用 resume all 可全部解除
sudo roamswitch events search|tree|export|verify|status root 搜尋執行記錄器(--since 2h --pid --exe --user --parent --text --json)、行程樹、匯出、雜湊鏈驗證、狀態顯示(§15)
sudo roamswitch forward status|test|queue root 檢視事件轉送的狀態、傳送測試事件、顯示重送佇列(§16)
roamswitch timeline / notifications [--json] [--export FILE] 使用者 顯示整合事件時間軸(實驗性)/通知歷程。使用 --json 輸出 JSON 陣列,使用 --export 檔案 輸出 JSON Lines
roamswitch audit-agent-setup [--json] 使用者 以唯讀方式檢查提供給 AI 代理的指示檔、技能和 OpenClaw 設定中的危險內容(僅限主目錄,不進行網路通訊,--json 輸出 JSON)。也可在 Server TUI 的「工具」中執行

12. 故障排除和常見問題解答

Q1. RoamSwitch 會意外地斷開我的 SSH 會話嗎?

不會。RoamSwitch 在正常情況下會無條件放行已知的 ESTABLISHED/RELATED 連線狀態與 ssh_ports(預設 22)。此外,即使因嚴重攻擊觸發了 Air-Gap 緊急隔離,preserve_ssh_on_isolation=true(預設)也會保留維護 SSH 連接埠與管理來源 IP 的管理工作階段(除此之外的已建立連線會被阻斷)。1.10.4 及之前的伺服器版存在缺陷,隔離規則會丟棄 SSH 的回應,因此隔離期間維運人員的 SSH 無法使用。該缺陷已在 1.10.5 修正。

Q2。如果不小心被鎖定,如何重新獲得存取權限?

透過雲端服務商的 Web 管理主控台(VNC/序列主控台)登入,執行 sudo roamswitch emergency-restore 解除緊急隔離,或執行 sudo systemctl stop roamswitch-server 停止服務。

Q3。如何為新新增的 Web 服務(例如 Nginx)公開連接埠?

執行 sudo roamswitch server config set allowed_ports 80,443,3000(或直接編輯 /etc/roamswitch/server.conf),然後執行 sudo roamswitch server restart。

13. File Scan Guard(保護郵件中繼、共享資料夾與上傳目的地)

僅當此主機存在用於保存要交給他人的檔案的目錄(如郵件中繼、Samba/NFS 共享、檔案上傳目的地)時才需要關注的選用功能。內建 YARA 引擎無需外部依賴即可持續掃描 clamav_scan_dirs,設定 clamav_enabled=true 後還會加入 ClamAV 作為第二重判斷。確認的威脅會自動隔離至 /var/lib/roamswitch/quarantine,並通知維運人員。

# --- File Scan Guard(ClamAV,選用啟用) ---
# 內建 YARA 引擎始終無條件掃描 clamav_scan_dirs。
clamav_enabled=false             # 設為 true 可啟用 clamdscan 進行額外檢查
clamav_scan_dirs=                # 掃描目標的絕對路徑(以逗號分隔)
clamav_scan_interval_secs=86400  # 掃描間隔(秒,最小 3600)
clamav_freshclam_interval_secs=7200  # 特徵庫自動更新間隔(秒,最小 1800)

也可透過互動式精靈 sudo roamswitch server setup 進行設定,並可透過 get_file_scan_guard_status MCP 工具查看設定與隔離狀態。

14. Log Audit(記錄模式異常偵測與通知)

透過定期掃描 journalctl 將記錄訊息範本化,偵測新模式(前所未見的記錄形態)與頻率異常(統計激增,Z-score > 3.0)。由於不需要額外守護行程或外部相依性,這是一種輕量機制,預設已啟用。偵測到異常時會透過與 File Scan Guard 及 FIM 相同的通知管道(Telegram / LINE / Webhook)發送通知。記錄中可能出現的 API 金鑰或權杖,會在寫入通知內文之前自動遮罩。

# --- Log Audit(預設啟用) ---
log_audit_enabled=true           # 設為 false 可停用
log_audit_interval_secs=1800     # 掃描間隔(秒,最小 300)

也可透過互動式精靈 sudo roamswitch server setup 進行設定,並可透過 roamswitch audit-logs CLI 指令或 audit_security_logs MCP 工具查看最新的偵測結果。

存取日誌診斷工具 AccessScope(獨立工具):Server Edition 的 deb / rpm 中隨附一個獨立工具的指令 accessscope,用於診斷 Web 伺服器與 SSH 的存取日誌(不含介面應用程式)。它是唯讀的,分析既不使用 LLM,也不使用網路。透過 LLM 分析是選用的,預設關閉(啟用後也可以 root 執行,但 LLM 會以 root 權限執行,建議以無特權的使用者執行)。accessscope scan --auto 診斷本主機的日誌,accessscope discover 列出日誌的位置。詳情請參閱 AccessScope 頁面。 同一份 Server Edition 的 deb / rpm 也包含另外兩個獨立工具 PersonalSOC(檢查本主機的日誌與防禦狀況)和 PathScope(分析提權路徑)的指令 personalsoc 與 pathscope,不含畫面應用程式。這兩個指令本身不進行網路通訊。PersonalSOC 的 LLM 分析只在指定 --llm 時執行。

15. 執行記錄器與關聯規則(本機,僅通知)

透過 netlink 的 proc connector 記錄行程的執行(exec)(執行檔、引數、父行程譜系、UID、cwd、容器 ID、SHA-256)。預設開啟,記錄以帶雜湊鏈的分段 JSON Lines(0600,預設 200 MB / 14 天)儲存在本主機僅 root 可存取的目錄 /var/lib/roamswitch/exec_log 中,不會傳送到外部。它能夠偵測竄改(events verify),但無法防止竄改。如果無法開啟 proc connector,則退化為低頻率的 /proc 掃描。記錄處理執行在與 fanotify 許可事件迴圈不同的執行緒上,並將自身的 CPU 使用率控制在預算(預設 3%)以內。

在本機搜尋與匯出(由於是僅 root 可讀的日誌,通常需要 sudo)。

sudo roamswitch events status
sudo roamswitch events search --since 2h --exe curl
sudo roamswitch events tree 4242
sudo roamswitch events export --since 1d > exec-events.jsonl
sudo roamswitch events verify

關聯規則 EXR-001〜007(僅通知,附帶 MITRE ATT&CK 技術 ID):EXR-001 由 Web 服務啟動的 Shell / EXR-002 從 /tmp、已刪除檔案、memfd 執行 / EXR-003 下載後立即執行 / EXR-004 使用 base64、eval 的直譯器單行指令 / EXR-005 非 setuid 來源的 uid 0 取得 / EXR-006 執行 cron、systemd 剛剛放置的執行檔 / EXR-007 ld.so.preload 變更後的執行。各規則採用安靜的預設值,單獨不會觸發隔離。可透過 exec_rules_disabled(例如 EXR-003,EXR-004)個別停用,也可透過 exec_rule_service_users 調整 EXR-001 的目標使用者。

只有明確將 exec_rules_isolation_optin(預設 false)設為 true 時,嚴重程度高的規則才會被視為高信賴度的隔離觸發條件(§4.1)。預設情況下,規則只做通知。也可以透過唯讀的 MCP 工具 search_exec_events / get_process_tree 檢視。

16. 事件轉送(SIEM / syslog / Webhook,需主動開啟)

可以將偵測事件轉送到維運人員指定的自己組織的目的地。預設關閉,在設定 forward_enabled=true 並設定至少一個目的地之前不會傳送任何內容,也沒有內建任何廠商的目的地。轉送對象包括事件時間軸、通知歷程、eBPF 防護、隔離的狀態轉換、FIM、金絲雀、exec 規則的警示,但不會轉送 exec 的原始日誌本身。目的地有以下 3 種。

  • syslog(forward_syslog_url: udp://host:514 / tcp://host:port / tls://host:port):RFC 5424 或 CEF(forward_syslog_format)。TCP / TLS 的分框為 octet(RFC 6587,預設)或 lf。TLS 驗證可透過 forward_tls_ca_file 指定 CA,通訊則交由系統的 openssl s_client 處理。
  • JSON Lines 檔案(forward_file_path):每行一個事件。透過 forward_file_max_mb(預設 50)與 forward_file_keep(預設 5)進行輪替。
  • 結構化 Webhook(forward_webhook_url):以 POST 傳送 JSON,並在 X-RoamSwitch-Signature 標頭中附上基於共用密鑰(forward_webhook_secret,或指向 0600 檔案的 forward_webhook_secret_file)的 HMAC-SHA256 簽章。傳送透過系統 curl 子行程進行,密鑰不會出現在引數中。

未能傳送的事件(TCP / TLS / Webhook)會進入磁碟上的重送佇列(0600,上限由 forward_queue_max_mb 預設 20 與 forward_queue_max_age_hours 預設 72 決定),即使重新啟動後也會依指數退避重送。可透過 forward_min_severity(預設 low)設定傳送的最低嚴重程度。為避免阻塞熱路徑,傳送在專用執行緒中進行,佇列溢出時會從最舊的開始丟棄。

狀態檢視、連線測試與重送佇列檢視使用以下指令(變更設定後請重新啟動服務)。

# /etc/roamswitch/server.conf
forward_enabled=true
forward_syslog_url=tls://siem.example.org:6514
forward_syslog_format=rfc5424
forward_tls_ca_file=/etc/ssl/certs/corp-ca.pem
forward_min_severity=medium

sudo roamswitch server restart
sudo roamswitch forward status
sudo roamswitch forward test
sudo roamswitch forward queue

17. Server TUI(可操作全部功能的終端機 UI)

roamswitch-server-tui(也可透過 roamswitch server tui 啟動)是一個 TUI,只需透過 SSH 的鍵盤操作,就能處理分散在 CLI 動詞與兩個設定檔(server.conf 與 guard.yaml)中的 Server Edition 的所有功能(可在 80x24 下運作,支援 10 種語言)。如果 CLI 動詞或設定鍵增加了而 TUI 中沒有對應項,開發時的測試就會失敗。

  • 權限模式:以一般使用者啟動時為唯讀(變更與特權操作被停用,取而代之的是顯示應當執行的 sudo roamswitch … 指令)。以 root 啟動時可以進行操作,影響較大的操作會先顯示內容,最危險的操作則要求輸入 yes。不會啟動常駐程式,自身也不會開啟網路通訊端。
  • 畫面(用數字鍵切換):1 儀表板(健康狀況、隔離狀態)/ 2 防禦(eBPF、隔離、金絲雀、FIM、Docker、Egress、DNS、執行記錄器、規則、事件搜尋、情報來源、XDP 閘控)/ 3 事件(各類事件(含 SSH 暴力破解的封鎖清單與解除)、時間軸、通知歷程、凍結的行程、隔離 Vault、允許清單)/ 4 通知、轉送 / 5 Sensor / 6 設定 / 7 服務 / 8 工具 / 9 日誌稽核 / 0 資訊、說明。按 ? 檢視目前畫面的按鍵清單,按 L 切換 10 種語言,按 r 重新載入,按 q 結束(如有未儲存的設定變更會進行確認)。
  • 設定編輯器:由 schema 產生,可以在驗證型別、範圍與列舉值的同時,編輯 server.conf 與 guard.yaml 的全部 146 個鍵(§18)。儲存前可以確認差異(密鑰已被遮蔽),儲存時會建立帶時間戳記的備份並以原子方式寫入。需要重新啟動的鍵,以及設定錯誤會失去管理路徑或削弱防禦的鍵,都會明確標示。調查代理連動(§10.1)的設定,也可以在選擇預設組合並預覽之後寫入。

啟動:

sudo roamswitch-server-tui    # full control
roamswitch-server-tui         # read-only
roamswitch server tui         # same as roamswitch-server-tui

18. 設定鍵一覽(server.conf / guard.yaml)

roamswitch-server 不支援設定的重新載入(reload)。所有鍵的生效都需要重新啟動服務(sudo roamswitch server restart)。server.conf 的各個鍵可透過 roamswitch server config set <鍵> <值> 或 §17 的編輯器修改。guard.yaml 透過編輯器或手動編輯來修改。

18.1 server.conf(109 個鍵)

鍵 型別 / 可用值 預設 重新啟動
languagesystem | ja | en | zh-hans | zh-hant | ko | de | fr | es | it | ptja需要
ssh_portsport list22需要
allowed_portsport list80,443需要
whitelist_ipslist—需要
preserve_ssh_on_isolationbooltrue需要
telegram_enabledboolfalse需要
telegram_bot_tokenstring—需要
telegram_chat_idstring—需要
line_enabledboolfalse需要
line_channel_access_tokenstring—需要
line_user_idstring—需要
webhook_enabledboolfalse需要
webhook_urlURL—需要
webhook_block_private_addressesboolfalse需要
webhook_allow_addressesCIDR list—需要
action_on_criticalisolate | freeze | alert_onlyisolate需要
ebpf_socket_pathabs path/run/roamswitch/events.sock需要
ebpf_heartbeat_interval_secs0 (off) | int 60–86400600需要
isolation_hard_cap_secsint ≥ 03600需要
fim_check_interval_secsint ≥ 10300需要
fim_intrusion_context_enabledbooltrue需要
protect_docker_portsbooltrue需要
dns_sinkhole_enabledboolfalse需要
dns_sinkhole_providerquad9 | cloudflare | adguard | cleanbrowsingquad9需要
egress_ip_blocklist_enabledbooltrue需要
metadata_watch_enabledbooltrue需要
metadata_watch_allow_userslist—需要
cve_kernel_map_updates_enabledbooltrue需要
clamav_enabledboolfalse需要
clamav_scan_dirsabs path list—需要
clamav_scan_interval_secsint ≥ 360086400需要
clamav_freshclam_interval_secsint ≥ 18007200需要
lockfile_watch_dirsabs path list—需要
npm_audit_signatures_enabledboolfalse需要
log_audit_enabledbooltrue需要
log_audit_interval_secsint ≥ 3001800需要
resource_guard_enabledbooltrue需要
resource_guard_rss_sample_interval_secsint ≥ 1060需要
resource_guard_rss_window_secsint ≥ 3001800需要
resource_guard_rss_min_samplesint ≥ 310需要
resource_guard_rss_min_growth_pctint ≥ 1050需要
resource_guard_rss_recovery_drop_pctint ≥ 110需要
resource_guard_rss_min_kbint ≥ 020000需要
resource_guard_crash_loop_window_secsint ≥ 60300需要
resource_guard_crash_loop_min_restartsint ≥ 23需要
resource_guard_correlation_window_secsint ≥ 60600需要
resource_guard_zombie_min_countint ≥ 020需要
resource_guard_load_min_normalizedfloat ≥ 0.00.5需要
resource_guard_load_enabledbooltrue需要
resource_guard_cpu_enabledbooltrue需要
resource_guard_cpu_sample_interval_secsint ≥ 060需要
resource_guard_cpu_window_secsint ≥ 0600需要
resource_guard_cpu_min_samplesint ≥ 08需要
resource_guard_cpu_pct_thresholdfloat 0.0–1000.080.0需要
container_exec_guard_enabledbooltrue需要
port_scan_detect_enabledbooltrue需要
port_scan_detect_min_distinct_portsint ≥ 015需要
port_scan_detect_window_secsint ≥ 0300需要
port_scan_block_enabledbooltrue需要
port_scan_block_duration_secsint ≥ 0600需要
ssh_guard_enabledbooltrue需要
ssh_guard_block_enabledbooltrue需要
ssh_guard_max_failuresint 2–10006需要
ssh_guard_window_secsint 10–86400600需要
ssh_guard_ban_secsint 60–25920003600需要
ssh_guard_ban_max_secsint 60–31536000604800需要
ssh_guard_allowIP/CIDR list—需要
ssh_guard_log_sourceauto | journal | abs pathauto需要
ssh_guard_yield_to_fail2banbooltrue需要
ssh_guard_trust_key_daysint 0–365030需要
dns_tunnel_detect_enabledbooltrue需要
reverse_shell_watch_enabledbooltrue需要
reverse_shell_watch_include_privateboolfalse需要
reverse_shell_watch_notify_onlyboolfalse需要
sensor_pairing_enabledboolfalse需要
sensor_colocatedboolfalse需要
forward_enabledboolfalse需要
forward_syslog_urlURL—需要
forward_syslog_formatrfc5424 | cefrfc5424需要
forward_syslog_framingoctet | lfoctet需要
forward_tls_ca_fileabs path—需要
forward_file_pathabs path—需要
forward_file_max_mbint 1–1000050需要
forward_file_keepint 1–1005需要
forward_webhook_urlURL—需要
forward_webhook_secretstring—需要
forward_webhook_secret_fileabs path—需要
forward_webhook_block_private_addressesboolfalse需要
forward_webhook_allow_addressesCIDR list—需要
forward_min_severityinfo | low | medium | high | criticallow需要
forward_queue_max_mbint 1–1000020需要
forward_queue_max_age_hoursint 1–876072需要
exec_recorder_enabledbooltrue需要
exec_recorder_retention_mbint 1–100000200需要
exec_recorder_retention_daysint 1–365014需要
exec_recorder_hash_chainbooltrue需要
exec_recorder_hash_exebooltrue需要
exec_recorder_cpu_budget_pctint 1–503需要
exec_rules_enabledbooltrue需要
exec_rules_disabledstring—需要
exec_rule_service_usersstring—需要
exec_rule_window_secsint 5–3600120需要
exec_rules_isolation_optinboolfalse需要
honeytokens_enabledbooltrue需要
honeytokens_homeabs path/root需要
harden_userns_enabledbooltrue需要
dns_tunnel_entropy_allowlistlist—需要
fleet_forwarding_allowed_hostslist—需要
fleet_forwarding_allow_plaintextboolfalse需要

18.2 guard.yaml(37 個鍵)

鍵 型別 / 可用值 預設 重新啟動
sensor.typefalco | tetragonfalco需要
sensor.transportstringunix_socket需要
sensor.socket_pathabs path/run/roamswitch/events.sock需要
sensor.reconnect_interval_msint 100–36000001000需要
policies.on_warning.actionlog_and_notify | isolate_process | isolate_host_alllog_and_notify需要
policies.on_warning.server_actionlog_and_notify | isolate_process | isolate_host_all—需要
policies.on_warning.kill_processboolfalse需要
policies.on_warning.freeze_processboolfalse需要
policies.on_warning.fallback_to_host_isolation_after_retriesint 0–1000—需要
policies.on_error.actionlog_and_notify | isolate_process | isolate_host_allisolate_process需要
policies.on_error.server_actionlog_and_notify | isolate_process | isolate_host_all—需要
policies.on_error.kill_processboolfalse需要
policies.on_error.freeze_processboolfalse需要
policies.on_error.fallback_to_host_isolation_after_retriesint 0–1000—需要
policies.on_critical.actionlog_and_notify | isolate_process | isolate_host_allisolate_process需要
policies.on_critical.server_actionlog_and_notify | isolate_process | isolate_host_all—需要
policies.on_critical.kill_processbooltrue需要
policies.on_critical.freeze_processboolfalse需要
policies.on_critical.fallback_to_host_isolation_after_retriesint 0–10003需要
policies.on_emergency.actionlog_and_notify | isolate_process | isolate_host_allisolate_host_all需要
policies.on_emergency.server_actionlog_and_notify | isolate_process | isolate_host_all—需要
policies.on_emergency.kill_processbooltrue需要
policies.on_emergency.freeze_processboolfalse需要
policies.on_emergency.fallback_to_host_isolation_after_retriesint 0–1000—需要
server_safeguards.allow_established_connectionsbooltrue需要
server_safeguards.maintenance_ssh_portsport list22需要
server_safeguards.whitelist_cidrslist—需要
server_safeguards.whitelist_dns_serverslist—需要
server_safeguards.safety_timer_secsint ≥ 0300需要
adaptive_security.enabledbooltrue需要
adaptive_security.untrusted_network_actions.elevate_falco_profilestring—需要
adaptive_security.untrusted_network_actions.auto_enable_userns_restrictionboolfalse需要
investigation.enabledboolfalse需要
investigation.commandabs path—需要
investigation.argslist—需要
investigation.run_asstring—需要
investigation.timeout_secsint 1–86400180需要

19. Web Shell 與注入程式碼偵測 (Web Rules)

此功能用於找出在 Web 伺服器上執行的 PHP、JavaScript、JSP、ASP Web Shell 與注入程式碼、偽裝成圖片的 PHP 以及 .htaccess 濫用(自 Linux 1.11.23 起)。不需設定:它會從 Apache、nginx、Caddy 的設定中自動找到文件根目錄,並在檔案於其中寫入並關閉後立即檢查(使用僅通知的 fanotify,不會使其他行程停滯)。為彌補可能遺失的事件與啟動前已存在的檔案,每 6 小時還會定期掃描。不需要 ClamAV。

行為由 /etc/roamswitch/web_rules.conf 決定(root 所有,權限 0644;他人可寫的檔案會被忽略)。修改後用 sudo roamswitch server restart 使其生效。範本可用 roamswitch web-rules example conf 輸出。

鍵意義(預設值)
quarantine自動隔離層級。off 不隔離,critical 僅隔離 critical,high 隔離 critical 與 high(預設:critical)。在 critical 層級下發現 high 時,只發送通知並觸發掛鉤,不觸碰檔案。
account_action是否停用被偵測檔案擁有者的登入 shell。off / revoke_shell(預設:off)。僅針對已隔離的 critical 或 high。不會處理 root、UID 低於 account_min_uid 的帳號、已登入的使用者以及常駐程式自身。原 shell 會被記錄,可用 sudo roamswitch web-rules unlock-account <使用者> 還原。
account_min_uidaccount_min_uid:帳號處置可作用的最小 UID(預設 1000,不能低於 100)。
scan_dirs, auto_docroots, watch, scan_interval_secsscan_dirs(以逗號分隔的絕對路徑)、auto_docroots(預設 true;設為 false 則不再從 Web 伺服器設定自動探索)、watch(預設 true;設為 false 則關閉寫入監視,僅保留定期掃描)、scan_interval_secs(預設 21600,最小 3600)。
# /etc/roamswitch/web_rules.conf
quarantine=critical
account_action=off
account_min_uid=1000
#scan_dirs=/srv/sites/a,/srv/sites/b
auto_docroots=true
watch=true
scan_interval_secs=21600

偵測到時會發送通知(Telegram、LINE、Webhook),通知中寫明規則名稱以及檔案是已隔離還是保留。若只想檢視而不移動任何檔案,請使用 sudo roamswitch web-scan <資料夾>(僅檢查;加 --quarantine 才隔離)或 Server TUI 的「工具」畫面。自訂規則放在 /etc/roamswitch/rules.d/*.json;若要在偵測後呼叫自己的腳本,請放在 /etc/roamswitch/hooks/post-detection(偵測內容以 JSON 透過標準輸入傳入;僅執行 root 所有、他人不可寫且父目錄也安全的檔案,不經過 shell,30 秒後終止)。規則更新併入每日僅接收更新。關閉 cve_kernel_map_updates_enabled 後完全不進行網路通訊,使用內建規則運作。

← 伺服器版白皮書 前往 Linux 版安裝頁面 →