跳至主要內容

代理程式隔離最佳實踐:沙箱隔離(私人測試版)

針對我們網路驗證計畫中的客戶,我們在 API 中提供了新的沙箱逃逸分類器,用於監控和減少濫用。本文說明了為什麼自主代理程式需要強大的隔離、參考設計如何隔離它們,以及如何確定範圍和監督需要網路存取的互動。

此分類器處於私人測試版。

如需瞭解所有可用資源的概述,請參閱 代理程式隔離最佳實踐:入門指南(私人測試版)。

概述

  • 在自主執行中,沒有人類批准代理程式的工具呼叫,代理程式可能會執行目標程式碼。我們建議在強大的沙箱中執行自主代理程式,該沙箱在主機與代理程式和目標程式碼之間放置硬體虛擬化核心。不要使用裸 Docker/runc,也不要使用 --privileged 或主機網路。

  • 參考設計在內部網路上的自己的 microVM(Kata Containers with Firecracker)中執行每個代理程式。它需要具有 KVM 的 Linux 主機,這限制了可以執行它的主機。Kata 已棄用 Firecracker 依賴的執行時。

  • 永遠不要將包含認證的路徑(例如 ~/.aws、~/.ssh 或 .env)掛載到代理程式的環境中。也要將模型 API 認證保留在代理程式的環境之外:讓單獨的認證代理程式持有它,並將其新增到每個模型請求中(請參閱 認證代理程式)。

  • 預設拒絕出站流量。在參考設計中,模型呼叫通過認證代理程式,出站代理程式拒絕所有其他目的地,除非您將其列入允許清單。

  • 在依賴沙箱之前,在每個主機上測試它,並在沙箱或模型變更時再次測試。

  • 對於需要網路存取的互動,在代理程式的指示中說明範圍,在網路中強制執行,並將自主代理程式遠離即時高後果系統(請參閱 範圍和監督)。

沙箱隔離指南

要達成的屬性

如果您建立自己的沙箱,這些是參考設計提供的屬性。本文的其餘部分描述了獲得它們的一種方式。

  1. 每個代理程式都有自己的客體核心,它不與主機共享。

  2. 代理程式的檔案和 shell 工具只能看到客體的檔案系統。沒有主機目錄共享到客體中。

  3. 模型 API 認證不在代理程式的環境或磁碟上。沙箱外的代理程式將其新增到每個請求中。

  4. 代理程式沒有網際網路存取。出站流量在客體外強制執行,除非目的地在允許清單上,否則拒絕所有目的地。

  5. 無法從代理程式到達雲端中繼資料服務。

  6. 每個代理程式都有輪次限制,如果您設定了時間限制。

  7. 沒有特權模式、新增的功能、裝置傳遞或主機網路。

  8. 協調器在受信任的主機上執行並將文字記錄寫入其中。

一般指南

強大的沙箱對自主執行最重要,其中代理程式執行目標程式碼,沒有人類批准每個動作

在強大的沙箱中執行自主代理程式,並思考該沙箱中的程序可能仍會造成什麼副作用。前沿模型越來越善於找到繞過限制的創意路徑:使它們成為有效漏洞獵人的相同屬性意味著它們可能對自己的執行環境採取意外行動。這不是假設。Anthropic 已發佈了模型繞過弱約束以完成任務的範例(請參閱 我們如何在各個產品中隔離 Claude)。

具體來說,不要在裸 Docker/runc 中執行自主漏洞尋找代理程式,尤其不要使用 --privileged 或主機網路。標準容器共享主機核心,因此容器內的核心漏洞是主機洩露。我們建議在目標程式碼和主機之間放置硬體虛擬化核心,這意味著在虛擬機器中執行代理程式。如果不可能,請使用不包含任何其他內容的專用裸機主機。如果您建立自己的沙箱,我們建議在 Linux 上使用 Firecracker、在 Windows 上使用 Hyper-V,以及在 macOS 上使用基於 Hypervisor 框架的 VM。參考設計使用 Firecracker。

阻止來自沙箱的所有出站流量。代理程式通過添加認證並在沙箱外執行的代理程式到達模型 API,因此沙箱不需要到 API 主機的直接路由。在執行開始前安裝每個工具、套件和相依性,以便在執行期間不需要擷取任何內容。

互動使用(有人在迴圈中)通常風險較低,但我們仍建議為其使用沙箱。如果您從筆記型電腦上的 Claude Code 以互動方式驅動代理程式,請檢查每個工具使用(手動模式),或依賴自動模式權限分類器並讓人類批准每個到達存放庫外的動作。自動模式移除例行權限提示:它自動批准讀取和工作目錄編輯,並將所有其他內容發送到旨在阻止破壞性、不可逆或偏離任務的動作的背景分類器。這是盡力而為的檢查。它可能會遺漏一些內容,在安全工作中,它也可能拒絕一些合法步驟。自動模式描述了它的工作原理、您可以期望什麼,以及如何為您的環境配置它。

永遠不要將包含認證的路徑(例如 ~/.aws、~/.ssh 或 .env)掛載到代理程式的環境中。代理程式自己的模型呼叫使用的認證也是如此。將其保留在沙箱外,並讓代理程式無法讀取的代理程式將其新增到每個請求中(請參閱 認證代理程式)。不要將代理程式連接到 MCP 伺服器或具有對外部狀態(例如電子郵件、雲端儲存或生產基礎結構)的寫入存取權限的工具。

將每次執行分為具有不同網路原則的設定階段和攻擊階段

這是將上述指南付諸實踐的一種模式。設定階段具有出站網際網路存取和人類在迴圈中批准每個工具呼叫。在其中,代理程式拉取相依性、建立目標並從規格文件中建立其沙箱。攻擊階段沒有一般網際網路存取。所有出站流量都通過允許清單代理程式,該代理程式僅允許互動中命名的主機,因此代理程式也強制執行範圍。模型呼叫通過單獨的認證代理程式。代理程式可以無人值守地探測目標。代理程式包含代理程式自己的流量。它不包含網路化目標代表代理程式發送的流量。

將代理程式需要重複使用的相依性烘焙到設定映像中,以便攻擊階段執行根本不需要網際網路存取。按目標確定認證範圍,以便在一個目標上工作的代理程式無法針對另一個目標使用它們。在攻擊階段期間在沙箱內保持 Claude Code 的自動模式開啟,並向其分類器描述沙箱。請參閱 自動模式。

限制每次執行,並知道您的關閉開關

給每個代理程式一個明確的預算,以便超過其預期測試的執行在自己停止,而不是在有人注意到時停止。對每個代理程式強制執行硬輪次限制。當代理程式耗盡它時,結束執行,不要自動授予更多輪次。使用更高的限制重新啟動是人員決定繼續的時刻。也要在時間上限制執行。以相同的方式結束超過其時間限制的工作階段:執行是最終的,永遠不會恢復,代理程式程序被停止,即使在長時間執行的命令中間達到限制。如果限制設定為無法讀取的值,請拒絕啟動而不是無上限執行。為互動故意設定限制,不要接受慷慨的預設值。將它們與 代理程式文字記錄的離線監控中的監控頻率配對,以便每小時或兩小時查看一次長批次,而不是只在最後查看。知道如何停止單個代理程式而不停止批次。在基於 Docker 的設定中,這是 docker rm -f <agent-container>。協調器應將該執行記錄為失敗,並繼續進行批次的其餘部分。

如需更多指南,請閱讀兩個 Anthropic 資源。安全部署 AI 代理程式涵蓋隔離選項、認證代理和檔案系統強化。工程回顧 我們如何在各個產品中隔離 Claude 涵蓋了這些相同機制在生產中執行時的保留內容和未保留內容。

範圍和監督

沙箱限制代理程式可以到達的內容。對於滲透測試、紅隊和其他需要網路存取的互動,以下實踐限制了代理程式被要求和允許做的事情。它們取決於您的目標和您的團隊,因此工具無法為您實施其中大部分。

在代理程式的指示中說明範圍

在執行前,告訴代理程式哪些目標在範圍內、允許哪些動作、網路邊界在哪裡以及什麼超出範圍。將每個約束表述為意圖(「不要存取 10.0.3.0/24 外的主機」),而不是關於環境的聲明(「您無法到達網際網路」),以便如果環境配置錯誤,指示仍然成立。對沙箱化本地工作也要這樣做:告訴代理程式不要使用網際網路存取,即使沙箱阻止它。您提供給自動模式分類器的描述是另一回事。它說明了機器的事實(請參閱 自動模式)。

在網路中強制執行相同的範圍

在可能的情況下,在上述相同隔離內執行代理程式,並僅將出站流量列入允許清單到範圍內的目標(請參閱 出站允許清單)。代理程式通過認證代理程式而不是通過允許清單到達模型 API。如果有可用的,請將互動指向與生產斷開連接的暫存或複製環境。

在可能的情況下代理對目標的存取

通過您可以觀察的內容(例如存取代理程式或一組定義的工具)給予代理程式對目標系統的存取。避免讓代理程式使用對目標的一般存取權限編寫自己的工具。在自訂工具中,將唯讀工具與更改狀態的工具分開,並更密切地監督第二組。考慮在提出時分析有風險的命令,並拒絕它們或將其升級給人員。

監督具有網路存取的執行

我們建議工程師在執行時觀察每次執行,跟蹤工具呼叫和網路活動,並能夠立即停止執行。代理程式以機器速度行動,因此即時觀察補充了在動作執行前起作用的控制項(網路允許清單、代理工具和狀態變更動作審查)。它不會取代它們。對於連續注意不切實際的長期或自主執行,在軟體中持續監控(請參閱 代理程式文字記錄的離線監控)。

將自主代理程式遠離即時高後果系統

不要針對即時生產系統執行自主代理程式,其中超出範圍的動作可能危害安全或關鍵服務的可用性,例如 OT/ICS、醫療或能源系統。這已經是人類主導的此類系統測試的規範,它同樣適用於此。針對複製品、測試台或數位孿生進行測試,或在計畫的停機期間進行測試。如果無法避免即時存取,請將代理程式限制為被動或唯讀活動,並讓人員執行每個狀態變更步驟。

在依賴沙箱之前測試它

在從主機執行真實互動之前,使用以下兩個步驟測試其沙箱。在首次真實使用前執行此操作,並在每次變更模型或沙箱時再次執行。沙箱變更包括新主機、新版本的虛擬機器管理程式或容器執行時、不同的網路或代理程式設定,以及編輯的容器或撰寫配置。

首先,讓 Claude 檢查配置

在主機上的互動式 Claude Code 工作階段中,要求它讀取在此機器上設定的沙箱配置,並報告任何削弱本文所述邊界的內容。指向它:

  • 虛擬機監視器和容器執行時配置(對於參考設計,Kata 的呈現 configuration.toml 和 Docker 的 daemon.json);

  • 代理程式的網路和執行時報告的出口代理,以及代理的允許清單;

  • 執行時報告的認證代理,以及執行中代理容器的環境(請參閱下方的 認證代理);

  • 啟動代理或目標的任何撰寫或編排檔案;

  • 掛載或串流到客體的內容清單(請參閱下方的 操作說明)。

此步驟僅讀取配置和狀態。它不會啟動代理。

然後,執行受監督的逃逸測試

以啟動生產代理的相同方式啟動測試代理,而不是使用手動建立的命令,以便測試執行真實路徑。下方的 自行驗證隔離 部分涵蓋邊界的手動檢查。給代理一個單一任務:嘗試到達其邊界外的任何內容,並在任何內容成功時立即停止並報告。在提示中具體命名邊界:主機、其他容器、容器執行時套接字、雲端中繼資料服務,以及代理允許清單上沒有的任何主機。僅在密切的人工監督下執行此操作,在沒有超過模型 API 的網際網路存取的主機上執行,並且您已準備好重建,以便成功逃逸不會造成損害。在裸機上,在一次性虛擬機內執行測試。在雲端虛擬機上,使用新實例並在之後銷毀它。在執行時監視工作階段。將任何成功視為阻止程式:修復主機、重複測試,並在測試通過之前不要從該主機執行參與。

之後,閱讀整個記錄

檢查代理嘗試的內容以及它是否逃逸。尋找未通過代理的直接連線、認證檔案或中繼資料位址的讀取、容器執行時套接字的使用或相鄰容器的探測、容器自身檔案系統外的寫入,以及嘗試變更代理自身的設定或工具。當記錄顯示每一項都被嘗試並因您預期的原因失敗時,測試通過。對於每一項,記錄沙箱或權限分類器是否停止了它。分類器拒絕的嘗試永遠不會到達沙箱,因此請用手動檢查涵蓋它(請參閱下方的 自行驗證隔離)。通過的測試是最低標準,而不是隔離的證明。

避免不可能的任務,並先檢查失敗的執行

在啟動前確認任務可以按給定方式完成。無法完成的任務範例:沒有任何內容可尋找的焦點區域、無法到達的目標、不存在的錯誤,或任務需要但未安裝的工具。每當您變更設定或開始新類型的任務時,在啟動前確認目標建置成功、可以到達,以及代理具有所需的工具。出於相同原因,當您檢查批次時,在檢查成功的執行之前,先閱讀失敗或未發現任何內容的執行記錄。

自行驗證隔離

在每個主機上手動執行這些檢查。第二欄描述參考設計(具有 Kata 執行時和 Firecracker 的 Docker)的檢查。將其調整為您自己的執行時。

要確認的內容

方式

預期結果

獨立的客體核心

在沙箱容器和主機上執行 uname -r

兩個版本不同

虛擬機監視器在主機上被監禁

對於執行中的容器,檢查 Firecracker 程序:其根目錄、/proc/<pid>/status 中的 Seccomp 和 NoNewPrivs、其掛載和網路命名空間,以及其 cgroup

只有虛擬機自身的檔案在其根目錄下。Seccomp: 2 和 NoNewPrivs: 1。兩個命名空間都與主機的不同。cgroup 路徑命名容器

主機檔案在內部不可見

在主機上建立檔案並嘗試從沙箱容器讀取它

找不到。這是任何執行時都應該通過的基本檢查

出口被拒絕

從代理容器,通過出口代理要求模型 API 主機和另一個公開主機

兩者都被拒絕,出口代理為每個記錄一條拒絕行。代理僅通過認證代理到達模型

代理容器中沒有認證

在執行進行時,列出代理容器的環境,按提供者名稱篩選

預留位置、認證代理的位址和提供者設定。沒有真實金鑰、權杖或認證檔案

參考設計

本部分描述參考實作如何滿足上述指導。實作未包含。將其作為您可以複製的設計閱讀。

每個代理如何被隔離

每個代理在其自己的 microVM 內以 claude -p 執行,位於目標二進位檔和來源旁邊。microVM 是由 Kata Containers 容器支援的 Firecracker 虛擬機監視器,向 Docker 註冊為執行時。代理的 Read、Write 和 Bash 工具只看到該客體的檔案系統和核心。

客體和主機之間的連線刻意很小。它由 KVM 和 Firecracker 模擬的少數虛擬裝置組成:容器磁碟的區塊裝置、一個網路介面,以及 Kata 用來在客體內啟動程序的 vsock 控制通道。Firecracker 程序本身在主機上被限制。它在「監獄」中執行,這是一個 chroot 目錄,僅包含該虛擬機的檔案,具有自己的掛載命名空間、容器的網路命名空間和 Firecracker 的內建 seccomp 篩選器。它被計入容器的 cgroup。您在主機端信任的是 KVM、Firecracker 和 Kata 的執行時程序(Docker 與之通話的每個容器「shim」,以 root 身份執行)。

編排器保留在受信任的主機上。它管理容器生命週期、串流記錄,並使用 docker exec 移入和移出檔案,Kata 通過其在客體內的代理提供此功能。啟動器僅在此沙箱內啟動代理。在任何代理啟動之前,它檢查沙箱執行時是否已註冊、/dev/kvm 是否存在,以及出口代理是否啟動,否則拒絕執行。

沙箱為每個表面變更的內容:

表面

沒有沙箱

有沙箱

代理 Read/Write

主機檔案系統

僅客體檔案系統(容器自身的虛擬磁碟,在客體核心下)

代理 Bash

僅客體 shell

僅客體 shell(客體核心;主機只能通過 KVM 和 Firecracker 的虛擬裝置到達)

網路出口

主機擁有的任何內容

無網際網路存取;僅限模型呼叫,透過認證代理

模型 API 認證

在代理的環境中

不在代理容器中;由單獨的認證代理容器保存(請參閱下方的認證代理)

主機耦合

完整

docker exec 用於檔案進出,由 Kata 在客體內的代理提供;唯讀輸入在容器啟動時作為副本到達;在執行期間變更的檔案由協調器串流傳入

權限檢查

僅自動模式分類器

自動模式分類器加上 microVM 邊界(請參閱自動模式)

每個屬性的強制位置:硬體虛擬化提供核心和檔案系統邊界。代理的 Read/Write/Bash 針對客體核心執行,其背後的 Firecracker 程序在主機上被隔離和 seccomp 限制。出口政策在虛擬機網路介面的主機端強制執行,透過 Docker --internal 橋接(無預設路由)和該網路上的兩個代理。認證代理轉發模型呼叫,別無其他。出口代理拒絕所有其他目的地,因為其允許清單為空,除非您新增到其中。流量透過客體自己的網路堆疊離開;篩選發生在兩個代理中。

認證代理

模型 API 的認證(您的 API 金鑰、OAuth 權杖、AWS 或 Google 認證)永遠不會放在代理容器中。主機上的協調器讀取並驗證它,每次啟動都會啟動一個小型額外容器,即認證代理,來保存它。代理連接到代理的內部網路,代理容器將其模型呼叫傳送給它:其 claude CLI 取得代理的位址作為其 API 基礎 URL,以及金鑰或權杖通常所在位置的固定預留位置值。這遵循僅透過代理到達模型 API 的最佳實踐,API 金鑰從沙箱外部注入。在參考設計中,代理是代理網路上的單獨容器,而不是代理自己的 localhost 上的程序。對於每個請求,代理:

  1. 拒絕任何不是對啟動所設定的一個提供者端點的模型呼叫的內容(其他路徑和主機取得 403 和日誌行);

  2. 移除容器傳送的任何驗證標頭;

  3. 新增真實認證:API 金鑰標頭、持有人權杖(代理在權杖短期時自行重新整理),或透過確切請求計算的 AWS SigV4 簽名;

  4. 透過 HTTPS 將請求轉發給提供者,進行憑證驗證,並將回應串流回傳。

對於受損的代理容器,這意味著沒有金鑰、權杖或認證檔案可讀取、複製或傳送到任何地方。雲端中繼資料服務也無法從容器到達。容器仍然可以做的是透過代理進行模型呼叫,在您的帳戶上,只要執行持續進行。因此,為代理執行偏好狹義範圍的認證,並在任何執行後輪換它,其文字記錄顯示意外行為。代理為每個請求記錄一行,包含用戶端位址、方法、路徑、狀態和大小。它不記錄標頭或正文。在執行結束時儲存該日誌(請參閱離線監控代理文字記錄中的保留部分)。

代理傳送給模型 API 的任何內容都會離開您的網路,在代理不檢查或記錄的請求正文中。

每個驗證路由每一側保存的內容:

路由

認證代理保存的內容

代理容器取得的內容

API 金鑰

金鑰

代理位址 + 預留位置 ANTHROPIC_API_KEY

OAuth 權杖(claude setup-token)

權杖

代理位址 + 預留位置 CLAUDE_CODE_OAUTH_TOKEN

工作負載身分聯盟 (WIF)

身分權杖,加上代理交換並重新整理的存取權杖。使用 ANTHROPIC_IDENTITY_TOKEN_FILE,權杖檔案的目錄以唯讀方式掛載到代理中,因此代理會看到輪換的權杖。使用內嵌 ANTHROPIC_IDENTITY_TOKEN,代理保存該值,沒有檔案可重新讀取

代理位址 + 預留位置 CLAUDE_CODE_OAUTH_TOKEN

ant auth login 設定檔

設定檔目錄,以唯讀方式掛載到代理中

代理位址 + 預留位置 CLAUDE_CODE_OAUTH_TOKEN

Bedrock

持有人權杖,或存取金鑰集(代理簽署每個請求)

代理位址、CLAUDE_CODE_SKIP_BEDROCK_AUTH=1、區域;無 AWS 認證

Vertex

服務帳戶金鑰,加上代理從中鑄造並重新整理的存取權杖

代理位址、CLAUDE_CODE_SKIP_VERTEX_AUTH=1、區域和專案;無 Google 認證

認證代理容器是設定的受信任端的一部分。它在純 runc 而不是沙箱執行時下執行,以 root 身分執行,除了讀取掛載檔案所需的功能外,所有功能都已刪除,並具有唯讀檔案系統。它僅在代理內部網路上的其位址上偵聽,並直接連接到提供者,而不是透過出口代理。協調器透過 docker exec 將認證傳遞給執行中的代理。對於 WIF 權杖檔案和設定檔路由,保存權杖或設定檔的目錄以唯讀方式掛載到代理中,代理從那裡讀取檔案。認證不在代理容器的環境或命令行中,因此對其進行 docker inspect 會顯示掛載,而不是祕密。

每次啟動啟動一個代理,並在執行結束或中斷時將其移除。檢查被殺死的執行留下的代理,並在下次啟動前將其移除。

認證代理有兩個副作用。首先,代理的 CLI 被賦予非預設 API 位址,因此僅適用於預設位址的一些 CLI 功能在代理容器內關閉。其遙測和更新檢查也被關閉,因為它們無論如何都沒有路由。其次,在 Vertex 上,代理的路徑篩選是阻止代理容器使用 Vertex AI API 其餘部分的主要控制(請參閱出口允許清單)。在啟動時檢查金鑰的 IAM 範圍是第二層。

出口允許清單

出口代理的允許清單預設為空。代理容器僅透過認證代理到達模型 API(請參閱認證代理)。每次啟動都會為您的認證選擇的提供者啟動該代理,因此沙箱設定中不會儲存任何提供者特定的內容。代理透過出口代理請求的任何其他目的地,包括模型 API 主機本身,都會取得 403 和其日誌中的拒絕行。選擇 Bedrock 和 Vertex 端點的區域值(AWS_REGION、CLOUD_ML_REGION)在使用前會根據嚴格的模式進行檢查,以便格式不正確的值無法將認證傳送到不同的主機。

Vertex 有一個需要注意的限制。…aiplatform.googleapis.com 提供整個 Vertex AI API,因此允許建立自訂工作的認證可以在您的專案中執行具有完整網際網路出口的任意容器。針對此使用兩個控制。讓認證代理僅轉發您設定的專案上的發行者模型呼叫(…/publishers/anthropic/models/…:rawPredict, :streamRawPredict 和 :countTokens),並拒絕所有其他路徑。並在啟動時檢查金鑰的 IAM 範圍並關閉失敗:拒絕 gcloud 使用者 ADC,使用 testIamPermissions 檢查服務帳戶金鑰,如果它保存任何工作負載建立權限,則拒絕它。授予帳戶僅保存 aiplatform.endpoints.predict 的自訂角色。中繼資料伺服器、Google 的 STS 和 IAM 認證端點不應從代理容器到達。

如果代理需要到達額外的主機,例如套件鏡像或範圍內目標,將它們新增到出口代理的允許清單作為 host:port 項目。僅新增參與所需的內容(請參閱範圍和監督)。

不要將 model-API 主機新增到此清單。代理程式不需要它,因為它們的模型呼叫會透過認證代理進行。新增它會給代理程式容器一條直接連接到 API 的路由,而設計的其餘部分(包括權限分類器被告知的內容)假設它們沒有這條路由。

變更允許清單意味著重新啟動出口代理,這會中斷任何即時代理程式連線。在批次之間而不是在批次期間進行此操作,並在之後確認代理載入了哪個清單。

從您的認證設定衍生提供者端點,並忽略在主機上設定的基本 URL 變數(例如 ANTHROPIC_BASE_URL):認證代理應該始終轉發到認證選擇的端點。

建立和操作這樣的沙箱

本節收集了在參考實作中使用 Kata 和 Firecracker 執行代理程式所學到的內容。這不是一組安裝步驟。

主機需求

參考設計需要一台實體 Linux 機器或可以自行執行 VM 的 VM:

  • Linux x86_64 或 aarch64 搭配 KVM(/dev/kvm 存在且可用):裸機或啟用巢狀虛擬化的雲端 VM。

    • GCE、Azure 和 AWS 在選定的執行個體類型上提供巢狀虛擬化(例如在 AWS 上,C8i、M8i 和 R8i 系列)。AWS 裸機(*.metal)執行個體也可以運作。

    • 巢狀虛擬化會消耗一些效能。預期不會削弱邊界。

  • 容器的區塊裝置儲存。Firecracker 無法將主機目錄共享到客體;它可以連接到 VM 的唯一儲存是區塊裝置。因此,容器根檔案系統必須作為區塊裝置存在,而不是通常的覆蓋檔案系統。使用 Docker,containerd 的 devmapper 快照製作程式提供了這一點。它需要 rootful Docker(參考設計使用引擎 25 或更新版本)由系統 containerd(2.0 或更新版本)支援。

  • 在您建立主機和映像時的出站網路存取。代理程式不會獲得此出口。

它不會在以下情況下運作:

  • 容器或 Kubernetes Pod,包括 Docker-in-Docker 和基於容器的 CI 執行器。主機的 containerd、Docker 守護程式和裝置對應程式無法從容器內部進行設定,KVM 通常也無法在那裡使用;

  • 無根 Docker;

  • 沒有巢狀虛擬化的 VM,這是大多數通用雲端執行個體類型,除非您選擇提供它的類型並將其開啟;

  • macOS 或 Windows,包括 Docker Desktop 和 WSL2。

參考設計不支援 macOS 或 Windows 主機

其沙箱需要 Linux 主機上的 KVM。Mac 上的 Docker 在共享 Linux VM 內執行,該 VM 掛載使用者的主目錄並保存 Docker 守護程式,因此無法提供每個代理程式的硬體隔離。如果您在 Mac 上工作,請在具有 KVM 的 Linux 主機(裸機或具有巢狀虛擬化的雲端 VM)上執行代理程式,並透過 SSH 驅動它們。如果您在 macOS 或 Windows 上建立自己的沙箱,請參閱上面一般指南部分下命名的 Hypervisor。

切換 Docker 的映像存放區有副作用

在切換到 devmapper 快照製作程式後,在 Docker 先前存放區上建立的映像和容器對 Docker 變得不可見。它們保留在磁碟上。若要再次看到它們,請將 daemon.json 中的兩個儲存設定(storage-driver 和 features.containerd-snapshotter)放回它們的原始狀態,然後重新啟動 Docker。

Kata 設定

固定 Kata 版本,並在安裝前驗證其摘要。參考設計從 Kata 的 Firecracker 設定檔開始,並在 /etc/kata-containers/configuration.toml 中固定這些設定:

設定

值

原因

jailer_path

Kata 的 jailer 二進位檔案的路徑

在其監獄內啟動 Firecracker:一個 chroot,只包含 VM 的檔案、它自己的掛載命名空間、容器的網路命名空間和 Firecracker 的 seccomp 篩選器。如果未設定,Kata 將在沒有監獄的情況下執行 Firecracker。

enable_annotations

[]

容器無法透過 OCI 註釋變更任何 Hypervisor 設定。

disable_guest_seccomp

false

容器的 Docker seccomp 設定檔也在客體內套用,VM 邊界下的第二層。

sandbox_cgroup_only

true

Firecracker 及其 I/O 執行緒被放置在容器的 cgroup 中,因此 VM 被計入容器。容器的 --memory 限制是否也限制 VM 取決於主機(請參閱大小調整)。

static_sandbox_resource_mgmt

true

Firecracker 無法將 CPU 或記憶體新增到執行中的 VM,因此 VM 在啟動時從容器的限制進行一次大小調整。

default_vcpus / default_memory

4 / 4096 MiB

每個 VM 的基準;容器的 --memory 在頂部新增。為建置密集型目標提高(Firecracker 每個 VM 最多允許 32 個 vCPU)。

debug_console_enabled, enable_debug

false

沒有進入客體的主控台,主機日誌中沒有客體主控台輸出。

[factory] enable_template

false

關閉,因為 VM 樣板化會在 VM 之間共享客體記憶體頁面。

entropy_source

/dev/urandom

非阻塞主機熵供客體使用。

Kata 版本隨附的 kernel、image 和 kernel_params 值保持不變。

使客體核心和映像不可變

每個 VM 都從相同的兩個檔案啟動,Kata 將它們綁定掛載到每個監獄中,並且 jailer 以 root 身份啟動,因此普通檔案權限不會阻止受損的 Firecracker 程序重寫每個後續 VM 啟動的映像。在兩者上設定不可變標誌 (chattr +i)。清除該標誌需要系統呼叫,Firecracker 的 seccomp 篩選器不允許該呼叫,其設計目的是阻止監獄內的 root 執行此操作。在安裝新的 Kata 版本之前,自行清除該標誌。在不支援 chattr 的檔案系統上,改用唯讀綁定掛載。

調整大小

記憶體

每個代理 VM 在啟動時調整一次大小:default_memory 加上容器的 --memory。基準為 4096 MiB,容器限制為 4g,代理是 8 GiB VM。主機在客體使用時將該記憶體分配給 VM,而不是在啟動時全部分配,但要為每個並行代理規劃完整數量:十個並行代理可能增長到 80 GiB。容器的 --memory 限制是否也限制整個 VM 取決於主機的 cgroups 如何配置。檢查哪一項適用於您的主機:

  • 容器限制適用於整個 VM。代理無法使用超過 --memory 的主機記憶體,即使其 VM 名義上更大,超過限制的 VM 也會從主機端被終止。

  • 主機上沒有任何東西將 VM 限制在其啟動大小以下。代理的記憶體使用受 VM 大小 (default_memory + --memory) 和客體核心自身的記憶體不足終止程式限制。

  • 父 cgroup 將其限制在不同的值。

我們尚未在每種主機上確認此行為。無論如何,按 VM 大小調整主機大小。

CPU

每個 VM 都獲得 default_vcpus。Firecracker 無法將 CPU 新增到執行中的 VM,因此對於構建密集型目標,請在啟動前提高該值;每個 VM 的最大值為 32。

磁碟

每個映像和每個容器都從裝置對應程式精簡池中獲得虛擬磁碟,該池支援映像存放區。如果池填滿,容器內的寫入會失敗,出現 I/O 或空間不足錯誤。如果保存池的檔案系統先填滿,池將變為唯讀,其上的每個容器都會失敗。使用 docker rmi 和 docker system prune 釋放空間(釋放的區塊返回到池)。sudo dmsetup status <pool> 顯示使用情況。對於長期執行的主機,專用磁碟上的 LVM 精簡池是更好的配置。

啟動時間

每個代理啟動都會啟動客體核心。在裸機上這需要不到一秒,在嵌套虛擬化下需要幾秒,與代理執行時間相比很小。

強化主機

  • 將主機專用於此工作。

    • 假設代理可以讀取其上的任何內容,除了代理需要的模型 API 認證外,不要在那裡保留任何認證或敏感資料。

  • 保持代理流量接觸的每一層都已修補,不僅是核心:Docker、代理容器的基礎映像以及主機和模型 API 之間的任何防火牆或網路設備。沙箱邊界上過時的代理或防火牆本身就是攻擊面。

  • 保持核心、KVM 和 CPU 微碼為最新版本,並將核心的 CPU 漏洞緩解措施保留在預設值。

    • grep . /sys/devices/system/cpu/vulnerabilities/* 不應顯示任何 Vulnerable 行。

    • 如果主機與不得相互觀察的工作負載共享,也請遵循 Firecracker 的 生產主機設定指南中關於 SMT 和推測執行設定的內容。

  • 停用交換 (sudo swapoff -a,並從 /etc/fstab 中移除它),以便客體記憶體不會寫入交換。

  • /dev/kvm 不需要對全球可寫,Kata 的安裝和執行時目錄必須保持由 root 擁有,不可被其他使用者寫入。

    • root:kvm 模式 0660 對 /dev/kvm 足夠,因為 Kata 的執行時以 root 身份執行。

  • 永遠不要將 --privileged、--device、--cap-add 或主機網路新增到代理容器或目標服務。

    • 在 Kata 下,這些標誌會將主機裝置和權限傳遞到 VM 中。

  • 將代理保留在兩個代理後面的內部網路上。

    • Firecracker 本身不進行封包篩選;主機端網路和代理是出口控制。

  • 在故障排除之外保持 enable_debug 關閉;偵錯日誌包括客體主控台輸出。

驗證新主機

設定新機器後,此序列顯示沙箱端到端工作。步驟 3 和 4 進行真實模型呼叫。

  1. 在自行驗證隔離下執行隔離檢查。兩個核心版本必須不同。注意容器記憶體限制是否限制 VM(請參閱調整大小)。

  2. 在在依賴沙箱之前測試沙箱下確認代理 CLI 在沙箱執行時下執行,在您將使用的映像中。

  3. 測試邊界:讓 Claude 檢查沙箱配置,然後執行監督逃逸測試,兩者都如在依賴沙箱之前測試沙箱中所述。

  4. 針對您知道的目標端到端執行小批次。使用您將用於真實參與的認證模式執行此步驟,而不是替代 API 金鑰:認證代理以不同方式處理每種模式(WIF 的令牌交換、Bedrock 的簽署、Vertex 的令牌鑄造),此執行確認您的端到端工作。之後檢查認證代理的日誌。

  5. 檢查沒有留下任何東西。批次完成後,不應保留任何代理容器、幫助程式容器、VM 程序或認證代理。出口代理的日誌應該不顯示除步驟 1 和 3 的探測外的任何拒絕行,認證代理的日誌應該只顯示模型呼叫。

操作說明

在 Kata 下使用 Firecracker 執行代理與執行純容器的不同之處。

綁定掛載是副本;即時檔案必須串流

Firecracker 沒有主機檔案系統共享,因此 Kata 在容器啟動時將綁定掛載的檔案或目錄複製到客體中,之後主機上的更改在內部看不到。這對於在執行期間不變的輸入(例如目標來源)很好,這些可以保持唯讀掛載。不掛載或串流任何認證檔案,因為代理容器不保存任何檔案(請參閱認證代理)。在執行期間確實變化的檔案必須由協調器通過 docker exec 寫入容器,並保持最新。容器內副本是代理可以編輯的普通檔案,因此讓協調器讀取主機上的原始檔案,並從代理無法到達的副本判斷發現。

每個代理都需要一個伴隨容器用於其網路

microVM 的網路介面必須在 VM 啟動時存在;Firecracker 之後無法新增一個。但是,Docker 只在執行時建立容器後才連接容器的網路。參考設計解決了這個問題。它首先啟動一個小的空閒容器,該容器連接到正確的網路並僅執行 sleep,然後在該容器的網路命名空間中啟動代理 (--network container:<name>)。Kata 在啟動時在那裡找到介面並將它們連接到 VM。伴隨恰好服務一個 VM,因為 Kata 將 VM 的主機端網路裝置留在其中,因此一起建立和移除該對,不要重複使用伴隨。一個成本約為 12 MB 的空閒程序。

停止卡住的代理

docker rm -f <agent-container> 就足夠了。協調器應該檢測到死容器,將執行標記為失敗,並在拆除執行時移除伴隨容器。

所有內容都由 IP 定址

Docker 的嵌入式 DNS 在主機端網路命名空間中執行,無法從客體內部存取,因此請將代理伺服器作為 IP 位址傳遞給代理程式,並為網路化目標指定靜態 IP。

docker exec 可行,docker cp 不可行

docker exec 進入代理程式容器的行為如常;Kata 客體內的代理程式執行命令。docker cp 進出代理程式容器不可行,因為容器的檔案位於客體內的虛擬磁碟上。使用 docker exec <container> cat <path> 等方式。

Firecracker 在其監獄內以 root 身份執行

Kata 以 uid 0 啟動監獄程式,因此 Firecracker 程序受到其 chroot、命名空間、seccomp 篩選器和 cgroup 的限制,而非由無特權使用者 ID 限制。每個 VM 共享的兩個檔案(客體核心和映像)改由不可變旗標保護(請參閱 Kata 設定)。

Kata 已棄用 Firecracker 依賴的執行時

Kata 透過其較舊的 Go 執行時執行 Firecracker。Kata 4.0 為其他 Hypervisor 設定了較新的 Rust 執行時作為預設值,並棄用了 Go 執行時。上游表示 Go 執行時仍會收到重要錯誤修正和 CVE 修正,且最早可能在 Kata 5.0 時移除。Rust 執行時未在其 Hypervisor 中列出 Firecracker,上游主要使用 QEMU 測試其 Docker 整合。規劃遷移。當您變更 Kata 版本時,重複執行 驗證新主機。Kata 也可以使用 Cloud Hypervisor 代替 Firecracker;參考實作尚未測試或強化該設定。

日誌

Kata 的執行時、Firecracker 和客體代理程式訊息進入日誌:journalctl -t kata。containerd 和 Docker 問題在 journalctl -u containerd 和 journalctl -u docker 中。

是否回答了您的問題?