你花了一整周把 27B 模型跑上自己的 GPU,vLLM 配好了、ROCm 裝好了、Docker 容器跑起來了。然後你把它接到 LAN 上,讓手機和筆電都能連。
問題是:你的「本地」推論伺服器,現在跟一扇沒鎖的門沒有兩樣。
為什麼這跟你有關
LLM 推論伺服器(vLLM、Ollama、LMDeploy、TGI)本質上是一台無認證的 HTTP 代理,帶著 GPU 上跑的模型和它所在網路的完整可視性。如果它沒有認證機制、又暴露在能到達的網路上,那它就能被當作一個「從裡面打出去」的跳板。
2026 年 4 月 22 日,LMDeploy 的 vision-language 圖片載入函式被證實有 SSRF 漏洞(CVE-2026-33626,CVSS 7.5)。從 GitHub advisory 公開到第一筆確認的野外利用,只用了 12 小時 31 分。(source: Sysdig TRT, CSA Research Note)
攻擊鏈:8 分鐘的偵察
Sysdig 的 honeypot 網絡記錄下了完整的攻擊過程。攻擊者 IP 定位在九龍灣(經代理可能非真實位置),整段 session 只有 8 分鐘,明顯是自動化腳本:
- IMDS 探測 — 對
169.254.169.254(AWS Instance Metadata Service)發image_url請求,試圖抓取 EC2 實例的臨時 IAM 憑證 - 端口列舉 — 掃 Redis (6379) 和 MySQL (3306) 標準端口
- 管理介面發現 — 找到一個從外網不可達、但推論伺服器能看到的 HTTP 管理介面
- DNS 外洩 — 透過攻擊者控制的 DNS 名稱伺服器回傳內部主機名和 IP
關鍵機制:LMDeploy 的 load_image() 函式(lmdeploy/vl/utils.py)接受 client 傳來的 image_url 參數,直接用 HTTP 去抓取這張圖——但沒有驗證目標 URL 是不是內網位址。攻擊者只要把 image_url 設成 http://169.254.169.254/latest/meta-data/iam/security-credentials/,推論伺服器就會幫你去打那個位址。(source: GitLab Advisory)
修補版本 v0.12.3 加入了 RFC1918 私網位址、loopback、link-local 的封鎖清單。
這不是孤例
| CVE | 元件 | 類型 | 影響 | 修補版本 |
|---|---|---|---|---|
| CVE-2024-37032 | Ollama | Path Traversal → RCE | 任意檔案覆寫 → 遠端程式執行 | v0.1.34 (2024) |
| CVE-2025-9141 | vLLM | 不安全反序列化 (eval) | 工具呼叫參數直接 eval() → RCE |
v0.10.1.1 (2025) |
| CVE-2026-33626 | LMDeploy | SSRF | 內部網路偵察、IAM 憑證擷取 | v0.12.3 (2026-04) |
(source: Wiz Research, GitHub GHSA-79j6-g2m3-jgfw, GitLab Advisory)
共同模式:預設無認證 + 可從網路到達 + 有內部網路可視性。
CVE-2025-9141 特別值得注意:vLLM 的 Qwen3-Coder tool parser 在解析工具呼叫參數時,對不認識的資料型別直接調用 Python 的 eval()。任何能讓模型把任意字串塞進 tool call 參數的輸入,都能在 GPU host 上執行。CVSS 向量:AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H。(source: GitHub Advisory)
你的 homelab 怎麼防
1. 永遠不要讓推論端口直接對外
# vLLM 預設只綁 127.0.0.1,這很好
docker run -d -p 127.0.0.1:8000:8080 vllm/vllm-openai ...
# 需要多機存取?用 reverse proxy + 認證
# Caddy 範例:
# Caddyfile
inference.yourdomain.com {
reverse_proxy 127.0.0.1:8000
headers {
# 加上 Bearer token 檢查(用 reverse_proxy 的 request_header)
}
}
或者更簡單:SSH 隧道 / WireGuard 把流量封進 LAN,不開任何 inbound port。
2. 加認證層
vLLM 0.24+ 支援 --api-key:
docker run -d -p 127.0.0.1:8000:8080 \
-e VLLM_API_KEY=sk-your-secret \
vllm/vllm-openai serve ...
Ollama 本身不支援認證,必須靠 reverse proxy(Caddy、Nginx、Authelia)擋在前面。
3. 網路分區
推論容器不該跟你的資料庫、管理介面在同一個 flat subnet。Docker 自訂 bridge network + firewall rule:
# 只有反向代理能到達推論容器
iptables -A DOCKER-USER -i eth0 -p tcp --dport 8000 -j DROP
iptables -A DOCKER-USER -i docker0 -p tcp --dport 8000 -j ACCEPT
4. 追蹤 CVE 並設定 patch SLA
12 小時的利用窗口意味著「下週再更新」已經不夠。實務做法:
- 訂閱你用的推論引擎的 GitHub Release / Security Advisory
- 容器映像定期 rebuild(
docker pull+docker compose up -d) - 如果你的推論伺服器是關鍵路徑(agent 的 brain),設定 24 小時內的 patch SLA
5. 用 Trivy 掃映像
我現在每週跑一次 Trivy 掃容器映像(走 systemd timer),有 CRITICAL/HIGH finding 就進報告:
trivy image --severity HIGH,CRITICAL --image-src docker vllm/vllm-openai:latest
If You're Stuck
connection refused連到自己的推論伺服器 → 檢查是不是綁了127.0.0.1但你從另一台機器連。改成0.0.0.0或加--network host,但記得加認證- Docker 容器內連不到宿主機 → 用
host.docker.internal(macOS/Windows)或172.17.0.1(Linux),或加--add-host=host.docker.internal:host-gateway - vLLM 啟動後 API 回 401 → 檢查
VLLM_API_KEYenv var 是否傳進容器,client 端的Authorization: Bearerheader 是否對得上 - Ollama 暴露後被掃到 → 先用
curl http://target:11434/api/tags確認 model list 是否洩漏,然後加 reverse proxy 或收回OLLAMA_HOST - CVE-2025-9141 影響你嗎 →
pip show vllm | grep Version看是否< 0.10.1.1,且啟動參數有--tool-call-parser qwen3_coder。兩者都符合就要升級
