---
title: C21 api → agent 資料面
eyebrow: Guidant AI 資安檢視總報告 · 連線清單
h1: C21 主系統 api → 代理程式資料面（HTTPS :8443，mTLS）
lede: 唯一一條**由我們雲端主動連進客戶機房**的線。「測試連線」按鈕、取消掃描、取回證據檔都走它，而且請求裡會帶**解密後的工具帳密**要代理程式拿去連內網。這一頁回答：這條線**怎麼連**、**哪些功能走它**、它帶來**什麼威脅、駭客怎麼打**、我們**要怎麼防、目前做到哪**。
chips:
  - { text: "裝了 agent 才有", kind: plain }
  - { text: "客戶要開 8443 入站", kind: warn }
  - { text: "威脅 4 種", kind: accent }
  - { text: "掃描命中 4 條", kind: plain }
---

> **這一頁怎麼來的**：[DFD Level 0](../DFD/dfd-level0.html#c21) 把產品運作時的連線編成 C01～C25；[STRIDE 六頁](../STRIDE/S-spoofing.html)每一條問題都標了發生在哪幾條線。這裡以**連線**為單位整理。個別問題修了沒不在這頁講，請點條目連回 STRIDE 頁。

## 一、連線圖

```{.mermaid cap="C21 — 雲端打進代理程式 :8443。這是反方向的線：客戶防火牆要放行入站 8443。agent 自己起 TLS 伺服器並強制要雲端出示客戶端憑證（真 mTLS），再驗一張 60 秒短效 JWT——綁這台的編號與硬體指紋。/health 與 /agent-info 兩支不驗。"}
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB'}}}%%
flowchart LR
    U(["👤 有工具設定修改權的使用者<br/>按「測試連線」"])
    subgraph MAIN["🏠 主系統 stack"]
        API["guidant-api<br/>解密工具帳密<br/>簽 60 秒 JWT<br/>出示雲端客戶端憑證"]
    end
    subgraph AGENTBOX["🏢 客戶機房"]
        direction TB
        subgraph AG["evidence-agent :8443（agent 自起 TLS）"]
            direction TB
            MTLS["① 要求客戶端憑證<br/>（CERT_REQUIRED）"]
            JWTG["② 驗 JWT：簽章・發行者・<br/>aud＝本機編號・bound_fp＝本機指紋・60 秒"]
            EP["/detection/probe 測試連線<br/>/detection/cancel 取消<br/>/blob/… 取檔"]
            OPEN["/health・/agent-info<br/>不驗"]
            MTLS --> JWTG --> EP
            MTLS --> OPEN
        end
        TOOL(["🖥 內網：受檢主機／工具伺服器"])
        EP -- "C23／C23a · 用請求帶的帳密去連" --> TOOL
    end
    U -- "C02" --> API
    API == "C21 · HTTPS :8443 · mTLS＋JWT<br/>body 含明文工具帳密" ==> MTLS
    classDef ext fill:#FBFCFC,stroke:#9AA8AA,stroke-dasharray:3 2
    classDef open fill:#FDECEC,stroke:#C0392B
    class U,TOOL ext
    class OPEN open
```

## 二、這條線怎麼連

| 項目 | 現況 |
|---|---|
| **誰 → 誰** | 我們的 `guidant-api` → 客戶機房 `evidence-agent` 容器的 :8443。**方向是雲端連入客戶**，客戶防火牆要放行 8443 入站；agent 的對外位址在安裝時填（`AGENT_BASE_URL`），報到時回報給雲端存在 `remote_agents.base_url` |
| **協定／埠** | HTTPS :8443。TLS 由 agent 程式自己承接（nginx sidecar 已退役），最低 TLS 1.2。認證模式下雲端要求 `base_url` 必須是 `https://`，否則不發 |
| **傳什麼** | 三件事：① **測試連線**（`POST /detection/probe`）——body 帶**解密後的工具帳密**（SSH／WinRM 密碼、OpenVAS／ZAP／SonarQube 帳密或權杖）與目標主機清單，要 agent 就近去連並回成敗；② **取消掃描**（`POST /detection/cancel`）——帶任務編號；③ **取檔**（`GET /blob/<uid>`、`/blob/<uid>/sha256`、`/blob/<uid>/pdf`）——雲端從 agent 暫存取回證據檔 |
| **怎麼驗身分** | **兩層，真 mTLS**：① agent 的 TLS 伺服器設 `verify_mode = CERT_REQUIRED`，雲端必須出示由同一個內部 CA 簽的客戶端憑證（BE `.env` 的 `AGENT_CLOUD_CLIENT_CERT/KEY`），沒帶直接 400；② 通過 TLS 後，`before_request` 驗 `Authorization: Bearer <JWT>`——RS256 簽章、發行者固定、**受眾必須等於這台 agent 的編號**、**`bound_fp` 必須等於這台的硬體指紋**（`product_uuid`＋`machine-id` 算出）、效期 **60 秒**（`AGENT_JWT_TTL_SEC`，每次請求現簽） |
| **哪些不驗** | `/health`（容器健康檢查用、綁 :8000 僅容器內）與 `/agent-info` 不在受保護前綴內，**:8443 上也打得到**。`/agent-info` 回什麼要注意（見六） |
| **雲端怎麼信 agent** | 雲端用內部 CA（`AGENT_CA_CERT`）驗 agent 出示的伺服器憑證——那張是 agent 報到時雲端自己簽的，SAN 取安裝時填的對外位址 |
| **帳密在這條線上的樣子** | probe 的 body 是**明文帳密**（TLS 保護傳輸）。agent 端只在本次請求記憶體內使用、不落地、log 只記主機與工具不記帳密 |
| **何時存在** | 客戶有裝代理程式、且雲端 `AGENT_AUTH_MODE=full`（installer 預設寫 full）。`mode=none` 是 demo 模式：裸 http、不驗任何東西——**正式部署不該出現** |

依據：agent repo `core/data_plane_server.py`（`CERT_REQUIRED`）、`core/data_plane_auth.py`（受保護前綴 `/blob`、`/detection`；JWT 四項檢查）、`core/agent_auth.py`（`verify_data_plane_jwt`）、`api/detection/routes/detection_route.py`、`api/blob/__init__.py`；套件 `jedi_remote_agent/common/agent_auth/tls.py`（雲端 mTLS context）、`jwt_util.py`（`jwt_ttl_sec=60`）、`jedi_detection/infra/detection_tools/connector/agent_probe_client.py`；主專案 `config/config.py:274-284`、`scripts/installer/install.sh:1705`（`AGENT_AUTH_MODE=full`）。

## 三、哪些功能會走這條線

| 群 | 功能 | 對威脅的意義 |
|---|---|---|
| **① 測試連線** | 檢測工具設定頁的「測試連線」按鈕：雲端把該租戶的工具帳密解密、連同目標主機清單送給 agent，agent 用既有 connector 去連並回「成功／失敗＋訊息」 | 這是**唯一一條會把解密後的客戶帳密主動送出雲端的路徑**（掃描本身是 agent 來領、見 [C20](C20-agent-to-frontdoor.html)）。誰能按、按下去連到哪、結果回什麼，三件事都是攻擊面 |
| **② 取消掃描** | 使用者按取消，雲端通知 agent 真的中斷正在跑的子行程 | 影響的是可用性與紀錄完整性，不帶祕密 |
| **③ 取回證據檔** | 掃描報告先存在 agent 旁的 SeaweedFS（[C22](C22-agent-to-seaweedfs.html)），雲端經這條線取回寫進主系統儲存 | 取回的檔案會進證據清單、被人預覽——內容可信度在 [C20](C20-agent-to-frontdoor.html) T2 討論 |

## 四、這條線會帶來什麼威脅、駭客怎麼打

掃描在這條線上抓到 4 條問題（[M01-1](../STRIDE/E-elevation-of-privilege.html#m01-1)、[M03-2](../STRIDE/E-elevation-of-privilege.html#m03-2)、[M03-14](../STRIDE/E-elevation-of-privilege.html#m03-14)、[M03-6](../STRIDE/I-information-disclosure.html#m03-6)），歸納起來是**四種攻擊手法**。這條線特別的地方：**它的入口在雲端那頭的畫面**——三條（T2～T4）都是先在畫面上按一顆按鈕，雲端替攻擊者把帳密與請求送進客戶內網。

| # | 風險 | 威脅 | 駭客怎麼打 | 得手什麼 | STRIDE | 實例 |
|---|---|---|---|---|---|---|
| T1 | 🔴 最嚴重 | **冒充雲端打進客戶機房** | ① 連得到客戶的 :8443（同一內網、或客戶把 8443 開到了公網）；② 若 agent 不要求客戶端憑證、或不驗 JWT 的受眾與指紋，就能照格式送一個 `/detection/probe`，帶自己編的「帳密」與目標——讓 agent 替他去敲內網任何主機；③ 或送 `/blob/<uid>` 把 agent 暫存的證據檔取走 | 把客戶內網的代理程式當跳板掃內網；取走掃描報告 | [S 冒充身分](../STRIDE/S-spoofing.html)、[I 資料外洩](../STRIDE/I-information-disclosure.html) | [M01-1 代理程式五條通訊管道全部不檢查對方是誰](../STRIDE/E-elevation-of-privilege.html#m01-1) 🔴（該條的「下載證據檔」通道在這條線上） |
| T2 | 🟠 高 | **誰都能按「測試連線」——按下去雲端就把帳密解密送出** | ① 公司裡任何能登入的帳號（不需管理權限）；② 打開檢測工具設定頁記下某份設定的編號；③ 直接送測試連線請求，端點若只驗登入不驗「你能不能改這份設定」，就把 SSH／WinRM 密碼與三套工具權杖解密、經這條線送到 agent；④ 目標主機若由請求指定（T3），帳密就送進攻擊者控制的機器 | 整家公司用來掃描主機的維運帳密與工具權杖 | [E 權限提升](../STRIDE/E-elevation-of-privilege.html)、[I 資料外洩](../STRIDE/I-information-disclosure.html) | [M03-2 「測試連線」沒檢查權限，按下去就把維運帳密解密送到指定主機](../STRIDE/E-elevation-of-privilege.html#m03-2) 🟠 |
| T3 | 🟡 中 | **測試連線連到哪，由按的人自己填——代理程式變成內網探測器** | ① 有權按測試連線的人；② 目標清單放一整段內網位址；③ agent 逐台去連；④ 從每台「連得上／被拒／逾時」的差異畫出客戶內網哪些機器開著哪些服務。帳密也隨之送到每一台 | 客戶內網的主機存活與服務分布圖；帳密被送到非預期主機 | [I 資料外洩](../STRIDE/I-information-disclosure.html) | [M03-6 「測試連線」要連到哪台主機由呼叫者自己指定](../STRIDE/I-information-disclosure.html#m03-6) 🟡 |
| T4 | 🟡 中 | **不該動手的人取消或干擾正在跑的掃描** | ① 以唯讀角色登入；② 對別人的掃描按取消，雲端經這條線叫 agent 真的中斷子行程；③ 反覆取消再重派，正常檢測永遠跑不完 | 干擾稽核檢測、改掉執行紀錄 | [E 權限提升](../STRIDE/E-elevation-of-privilege.html)、[D 讓服務停擺](../STRIDE/D-denial-of-service.html) | [M03-14 唯讀角色可以對客戶機器發動掃描、刪掉執行紀錄](../STRIDE/E-elevation-of-privilege.html#m03-14) 🟡（取消那一支走這條線） |

**四種手法的共同點**：T1 是這條線**自己的**門——客戶機房對外開了一個埠，認錯對方就等於內網被接管。T2～T4 的門其實在 [C02](C02-frontdoor-to-api.html)——這條線只是忠實地把雲端叫它做的事做掉；但因為它做的事是「拿客戶的鑰匙去開客戶的門」，上游守門一鬆，後果直接落在客戶內網。

## 五、我們要怎麼防、目前做到哪

對應四種威脅與這條線的本質，防線分七條。D1～D4 直接對應掃描抓到的四種手法；**標 ◇ 的（D5～D7）是依這條線的特性補的標準防線，掃描範圍沒涵蓋、沒有實例**。「目前」欄寫程式與部署裡**實際有的機制**；⚠️ 表示目前只靠慣例或只守到局部。

| # | 防線 | 擋哪種威脅 | 目前做到哪 |
|---|---|---|---|
| D1 | **入站兩層驗：先要憑證、再驗綁定這台的短效票**。TLS 層強制客戶端憑證；JWT 要綁受眾（這台編號）與硬體指紋、效期以秒計、每次現簽 | T1 | ✅ `build_server_ssl_context` 設 `CERT_REQUIRED`（docstring 特別標紅：預設 `CERT_NONE` 會讓 CA 載入看似成功但完全不要求憑證）；✅ JWT 驗簽章＋`iss`＋`aud=agent_uid`＋`bound_fp=device_uuid`＋`exp`，60 秒；✅ 每次請求讀**當下**的註冊狀態（重註冊換 uid 後立刻用新 uid 驗）。⚠️ `/health`、`/agent-info` 在 :8443 上不驗 |
| D2 | **會送帳密出去的按鈕，要先問「你能不能改這份設定」**。測試連線掛與新增／修改／重置相同的能力點守門 | T2 | ✅ 路由補上 `@capability_required(plugin_update_capability)`，寫法照同檔三處既有宣告。⚠️ 這是唯一的防線——「連到哪裡」刻意不設白名單（D3） |
| D3 | **目標由呼叫者填，就要限量、收斂回應、記下誰按的**：單次主機數上限；回應只回成功／失敗，逐台診斷進日誌；稽核日誌記操作者、客戶、設定、工具、代理程式、目標清單 | T3 | ✅ 三件都做了：`DETECTION_TEST_CONNECTION_MAX_HOSTS` 預設 32、回應收斂、稽核日誌。**裁定不設目標白名單**（掃描目標是客戶自己的主機，哪台算合法由客戶管）。⚠️ 所以「有權按的人把帳密送到自己機器」這條路**依設計是開的**——防線是 D2 的權限門，不是目標限制 |
| D4 | **取消與重派只放行任務被指派人與專案管理者** | T4 | ✅ 八支寫入端點換成 `assert_job_operator`（見 [C02](C02-frontdoor-to-api.html) D1） |
| D5 ◇ | **agent 端對 probe 請求也要有上限**：單次主機數、逾時、併發數——雲端的限制是一道，agent 自己再守一道，不信雲端一定對 | T3 的延伸、T1 | ⚠️ agent 端 `DetectionProbeRoute` 沒有自己的主機數上限，照雲端送來的清單逐台連；逾時由各 connector 自訂（OpenVAS 60 秒等）。雲端那層守住就沒事，但這條線的設計哲學是「不信對方」，agent 端應該也量一次 |
| D6 ◇ | **8443 只對雲端開**：客戶防火牆只放行雲端的來源 IP；安裝文件要明寫 | T1 | ⚠️ 安裝手冊寫「雲端連得到本機 :8443（防火牆要放行 8443）」，**沒說只放行雲端來源**。mTLS 擋得住冒充，但開到公網就是多一個可被探測、可被打 TLS 層漏洞的埠 |
| D7 ◇ | **demo 模式不得出現在正式部署**：`AGENT_AUTH_MODE=none` 是裸 http、不驗任何東西 | T1 | ✅ installer 寫 `AGENT_AUTH_MODE=full`、agent compose 預設 `full`、雲端在 full 模式下拒絕非 https 的 `base_url`；維運工具 `guidantai` 在 mode 不對時明確報錯指路。⚠️ 主專案 `config.py` 預設值仍是 `none`——靠 installer 寫 `.env` 蓋掉；手動部署忘了設就是 demo 模式，且沒有啟動期檢查擋它 |

**最該補的一步**：D7 的預設值。`AGENT_AUTH_MODE` 在程式裡預設 `none`、靠 installer 寫成 `full`；正式設定類（`StagingPremiseConfig` 等）應該在啟動時檢查 `mode != full` 就拒絕啟動——同 `SANDBOX_MODE` 留空在正式設定會拒絕啟動的做法。一行檢查，擋掉「手動部署忘了設、整條線變裸 http」。

## 六、依這些防線，掃描還沒看過的地方

- **`/agent-info` 在 :8443 回了什麼**（D1）：不驗身分就能打，回應裡若有版本、指紋、編號，等於幫攻擊者對 T1 做前置偵察。沒看。
- **agent 端的 probe 限量**（D5）：雲端限 32 台，agent 端沒再量；雲端被繞過時 agent 是最後一道。
- **8443 暴露面**（D6）：客戶實際怎麼開防火牆沒人管得到，但安裝文件可以寫清楚。
- **`AGENT_AUTH_MODE` 的啟動期檢查**（D7）：正式設定類沒擋 `none`。

---

*依據：STRIDE 六頁信任邊界連線標記（CM-2403／2404 驗收後版本）、agent repo `core/data_plane_server.py`／`core/data_plane_auth.py`／`core/agent_auth.py`／`api/detection/routes/detection_route.py`／`api/blob/__init__.py`／`deploy/README.md`／`deploy/docker-compose.yml`、套件 `jedi_remote_agent/common/agent_auth/tls.py`／`jwt_util.py`／`settings.py`、`jedi_detection/infra/detection_tools/connector/agent_probe_client.py`、主專案 `config/config.py`／`scripts/installer/install.sh`／`scripts/installer/guidantai`、DFD Level 0。*
