Lafine Systems Design · 技術文件

RoamSwitch Server Edition 架構/安全白皮書

適用於雲端與地端 Linux 基礎架構的無頭自主網路安全與完整性防禦套件。不使用宣傳性的措辭,所載內容皆可透過官方發行套件的實際行為,以及 §6 的自我檢查加以確認。

版本 v1.11.1 適用對象 RoamSwitch Server Edition 1.11.1(DNS 隧道偵測/蜜餌權杖/鑑識證據保全/NIST CSF・CIS Controls 對應/簽章核心 CVE 對照表更新) 需求 systemd + nftables 發布日期 2026-10-08

§1概述與核心原則

RoamSwitch 伺服器版 是一款無頭、常駐自主網路安全性和完整性保護套件,專為跨雲端供應商(AWS、GCP、Azure、裸機 VPS)和本地資料中心的 Linux 伺服器基礎架構而建置。

與專注於移動性和 Wi-Fi 週邊適應的客戶端工作站版本不同,伺服器版本建立在五個毫不妥協的原則之上:入站預設丟棄、關鍵路徑檔案完整性監控 (FIM)、搶權限佔式核心 LPE 和增強功能增測、eBPF 運行時威脅遙測和帶有斷線前緊急警報的自主氣隙主機隔離。

在程式碼層級貫徹從常駐程式本體中完全排除外部通訊函式庫的 Zero Telemetry 原則(預設對外的只有接收簽章資料(核心 CVE 資料、Web 規則,以及在 Ubuntu 伺服器上用於作業系統套件 CVE 比對的 Ubuntu 套件 CVE 資料;清單每天確認一次,CVE 資料本體約每 30 天一次),且可以關閉;其餘所有例外都是維運人員明確選擇啟用的,見 §1 核心設計原則),機密資訊(機器人權杖與設定)由權限 0600 保護。

1.1 比較:客戶端版與伺服器版

尺寸 客戶端版(桌面/行動) 伺服器版(無頭/基礎設施)
部署 筆記型電腦、行動開發者工作站 雲端虛擬機器、裸機節點、容器主機
網路行為 基於 Wi-Fi SSID/網關 MAC 的動態設定檔切換 靜態入站預設丟棄。僅公開明確允許的端口
用戶介面 GTK3 桌面 GUI + 托盤指示器 純無頭 CUI。CUI 指令 + 互動式設定精靈 + 終端機 UI(roamswitch-server-tui)
事件通知 桌面通知 (libnotify) 直接推送到 Telegram Bot、LINE Messaging API 和 Webhooks (Slack/Discord)
主要防禦 公共 Wi-Fi ARP 欺騙、BadUSB、勒索軟體文件加密 外部偵察投放、FIM 竄改偵測、容器逃脫、核心 LPE (CVE-2026-53362)

1.2 核心架構原則

  • Zero Telemetry(零遙測):預設不向外部傳送任何有關使用者或環境的資訊。常駐程式本體沒有 HTTP/TLS 外部通訊函式庫,只有在維運人員設定的通知與轉送時,才會把系統內建的 curl(Telegram/LINE/Webhook;權杖與 URL 等機密經由標準輸入的設定傳遞,不出現在命令列參數中)與 openssl(TLS syslog 轉送)作為子行程執行。預設啟用的對外通訊,除套件管理員的更新外,只有下面這一項。(1) 在 cve_kernel_map_updates_enabled(預設 true)開啟期間,roamswitch-updater 從 lafine.net 匿名接收簽章資料。接收的是用於容器隔離稽核的核心 CVE 資料、Web 應用層偵測規則(Web 規則),以及在 Ubuntu 伺服器上用於作業系統套件 CVE 比對的 Ubuntu 套件 CVE 資料。簽章清單及其簽章每天確認一次(2 次 GET),核心 CVE 資料本體與 Ubuntu 套件 CVE 資料只在距上次更新約 30 天後才取得(尚無 Ubuntu 資料的伺服器於下一次每日確認時取得),Web 規則只在清單版本更新時才取得。它只是不含查詢字串與 Cookie 的 HTTPS GET,能表明軟體身分的請求標頭只有固定的 User-Agent: RoamSwitch-Updater,只採用能通過 Ed25519 簽章驗證的資料,不會傳送任何有關本主機的資訊。維運人員可以用 roamswitch server config set cve_kernel_map_updates_enabled false、設定精靈或伺服器 TUI 將其關閉;現有 server.conf 中明確寫了 false 時,會原樣保持;關閉後稽核仍基於內建基準運作,但 Ubuntu 伺服器上的作業系統套件 CVE 比對會顯示「本機 CVE 資料未取得」,且不回傳結果。除此之外的例外,都是維運人員明確選擇啟用的。(2) 事件轉送(forward_enabled,預設 false)只傳送到維運人員設定的 syslog/JSON Lines 檔案/簽章 Webhook 目的地。(3) 僅當啟用 npm_audit_signatures_enabled(預設 false)且維運人員執行 roamswitch audit-npm-signatures <DIR> --confirm 時,才由 npm 本身連向 registry.npmjs.org。(4) 僅當啟用 sensor_pairing_enabled(預設 false)時,才會連線維運人員輸入的 Sensor 位址(Sensor 是另一款產品,不適用 Zero Telemetry)。(5) Fleet(Business 層)只有裝置端程式碼,未註冊的裝置不會傳送任何內容,也不會解析名稱;管理服務尚未部署或發行,且設計上沒有遠端命令通道。(6) 隨附的獨立工具 accessscope(存取日誌的資安診斷)的 LLM 串接預設關閉。僅當啟用時(在命令列中即指定了 --llm),診斷摘要、依據日誌行與環境資訊(尋找日誌的功能)才可能透過維運人員所選的 LLM 指令傳送到外部服務。常駐程式(roamswitch-server)不參與這項通訊,AccessScope 也可以 root 執行 LLM 分析(此時 LLM 以 root 權限執行,建議以無特權的使用者執行),且不適用 Zero Telemetry。隨附的另一個獨立工具 personalsoc(檢查日誌與防禦狀況)同樣如此:只有在指定 --llm 時,診斷摘要才可能透過維運人員所選的 LLM 指令傳送到外部服務(不適用 Zero Telemetry)。pathscope 指令不會呼叫 LLM。(7) 僅當啟用 clamav_enabled(預設 false)時,常駐程式才會執行 freshclam 來接收 ClamAV 特徵碼(在特徵碼資料庫尚不存在的初次,以及設定了 clamav_scan_dirs 期間每隔 clamav_freshclam_interval_secs(預設 7200 秒)一次)。
  • 入站預設拒絕 (Inbound Default Drop)會以 nftables 丟棄送往未允許連接埠(TCP)的新入站連線,連 RST 都不回覆。連接埠掃描只看得到已允許的連接埠(環回、已建立的連線、ICMP 與 ICMPv6 會放行)。
  • 故障關閉與自我修復如下。預設拒絕與隔離規則會留在核心中,因此即使常駐程式停止或重新啟動也會維持(Restart=always)。Docker 公開連接埠的防護每 60 秒複查一次,Egress 封鎖清單與連接埠掃描阻斷每 300 秒複查一次,並重新設置已消失的規則。降級(DEGRADED)的隔離規則會在每 15 秒的評估中確認,若已消失則重新設置。預設拒絕規則本身若被外部刪除,不會自動重新套用,因此請以診斷「入站預設拒絕」(roamswitch server status)確認。
  • 透過 0600 權限保護:設定檔 /etc/roamswitch/server.conf 在建立與更新時會被自動強制設為權限 0600。權杖與 Webhook URL 等機密在傳給 curl 時也經由標準輸入的設定傳遞,不會放在命令列參數中(其他使用者可透過 /proc/<pid>/cmdline 看到)。

§2威脅格局與對手模型

現代面向互聯網的伺服器面臨無情的自動掃描、容器突破向量和零日核心權限升級。

解決的主要威脅媒介
  1. 自動偵察和資料庫暴露:網際網路範圍內的掃描器定位無意暴露的內部資料庫連接埠(MySQL 3306、Redis 6379、Postgres 5432).
  2. 關鍵路徑竄改與後門插入:入侵者透過修改核心身分驗證二進位檔案(/bin/login、/usr/bin/sudo、/etc/pam.d/*、/etc/shadow)建立持久性。
  3. 核心權限升級 (CVE-2026-53362 Frag Gap):非特權攻擊者武器化使用者命名空間 (unshare -U -r) 以觸發核心記憶體損壞並升級到 root.
  4. Container Socket Breakout:設定錯誤的容器,已安裝 /var/run/docker.sock 或 --privileged 標誌,在主機作業系統上執行 root 操作.
  5. 進程記憶體窺探:攻擊者跨進程附加ptrace或讀取/proc/$pid/mem以提取私鑰或憑證。

§3系統架構

RoamSwitch 伺服器版作為本機 Rust 二進位檔案運行,旨在實現最小記憶體和零 CPU 開銷。

┌─────────────────────────────────────────────────────────────┐
│  使用者與管理員空間                                         │
│                                                             │
│   roamswitch (CLI)             roamswitch-mcp (AI Agent)    │
│   · server status(34 項診斷)  · 安全稽核工具集            │
│   · server config / setup      · 標準輸入輸出 JSON-RPC      │
│   · fim verify / update                                     │
│        │                               │                    │
└───────┼───────────────────────────────────┼─────────────────┘
         │ (CUI 命令 & 設定生效)          │ (stdio)
┌───────▼───────────────────────────────────▼─────────────────┐
│  系統基座 (systemd + root 權限)                             │
│                                                             │
│   roamswitch-server-daemon                                  │
│   ├── CriticalPathFim (SHA-256 背景巡檢)                    │
│   ├── eBPF / Falco 聯動模組                                 │
│   ├── Notifier (Telegram / LINE / Webhook 即時通知)         │
│   └── Air-Gap Controller (展開 nftables 緊急封鎖規則)       │
│                                                             │
│   設定管理: /etc/roamswitch/server.conf (權限 0600)         │
│   完整性資料庫: /var/lib/roamswitch/fim.db                  │
└─────────────────────────────────────────────────────────────┘

§4核心防衛機制

4.1 邊界安全(入站預設丟棄)

對 nftables 的 inet roamswitch_server 資料表中的 input 鏈套用 policy drop。僅允許送往管理者指定連接埠(ssh_ports、allowed_ports)的新 TCP 入站連線,對未允許連接埠的通訊則使其逾時(丟棄)。允許環回、已建立的連線、ICMP 與 ICMPv6。

即使觸發 Air-Gap(緊急隔離),維護用 SSH 連接埠(ssh_ports)與已登記的維護來源 IP(whitelist_ips)的管理通道(新建及已建立的連線)仍會保留在規則中,避免無法進行遠端復原的局面(preserve_ssh_on_isolation,預設 true)。其他已建立的連線(例如攻擊者已建立的 C2 或反向 shell)會被 default-drop 阻斷。如果未指定管理來源(whitelist_ips 與 guard.yaml 中的允許項皆為空),隔離期間維護 SSH 連接埠仍會接受來自任意來源的新連線,伺服器啟動時會輸出警告。設為 preserve_ssh_on_isolation=false 時,SSH 也會一併阻斷。1.10.4 及之前的伺服器版存在缺陷,隔離規則會丟棄 SSH 的回應,因此隔離期間維運人員的 SSH 無法使用。該缺陷已在 1.10.5 修正。

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

監控與系統開機、認證、網路和系統管理相關的最關鍵檔案的 SHA-256 雜湊完整性。範圍包括:固定的 23 處路徑(/etc/shadow、/etc/passwd、/etc/sudoers、/etc/ssh/sshd_config、/bin/login、/usr/bin/sudo、/usr/sbin/sshd、/usr/lib/systemd/systemd 等);/etc/pam.d、/etc/sudoers.d、/etc/ssh/sshd_config.d、/etc/cron.d 與 /etc/cron.{hourly,daily,weekly,monthly}、/etc/systemd/system、/etc/ld.so.conf.d、/etc/profile.d、/root/.ssh 這 12 個目錄下的檔案(同時偵測新檔案的出現。/root/.ssh 的 known_hosts 與 known_hosts.old 每次以 SSH 連線時都會被改寫,因此排除在外);RoamSwitch 自身的二進位檔;每個可登入使用者的 authorized_keys;以及不應存在的 /etc/ld.so.preload(偵測其出現)。正規的套件更新之後,正常基準線會自動更新。Debian 系的 /etc/apt/apt.conf.d/99roamswitch-fim 掛鉤(apt upgrade 等),以及 RHEL 系與 openSUSE 中監視 /var/lib/rpm 的 systemd.path 單元(roamswitch-fim-update.path),都會執行 roamswitch fim update。

入侵路徑的確定(誰、透過哪一次 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)才會發現。這時不知道寫入的行程是誰,通知中也會如此說明。

實測在 Ubuntu 24.04 虛擬機上進行,維運人員的來源放在獨立的網路命名空間(netns)中。無論是 sudo tee、用 nohup 脫離的行程(登出之後仍能確定來源 IP,並附上「該連線已經結束」)、sudo -i 的行程鏈,還是極短命的 cat,通知中都給出了 IP、使用者和驗證方式。本機登入則顯示「沒有找到 SSH 登入」。用 exec -a "sshd: …" 偽裝名稱的行程,沒有被當作 SSH。

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

4.3 內核與容器強化

Frag Gap (CVE-2026-53362) 緩解:透過 sysctl 強制執行 user.max_user_namespaces = 0,中和 LPE 向量。 Yama LSM 保護 強制執行 kernel.yama.ptrace_scope = 2,防止未經授權的記憶體檢查。容器工作負載經過 docker.sock 暴露審計。在伺服器版中,禁止非特權命名空間預設開啟(harden_userns_enabled)。這會使 rootless Podman 等無法執行,如果需要使用,請設為 false。

Docker 發布的連接埠(-p)存在繞過主機標準防火牆的已知問題,因此在 protect_docker_ports=true(預設)下,會阻斷來自外部介面、且 DNAT 之前的目的連接埠不在允許連接埠(ssh_ports、allowed_ports)中的流量(回程流量、迴環及容器間流量不受影響)。在 iptables/iptables-nft 後端,規則放入 DOCKER-USER 鏈(IPv4;啟用 Docker IPv6 時也透過 ip6tables);在 Docker 29 及之後等原生 nftables 後端(沒有 DOCKER-USER 的設定)下,放入專用的 inet roamswitch_docker_guard 表(forward 掛鉤,優先順序 -10),後者以一套規則集同時涵蓋 IPv4 與 IPv6。常駐程式會定期複查並重新安裝消失的規則。此外還有一個常駐防護,透過 docker events 即時偵測 --privileged 容器的啟動或 /var/run/docker.sock 的掛載,並作為容器逃逸風險立即通知(無需設定,僅通知,不自動阻斷)。對於處理會交給他人的檔案(如郵件中繼或共用資料夾)的主機,可選擇啟用 File Scan Guard(內建 YARA + 選用 ClamAV)提供定期掃描與自動隔離。

容器執行防護(container_exec_guard_enabled,預設 true)。在執行中 Docker 容器的 overlay2 根目錄上設定 fanotify 的 FAN_OPEN_EXEC(通知類),以內建 YARA 規則檢查被執行檔案的內容並發出通知。由於先訂閱 docker events,再用 docker ps 列舉執行中的容器,常駐程式啟動時已在執行的容器也在涵蓋範圍內。被執行檔案的內容從 fanotify 傳來的檔案描述子讀取,因此即使檔案在執行後立即自我刪除也能檢查。僅通知,不會阻止或拒絕執行(Server Edition 根本沒有許可類 fanotify)。Docker 29 把已棄用的 Status 從 docker events 的訊息中移除,因此直到 1.11.0,訂閱都會立即失敗,防護在無法使用訂閱的狀態下,每 5 秒重複重新連線。自 1.11.1 起,改用在舊版 Docker 上也是相同值的 Action。訂閱持續失敗時,重新連線的間隔會從 5 秒倍增到最長 5 分鐘,相同原因的警告只會記錄第一次。

4.4 eBPF 運轉時威脅遙測和防膨脹調整

利用現代 eBPF (CO-RE / BTF) 偵測器在幾毫秒內攔截權限升級和容器突破嘗試。為了消除 Falco 的標準痛點 — 日誌膨脹、磁碟耗盡和 CPU 開銷 —RoamSwitch 標準化了最佳化設定檔 (/etc/falco/config.d/99-roamswitch-optimized.yaml):

  • 严重性过滤 (priority: warning):将嘈杂的操作遥测(信息/通知)抑制 95%,暴露严格可操作的安全事件。
  • 核心層級預先刪除 (drop_failed_exit: true):直接在核心偵測中丟棄失敗的系統呼叫退出,將 CPU 上下文切換減少 50% 以上。
  • 内存占用优化 (cpus_for_each_buffer: 2):将环形缓冲区从 8MB 压缩到 2MB,将内存使用严格限制在 30–50MB。
  • 直接 UNIX 通訊端 IPC:不經磁碟 I/O,透過記憶體中的通訊端(/run/roamswitch/events.sock)即時連動。
  • 日誌自動上限 (/etc/logrotate.d/roamswitch-falco)以 maxsize 50M 與 7 代壓縮輪替(每日執行)抑制 Falco 日誌的膨脹。

eBPF 隔離的準確度與速度(不把一切交給 Falco 的規則)

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 行)。

反向 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 用戶端版沒有。

4.5 帶有預先切斷警報的緊急氣隙隔離

在發生嚴重篡改時切斷網路介面之前,守護程式會同步向 Telegram、LINE 和 Webhooks 發送緊急警報。警报会自动附加服务器 主机名 和 主 IP 地址。

緊急警報格式(日文/英文)
🚨 [RoamSwitch IMMINENT AIR-GAP] 【緊急警告】即將立即執行網路完全阻斷 (Air-Gap) (cve_2026_53362_lpe)
🚨 偵測到重大資安事件: cve_2026_53362_lpe
主機: production-app-01 (IP: 192.168.1.10)
目標處理程序: exploit_payload (PID: 4921)
緊急應對: 為防止災情擴大,將啟動主機的網路全面阻斷 (Air-Gap)(僅保留 SSH 管理連接埠)。
警告: 此通知傳送完成後,所有對外網際網路通訊將立即被阻斷。
時間: 2026-09-06 18:00:00
⚠️ 網路連線將立即被阻斷。

解除條件取決於觸發來源的信賴度。低信賴度觸發(例如 eBPF 的 Error 等級及以下)會在短計時器(guard.yaml 的 server_safeguards.safety_timer_secs,預設 300 秒)到期後完整恢復。高信賴度觸發(eBPF 的 Critical/Emergency/Alert、同一規則反覆觸發升級為主機隔離、金絲雀遭竄改等)不會悄悄恢復。短計時器到期後會複查原因(被凍結的 PID 是否仍存活、規則是否再次觸發等),只有確認原因已消失時才會附帶通知地解除。若無法確認且沒有 ACK,到達上限(isolation_hard_cap_secs,預設 3600 秒,0 = 無上限)後轉入 DEGRADED。DEGRADED 保留維護 SSH 連接埠與維護來源 IP 的管理通道(新建及已建立),新的對外連線僅允許發往維護來源 IP,並且絕不會因時間流逝而自動放開。解除方式只有:確認原因已消失的複查、roamswitch server ack(DEGRADED 中的 ACK 表示解除)或 roamswitch emergency-restore。已 ACK 的隔離(FULL)視為由維運人員接管,既不會由計時器恢復,在確認原因已消失時也不會自動解除,也不會轉入 DEGRADED,而是維持到以 emergency-restore 解除為止。每次轉換都會記錄到事件時間軸並發出通知。

行程執行記錄器 & 事件轉送

透過 netlink 行程連接器記錄 exec 的僅限本機的記錄器預設啟用(與用戶端版共通)。它把可執行檔路徑、命令列參數(限制長度,控制字元跳脫)、父行程譜系、uid、容器 ID、可執行檔的 SHA-256 等,儲存於 /var/lib/roamswitch/exec_log,格式為附雜湊鏈的 JSON Lines(0600,預設 200 MB/14 天)。雜湊鏈可以偵測竄改,但無法防止竄改(取得 root 的攻擊者可以重寫整條鏈)。僅通知的關聯規則 EXR-001~010(由 Web 服務啟動 shell、從 /tmp 或 memfd 執行、攻擊工具串連等)單獨不會隔離。僅當維運人員明確啟用 exec_rules_isolation_optin(預設 false)時,高嚴重度規則才會被當作主機隔離的高信賴度觸發。

事件轉送(forward_enabled,預設 false)只傳送到維運人員設定的目的地:syslog(RFC 5424 或 CEF,UDP/TCP/TLS)、JSON Lines 檔案,或附 HMAC-SHA256 簽章的 Webhook。TLS syslog 透過系統的 openssl s_client,Webhook 透過系統的 curl(機密經由標準輸入的設定傳遞,不出現在命令列參數中),常駐程式沒有 TLS/HTTP crate。傳送的僅限於:出現在事件時間軸與通知歷史中的偵測事件(eBPF、隔離狀態轉換、FIM、金絲雀等)以及執行規則通知的主機名稱、事件 ID、時間、來源、嚴重度、規則、處置、PID、行程名稱與摘要欄位,外加執行記錄的分段封印雜湊。不包含執行記錄的原始日誌。

DNS 隧道/資料外洩偵測

啟用 dns_tunnel_detect_enabled(預設 true)後,會透過專用的 NFQUEUE 監控本機自身送出的 DNS 查詢(僅限 UDP/TCP 53 埠)。當標籤長度超過 40 位元組且夏農熵超過 3.8,或查詢記錄的 qtype 為 TXT/NULL 時(僅以 ClamAV 特徵碼更新所用、發往 clamav.net 的 TXT 不計入),會將該查詢視為 iodine、dnscat2 等 DNS 隧道工具典型特徵的「可疑形狀」查詢,僅當最近 60 秒內此類查詢達到 10 次以上時才發出通知(對同一網域的重複通知間隔 300 秒,突發持續期間會延長為 600 秒、1200 秒,最長間隔為 1800 秒)。僅檢查 DNS(UDP/TCP 53 埠)流量,不檢查其他流量。僅通知,不會自動封鎖。底層 nft 規則帶有 bypass 旗標,因此即使偵測執行緒停止或無回應,DNS 查詢仍會照常放行,不會因為此功能本身故障而阻斷網域名稱解析。此設定的變更需執行 roamswitch server restart 才會生效(不支援即時重新載入)。

已知限制。以連字號分隔的長主機名稱(例如 prod-us-east-1-web-server-node-0042),以及郵件伺服器在短時間內驗證多個不同寄件網域的 SPF/DKIM TXT 記錄這類在伺服器情境中特別常見的正常處理,經實測確認會因不區分目的網域的單一全域計數器統計 TXT/NULL 突發查詢而引發誤判。這兩點皆已於 2026-09-23 修復。已透過可設定的 entropy 允許清單,以及將突發計數器按 apex domain(對 QNAME 末尾兩個標籤的簡易近似,並非嚴格的 Public Suffix List 實作)分別計數的方式解決。允許清單預設內建 16 個主流 CDN/雲端服務與 PaaS 的尾碼(cloudfront.net、akamaiedge.net、akamaized.net、edgekey.net、edgesuite.net、fastly.net、azureedge.net、googleusercontent.com、amazonaws.com、r2.dev、workers.dev、vercel.app、netlify.app、supabase.co、firebaseapp.com、web.app),維運人員可透過 ServerConfig.dns_tunnel_entropy_allowlist(server.conf 中以逗號分隔的鍵值,亦可在 TUI 中編輯)加入自有內部網域。允許清單僅會豁免標籤長度+熵值的可疑判定,TXT/NULL 的 qtype 判定始終有效,不受允許清單影響,藉此防止攻擊者在允許清單網域下偽裝隧道(唯一的例外是 ClamAV 特徵碼更新所用、發往 clamav.net 的 TXT。由於第三方無法在該網域下建立子網域,因此不計入)。突發計數器已按 apex domain 分別計數,消除了因單一全域計數器不區分目的網域而產生的誤判(60 秒滑動視窗與 10 次的閾值這項判定邏輯本身,並未因此次修正而變更。重複通知的間隔之後改為在突發持續期間從 300 秒延長至最長 1800 秒)。iodine、dnscat2 等真實惡意流量只會在單一攻擊者控制的網域下輪換標籤與記錄類型,因此按 apex domain 分別計數並不會降低偵測能力。

SSH 暴力破解的偵測與封鎖(ssh_guard)

RoamSwitch 內建的暴力破解防禦,由 ssh_guard_enabled(預設 true)啟用。它透過 journalctl -f 從 journald 即時讀取 sshd 日誌(僅在沒有 journald 的環境才追蹤 auth.log/secure),依來源位址統計失敗次數,對達到門檻(預設 600 秒內 6 次)的來源,在 inet roamswitch_sshguard 資料表中只丟棄其發往 SSH 連接埠的新連線(ct state new)。封鎖的同時,也會切斷該來源已建立到 SSH 的連線(刪除其 conntrack 項目,並新增一條丟棄回應方向封包的規則)。只有既沒有已驗證工作階段、也沒有公開金鑰登入成功紀錄、也不在豁免之列的來源才會被封鎖,且在切斷前會再確認一次,因此已驗證的工作階段與豁免的來源不會被切斷。封鎖從 1 小時開始,每次再犯延長為 4 倍,上限 7 天,到期由 nftables 的逾時處理。不會啟動 Air-Gap(隔離),也不會向外部通訊(只在本機執行 journalctl、nft、loginctl 等指令)。當 fail2ban(sshd 的 jail 已啟用)或 CrowdSec(firewall bouncer 正在執行)已在保護 sshd 時,它會讓出封鎖,只做偵測與通知。

日誌行中含有攻擊者可以決定的字串(使用者名稱)。因此來源位址只從行尾的 from <IP> port <N> 讀取,即使在使用者名稱中寫入偽造的來源位址,第三方也不會被封鎖。對於 journald,只讀取傳送端憑證(_UID、_COMM)屬於 root 的 sshd 的行,忽略以 logger -t sshd 寫入的行。追蹤檔案(auth.log)沒有能保證傳送端的欄位,能使用 syslog 的本機使用者可以偽造行,所以不作為預設方式。為避免把維運人員鎖在門外,閘道、DNS、本機自身、迴路位址、whitelist_ips、ssh_guard_allow、已驗證 SSH 工作階段的來源位址、30 天內以公開金鑰驗證成功過的來源位址,以及已配對的 Sensor 都不會被封鎖。私有位址不豁免。公開金鑰的失敗(Failed publickey)不計入。

實測(Ubuntu 24.04 虛擬機,真實的 journald 和 systemd):從第 6 次失敗到封鎖約 0.2 秒(0.17 至 0.24 秒)。維運人員的來源位址沒有被封鎖,在使用者名稱中寫入偽造來源位址的嘗試也沒有讓第三方被封鎖。真實的 hydra(4 並行)在 6 次失敗後被攔停。同時確認了:伺服器重新啟動後封鎖會連同剩餘時間一併還原,封鎖可以解除,以及 fail2ban 在保護 sshd 時只做偵測與通知。這些數值來自這一台虛擬機環境。加入切斷連線後的實測中,封鎖之後仍然通過的失敗次數,加入前為 16~24 次,加入後為 0~4 次。僅刪除 conntrack 項目並不能切斷連線,加上丟棄回應方向封包的規則之後才生效。

Web 應用層偵測規則(Web Shell 與注入程式碼)

Server Edition 此前沒有在寫入時觸發檢查的路徑,只有對 clamav_scan_dirs 的定期掃描。現在它以僅通知的 fanotify(FAN_CLASS_NOTIF,絕不會使其他行程停滯)監視從 Web 伺服器(Apache、nginx、Caddy)設定中找到的文件根目錄,在 PHP、JavaScript、JSP、ASP 等檔案寫入並關閉後立即以 Web 應用層偵測規則(Web Shell、被注入的混淆程式碼、偽裝成圖片的 PHP、.htaccess 濫用)檢查。為彌補可能遺失的事件與啟動前已存在的檔案,每 6 小時還會定期掃描。規則分三層(內建、每日更新程式驗證簽章後安裝、/etc/roamswitch/rules.d/*.json 中的自訂規則);18 條規則不含從真實樣本擷取的簽章,只描述公開記載的手法。

在 Server Edition 中,自動隔離預設僅限 critical。high 只發送通知並觸發偵測後掛鉤,不會觸碰運作中網站的檔案。通知(Telegram、LINE、Webhook)為 10 種語言,每次偵測都會寫明規則名稱以及檔案是已隔離還是保留。規則的取得併入與每日更新程式相同的一次取得,不會新增通訊目標。關閉 cve_kernel_map_updates_enabled 後完全不進行網路通訊,使用內建規則運作。在真實的 fanotify 監視下,寫入的 Web Shell 在 2 秒內被隔離,無害檔案被保留。

偵測之後,若在 /etc/roamswitch/hooks/post-detection 放置可執行檔,偵測內容(JSON)會透過標準輸入傳給它(僅執行 root 所有、不可寫且父目錄也安全的檔案;不經過 shell,環境變數極少,30 秒後終止)。選用的帳號處置(預設關閉)會停用被隔離檔案擁有者的登入 shell。它不會處理 root、UID 低於 account_min_uid(預設 1000)的帳號、已登入的使用者與常駐程式自身的使用者,並會記錄原 shell,可用 roamswitch web-rules unlock-account 還原。誤報實測:WordPress 核心 2,409 個檔案、phpMyAdmin 3,356 個檔案、npm 相依套件 14,743 個檔案均為 0 筆。限制:只讀取開頭 256 KB(寫入/執行時)與 4 MB(掃描),無法追蹤變數名稱拼接('ev'.'al')這類拆分;因沒有真實樣本,未附帶針對已知惡意軟體的個別簽章。

蜜餌權杖(憑證誘餌)

常駐程式啟動時,會在攻擊者及自動化竊取憑證工具實際會掃描的已知真實路徑——/root/.aws/credentials、/root/.ssh/id_rsa、/root/.docker/config.json、/root/.pypirc、/root/.env.backup(因常駐程式以 root 身分執行,位於 /root 下)——冪等地部署包含 ROAMSWITCH_HONEYTOKEN 標記的偽造憑證檔案(預設開啟;可用 honeytokens_enabled 關閉,部署位置可用 honeytokens_home 變更)。若該路徑下已存在真實檔案,則絕不覆寫(部署前一律先檢查檔案是否存在)。對蜜餌權杖的實際存取還可能觸發設有上限的連鎖部署,追加相關誘餌檔案(如額外的 AWS 設定檔、SSH config、kubeconfig 等)。截至 1.10.4 的發行套件未包含此功能所需的 roamswitch-honeytokens,因此以套件安裝的環境中該功能並未執行。自 1.10.5 起已隨附,伺服器版中 systemd 沙箱阻擋寫入 /root 的問題也在 1.10.5 修正。自 1.11.1 起,RoamSwitch 本身執行的 docker 指令,會以空的專用目錄作為 DOCKER_CONFIG 啟動,因此不會對誘餌 /root/.docker/config.json 產生反應。其他程式讀取時,會和以往一樣偵測。

背景監控行程(roamswitch-honeytokens)使用通知類的 fanotify(不會阻止任何操作)監控每個誘餌檔案的讀取與開啟。事件會帶有存取來源的 PID,因此可以當場識別存取來源的可執行檔(在無法使用 fanotify 的環境中,會切換為 inotify 與 fuser)。由於正常行程原本沒有理由讀取這些檔案,除了 RoamSwitch 自身的二進位檔,以及針對 SSH 誘餌的 OpenSSH 用戶端(ssh、scp、sftp、ssh-add、ssh-agent 等,不含 ssh-keygen)之外的存取,都會被視為入侵者得手後偵察(MITRE ATT&CK T1552, Unsecured Credentials)的強烈訊號並發出通知。無法識別存取來源可執行檔的存取,也不會放行,而是視為偵測。此功能僅用於通知,不會進一步凍結或封鎖發起存取的行程。

已知限制。/root/.ssh/id_rsa 誘餌檔案的內容包含可讀文字,其 base64 主體仍不是有效的 OpenSSH 私密金鑰格式。不過多數機密掃描工具僅透過比對 -----BEGIN ... PRIVATE KEY----- 標頭的正規表示式來標記檔案,因此我們判斷這對實際偵測率的影響有限。另外,在無法使用 fanotify 而切換為 inotify 的環境中,識別存取來源行程(呼叫 fuser)對於讀取檔案後立即結束的極短命行程,可能無法取得其 PID・行程名稱;此時僅會視為「未知」,不影響對存取本身的偵測(事件仍會觸發並發出通知)。

證據保全包(自動鑑識採集)

證據採集會在下列情形啟動。eBPF 執行期威脅感測器的事件促成了單一處理程序(per-process)網路隔離並成功時;該隔離失敗並升級為主機層級的 Air-Gap 時;或執行了遮斷整台主機的 Air-Gap 時。勒索軟體金絲雀偵測到竄改,並執行處理程序凍結與主機隔離的路徑也會啟動。在遮斷整台主機的路徑上,採集會在遮斷之前啟動,且不會讓遮斷等待。1.10.4 及之前僅在單一處理程序隔離成功時才會啟動,1.10.5 起擴大了範圍。若無法得知目標處理程序的 PID,則不採集 /proc 快照。roamswitch-incident-capture 啟動後,會將證據包儲存到 <狀態目錄>/incident-evidence/<時間戳>-<短 ID>/。採集內容包括:於預設路由介面上以 tshark 進行、限定 30 秒的封包擷取(若未安裝 tshark 則僅記錄為跳過),以及目標處理程序的 /proc/<pid> 快照(status/cmdline/maps、將疑似機密資訊的值替換為 [REDACTED] 的 environ、已開啟檔案描述子的連結目標清單(不採集內容本身),以及祖先處理程序鏈)。單一證據項採集失敗不會讓整個證據包中止,而是記錄該情況並繼續採集其餘內容。截至 1.10.4 的發行套件未包含此功能所需的 roamswitch-incident-capture,因此以套件安裝的環境中該功能並未執行。自 1.10.5 起已隨附。

採集結果彙整於 manifest.json 中,並記錄證據包內所有證據項的 SHA-256 雜湊(供事後偵測竄改)。證據包不會自動刪除。只有在維運人員明確執行 sudo roamswitch-incident-capture prune [--keep-days N](預設保留期間 30 天)時,舊的證據包才會被刪除。系統也提供 sudo roamswitch-incident-capture snapshot [--pid PID] [--reason TEXT] [--json] 指令,可在任意時間點手動採集。

採集到的證據在採集當下並不會被驗證。若需事後確認是否遭竄改,請執行 sudo roamswitch-incident-capture verify <證據包目錄> [--json]。此指令會對證據包內目前的所有檔案重新計算雜湊,並與 manifest.json 中記錄的值比對,將差異分別回報為「已修改」「遺失」或「未記錄」(存在但清單中未記錄的檔案)。

已知限制。此驗證會把 manifest.json 的 SHA-256 與保存在證據包之外的記錄進行比對,記錄在兩處:證據包之外的記錄鏈(evidence_anchor.log,每一行都連接到上一行,並附加僅附加的屬性)和系統日誌(標籤 roamswitch-evidence)。採集後改寫 manifest.json 會使 verify 失敗;改寫或刪除記錄中的某一行,也會因鏈斷裂而失敗。但如果擁有 root 權限的攻擊者能同時改寫這條鏈和系統日誌的轉送目的地,則無法防範。建議把系統日誌轉送到另一台機器。尚未實作簽章。沒有此記錄的證據包(由舊版本採集)會顯示為「無記錄」,表示沒有外部佐證。

§534 檢查安全診斷套件

伺服器版執行 34 項專門的安全健康審核:

# 類別 檢查標題 標準與邏輯
1授權和存取SSH Root 登入和密碼驗證驗證 PermitRootLogin no。若密碼驗證也已停用,則回報為僅限公開金鑰驗證;即使密碼驗證為啟用,只要禁止 root 登入即判定為通過
2授權和存取空密碼帳戶確保 /etc/shadow 中沒有使用者俱有空白密碼雜湊
3授權和存取Sudoers 特權衛生稽核 /etc/sudoers 與 /etc/sudoers.d 中是否沒有不需密碼即授予完整權限的 NOPASSWD: ALL
4網路入站預設拒絕審核 nftables 的預設入站丟棄策略
5核心與完整性非特權使用者命名空間(碎片間隙)透過 user.max_user_namespaces=0(或 kernel.unprivileged_userns_clone=0)阻斷 LPE 攻擊路徑
6核心與完整性eBPF BTF 支持透過 /sys/kernel/btf/vmlinux 驗證核心 BTF 型別資訊
7核心與完整性eBPF LSM 活動檢查核心 lsm= 啟動參數中的 bpf
8網路XDP 開機時閘門以 XDP 預設拒絕閘門涵蓋 Link Guard 的 nftables 表載入之前的開機空窗期(實驗性功能,預設不載入,需主動啟用)。檢查是否存在 pinned link;未載入不視為不合格
9核心與完整性eBPF 執行階段安全代理確認 Falco / Tetragon 等代理是否在執行。Falco 執行時,還會確認 RoamSwitch 自己規則的警報是否返回(心跳檢測),未返回則不合格(若缺少 RoamSwitch 的 Falco 檔案,會一併給出檔名)
10核心與完整性統一事件時間軸檢查將 Link Guard、Canary、eBPF Guard 與 Resource Guard 的事件依時間順序整合的時間軸是否處於可記錄狀態(已有事件紀錄,或儲存位置可寫入),並顯示最近一次圍堵耗時
11貨櫃Docker Socket 掛載稽核偵測容器是否掛載 /var/run/docker.sock
12貨櫃Docker 特權容器高風險 --privileged 容器工作負載的審核
13貨櫃容器執行階段隔離等級 (runc/gVisor/Kata)檢查預設容器執行階段。以 runc 為基礎的執行階段(共用主機核心)判為不合格;偵測到 gVisor(runsc)或 Kata Containers(每容器虛擬機隔離)則合格。未偵測到 Docker/containerd 時視為不適用
14貨櫃Docker 防火牆繞過防護 (DOCKER-USER)驗證 RoamSwitch 自身的規則是否確實存在於始終最先執行的 DOCKER-USER 鏈(或其專用的 Docker 防護 nftables 表)中,避免已發布的容器連接埠透過 Docker 自身規則繞過防火牆的預設拒絕。僅在 server.conf 中啟用 protect_docker_ports 時才評估
15核心與完整性ClamAV 實際偵測測試(EICAR)常駐程式在啟動 2 分鐘後及此後每 6 小時,從自身執行環境(例如 systemd 沙箱內)掃描一個無害的 EICAR 測試檔,確認 ClamAV 確實能夠偵測。僅在 server.conf 中啟用 clamav_enabled 時才評估
16核心與完整性fanotify 事件遺失(佇列溢位)檢查是否因 fanotify 事件佇列溢位而被核心丟棄了 FIM 與容器執行監控事件。溢位期間的檔案寫入與執行會逃過即時監控;若頻繁發生,請調高 fs.fanotify.max_queued_events
17核心與完整性執行中核心的已知 CVE 暴露將執行中的核心版本與本機已知 CVE 對照表(內建基準,或經過簽章驗證的更新)進行比對。檢查本身不進行任何對外通訊,對照表更新依 cve_kernel_map_updates_enabled(預設 true,可以關閉)取得。無法確定時以「無法判定」處理,而非判為不合格
18誠信關鍵路徑檔案完整性 (FIM)對 23 個固定的關鍵檔案以及 12 個目錄下的全部檔案等進行 SHA-256 雜湊完整性驗證
19核心與完整性Yama過程保護確認 kernel.yama.ptrace_scope 為 2 或 3,以防止記憶體竊聽
20網路IP 轉送已停用驗證 net.ipv4.ip_forward = 0
21網路TCP SYN Cookie 保護驗證 net.ipv4.tcp_syncookies = 1
22網路反向路徑過濾(rp_filter)確認 net.ipv4.conf.all.rp_filter 為 1(嚴格)或 2(寬鬆,適用於多宿主組態),以丟棄偽造封包
23核心與完整性核心轉儲限制透過 fs.suid_dumpable = 0 防止進程記憶體洩漏
24營運自動安全性更新確認透過 unattended-upgrades(Debian / Ubuntu)或 dnf-automatic(RHEL / Fedora)等進行的自動修補套用設定
25營運NTP時間同步透過 chrony 或 systemd-timesyncd 檢查同步
26營運SSH 暴力保護RoamSwitch 內建的 SSH 防護(ssh_guard)正在執行並進行封鎖時,或透過 fail2ban / crowdsec 驗證主動監控
27核心與完整性禁用非特權 eBPF確認 kernel.unprivileged_bpf_disabled 為 1 或 2,以防止 Spectre/LPE
28網路忽略 ICMP 重定向透過 accept_redirects = 0 防止路由中毒
29網路忽略 ICMP 回顯廣播緩解 Smurf 放大器 DoS 攻擊
30核心與完整性共享記憶體強化確認 /dev/shm 至少帶有 nodev、nosuid、noexec 其中一項掛載選項
31授權和存取不存在遺留的不安全協議驗證未安裝明文監聽服務(telnetd、rshd、tftpd 等)和明文用戶端(telnet、rsh、tftp 等)(服務與用戶端分開顯示)。
32核心與完整性SUID 進程核心轉儲受限防止 SUID 二進位檔崩潰時洩漏憑證
33核心與完整性輔助程式(誘餌與取證)已安裝常駐程式依名稱啟動憑證誘餌(蜜罐令牌)程式與取證包程式,缺少時會靜默地什麼都不做。此項檢查這兩個程式是否已安裝。
34網路Web 公開目錄中的敏感檔案暴露從 Apache / nginx / Caddy 設定找出文件根目錄,並透過向伺服器自身發送請求,檢查其中的 .git、.env、.DS_Store、phpinfo、SQL 傾印、備份與私密金鑰能否經由 Web 伺服器實際讀取。只有回應與磁碟上檔案的開頭一致時才判定為暴露,因此對所有路徑都回傳 200 的網站,或已用 403 拒絕的檔案,都不會誤報。不會回報檔案內容,只顯示路徑。沒有 Web 伺服器的環境為不適用;無法確認時視為「無法判定」,不扣分。

在適用的情況下,為 34 個檢查項目中的每一項標註 NIST CSF 2.0 的功能/類別識別碼(例如 PR.DS-01、DE.CM-09),並僅限於存在可靠對應關係的項目,一併標註 CIS Controls v8 的控制編號(例如 10.1、4.1)。對應關係不明確的項目不會被勉強標註,而是維持未對應狀態。CLI(roamswitch server status)與 MCP(get_security_report)的輸出中皆包含此對應表,方便需要符合法遵要求的維運人員與稽核人員,將各個檢查項目機械式地對應到既有框架。

§6自我檢查(Docker 環境下的可重現驗證)

針對從官方 APT 儲存庫安裝的 roamswitch-server 套件,以 Docker 中的另一個容器作為外部攻擊者,進行模擬內部與外部攻擊的自我檢查。2026-09-07 在 v1.3.2 上的實測為全部 18 項 PASS。2026-09-25 使用 1.10 系列原始碼建置的套件(arm64、Docker Desktop)再次執行,19 項檢查全部 PASS。此次重新執行發現 6 個產品缺陷並已全部修正(已包含在 1.10.5 中)。明細為:套件缺少輔助執行檔、FIM 將蜜餌權杖回報為新檔案、確認(ack)被忽略、隔離期間受保護的管理用 SSH 回應被丟棄而導致管理者無法登入、即使設定 preserve_ssh_on_isolation=false 連接埠 22 仍是開啟的,以及 systemd 單元的沙箱阻擋了誘餌的寫入。您可以在自己的機器上重現此驗證。步驟與腳本請參閱下文「自行重現的方法」。

# 場景 攻擊向量 確認結果
PENT-S1 Nmap SYN 隱形掃描 跨連接埠 22、80、443、3306、8080 進行探測 nftables Default Drop 使未允許的 3306 (MySQL) 與 8080 完全不回應而直接丟棄(Filtered)。100% 阻斷
PENT-S2 不允許的連接埠偵測 卷曲直接连接到端口 3306 和 8080 透過入站預設拒絕,僅已允許的連接埠 80 正常回應,其餘皆逾時遭阻斷
PENT-S3 Egress / C2 封鎖清單 嘗試向惡意 IP 情資中登記的位址發起出站連線 透過 egress_ip_blocklist_enabled(預設 true、nftables)僅封鎖已登記的位址。與未登記主機的通訊不受影響(並非一律封鎖)
PENT-S4 FIM 竄改攻擊 將後門有效負載注入 /bin/login SHA-256 Critical Path FIM 即時偵測到竄改。正規還原後,基準線正確重新同步
PENT-S5 guard.yaml 依嚴重程度分級的圍堵 注入引用真實處理程序的 Falco Critical 事件 以 on_critical: isolate_process + kill_process 對相關處理程序進行網路隔離後,再送出 SIGKILL
PENT-S6 受保護處理程序安全機制 注入引用真實 sshd PID 的同類事件 透過受保護處理程序清單(sshd/systemd/容器執行環境等),sshd 持續執行。僅將拒絕記錄為誤判日誌
PENT-S7 安全計時器 讓 Air-Gap 事件保持未確認狀態(無操作員 ACK) 透過 safety_timer_secs,無回應時自動復原。若已 ACK,則隔離持續到執行 emergency-restore 為止
PENT-S8 內核 LPE 碎片間隙 以一般使用者權限執行 unshare -U -r(於真實的 VM 上確認) 沒有本產品時會被允許的 unshare -U -r,在啟動後遭到拒絕。user.max_user_namespaces 與 kernel.unprivileged_userns_clone 為 0,Yama 的 ptrace_scope 為 2,非特權 eBPF 已停用(2026-09-25,Ubuntu 24.04 的 VM,已以 v1.10.4 的公開版與修正版兩者確認)

註:PENT-S7 的實測值為 v1.3.2 時的資料。目前版本中,高信心度觸發器造成的隔離在確認原因消失後解除,而維運人員已確認(ack)的隔離會維持到維運人員解除為止(確認被忽略的缺陷已在 2026-09-25 的重新執行中發現並修正)。低信心度觸發器仍由同一計時器恢復。詳見 §4。

驗證類型 — PENT-S8 確認核心功能(禁止使用者命名空間)已生效。PENT-S1、S2 確認 RoamSwitch 所設定的 nftables 規則,實際丟棄封包的是核心。檢驗 RoamSwitch 自身邏輯的項目是 PENT-S3(訂閱來源套用)、S4(FIM)、S5、S6(圍堵與受保護程序)與 S7(安全計時器)。

SSH 鎖定防護機制

preserve_ssh_on_isolation=true(預設)的設計是在 Air-Gap(on_emergency)期間保留管理用 SSH。但 2026-09-25 的重新執行顯示,1.10.4 及之前的隔離規則會丟棄 SSH 的回應,導致隔離期間維運人員被鎖在外面;先前的檢查只是在隔離解除之後才成功。該問題已在 1.10.5 修正,並在隔離原因仍然存在的條件下,驗證了隔離期間 SSH 可以通過。

驗證範圍的侷限性(誠實揭露)

本次驗證無法確認的事項

核心強化(停用非特權 User Namespace、提升 Yama ptrace_scope)無法在容器內進行端對端驗證。由於這些 sysctl 並非按容器命名空間隔離,特權容器(--privileged)中的寫入操作影響的並非驗證用的沙箱,而是正在執行本次驗證的真實機器本身。因此,本次驗證僅確認該 sysctl 寫入操作在(面對唯讀檔案系統時)能夠優雅降級而不當機,至於其數值是否真正生效,則需要在本產品實際運作的真實機器或虛擬機上進行確認。此項確認已於 2026-09-25 在 Ubuntu 24.04 的 VM 上進行過一次(請參閱 PENT-S8 的列)。

自行重現

上述所有驗證結果,均可透過官方支援儲存庫(roamswitch-support)中公開的 Docker 測試套件,僅使用官方發行套件在您自己的機器上 100% 重現(無需存取原始碼,也無需信任我們)。

# 取得並重現驗證套件(從官方 APT 儲存庫自動安裝 roamswitch-server)
git clone https://github.com/lafine1211/roamswitch-support.git
cd roamswitch-support/test/docker/server
./run.sh

在 Docker 的預設橋接網路上建立 Target、Attacker、C2 誘餌共 3 個一次性容器,自動驗證 18 個項目並輸出報告。v1.3.2 的完整執行結果已公開於 RESULTS-PENTEST-SERVER-2026-09-07.ja.md(基於透明原則,亦記載了建置過程中發現並修正的測試工具本身問題)。2026-09-25 重新執行的記錄請見 RESULTS-PENTEST-2026-09-25.ja.md。

§7營運、部署和生命週期

7.1 無頭 CUI 工具和設定精靈

透過 CLI 完成遠端管理:

  • roamswitch server status:輸出 34 項目的診斷報告(支援 10 種語言,依執行使用者的設定或作業系統的地區設定)。
  • roamswitch server setup:連接埠和通知的互動式終端精靈。
  • roamswitch server config show / set <key> <val>:Ansible/Terraform 的可編寫腳本的自動化。
  • roamswitch server test-notify [all|telegram|line|webhook]:端對端通知探測。
  • roamswitch server config set language <ja|en|zh-Hans|zh-Hant|ko|de|fr|es|it|pt|system>:常駐程式的定期診斷報告(每小時)與推播通知(Telegram/LINE/Webhook,包括測試傳送)的語言(每台主機一種語言)。system 跟隨作業系統地區設定,無法辨識的地區設定會退回為 ja。roamswitch server status 的顯示語言不依此設定,而是依執行使用者的設定或作業系統的地區設定。
  • roamswitch server bans [--json] / sudo roamswitch server unban <IP|IPv6 的 /64|--all>:檢視 SSH 暴力破解防護的狀態,以及封鎖清單與解除。MCP 的 get_ssh_guard_incidents 為唯讀,不能解除封鎖。

Server TUI(roamswitch server tui)

這是一個可透過 SSH、在 80x24 終端機中僅用鍵盤操作 Server Edition 全部功能的終端機介面(roamswitch server tui 或 roamswitch-server-tui)。共有 11 個畫面:儀表板、防禦、事件、通知與轉送、Sensor、設定、服務、工具、日誌稽核、資訊與說明、Fleet。設定編輯器由 server.conf 與 guard.yaml 的鍵定義(綱要)產生,會驗證型別、範圍與列舉值,顯示是否需要重新啟動,儲存前展示差異,並以附時間戳記的備份與原子寫入儲存(權杖等機密值以遮罩顯示、輸入時不回顯)。復原隔離、ACK、更新 FIM 基準線、停止服務等影響較大的操作會顯示寫明影響的確認畫面,影響特別大的還要求輸入 yes(鍵入式確認)。非 root 時為唯讀,並提示所需的 sudo roamswitch ... 命令。沒有設定重新載入(reload),需要重新啟動服務才會生效。介面支援 10 種語言。

7.2 包裝

以 Debian / Ubuntu 用的 .deb 套件,以及 RHEL / Fedora 用與 openSUSE 用的 .rpm 套件提供。

§8結論

RoamSwitch Server Edition 以單一整合套件為雲端與企業 Linux 基礎架構提供「零遙測(預設的對外通訊只有可以關閉的、僅接收簽章資料的一項)」「基於入站預設拒絕的穩固邊界防護」「關鍵路徑竄改的即時偵測」「核心權限提升的預防性阻斷」。

針對攻擊者瞄準的主要階段(初期偵察、入侵、權限提升、持久化),將多層偵測與自主封鎖(Air-Gap)結合的 Linux 伺服器安全套件。

本文件基於 RoamSwitch Server Edition v1.11.1(入站預設拒絕/關鍵路徑 FIM/guard.yaml 政策引擎/核心 LPE 強化/eBPF 執行階段監控/Air-Gap 分級解除/執行記錄器與事件轉送/Server TUI/DNS 隧道偵測/蜜餌權杖/鑑識證據保全/NIST CSF・CIS Controls 對應/簽章核心 CVE 對照表更新)當時的實作。但 §6 的自我檢查實測值,來自 v1.3.2(2026-09-07)以及以 1.10 系列原始碼建置的套件(2026-09-25)。逐項變更歷史請參閱 roamswitch-support 的 CHANGELOG。最新資訊請參閱 roamswitch.com/linux。