Proxy thông tin xác thực — kỹ thuật
Cách proxy hoạt động.
Nó bảo vệ khỏi những gì. Và không bảo vệ khỏi những gì.
Trang này dành cho người đánh giá bảo mật, người kiểm thử xâm nhập và kỹ sư đánh giá mô hình mối đe dọa của proxy. Nó mô tả những gì proxy thực hiện ở cấp độ giao thức, nơi thông tin xác thực tồn tại trong bộ nhớ và các bề mặt tấn công còn lại.
Kiến trúc
Proxy là một proxy MITM HTTPS dựa trên CONNECT. Một tác nhân AI đặt HTTPS_PROXY để trỏ đến nó. Khi tác nhân thực hiện yêu cầu HTTPS, proxy chặn kết nối TLS, kiểm tra header yêu cầu để tìm tham chiếu thông tin xác thực, truy xuất chúng từ két an toàn Clavitor và chuyển tiếp yêu cầu với thông tin xác thực được chèn vào để gửi tới API thượng nguồn.
Theo mặc định, proxy lắng nghe trên 127.0.0.1:1983 — mô hình sidecar nơi proxy và tác nhân chia sẻ một máy chủ. Đối với các triển khai được chia sẻ (một proxy phục vụ nhiều tác nhân trên mạng riêng, container sidecar cho nhiều workload, máy chủ proxy chuyên dụng), interface lắng nghe có thể được định cấu hình thông qua CLAVITOR_PROXY_LISTEN.
Proxy là một tệp nhị phân Go độc lập. Không có CGO. Tất cả mật mã giao thức Clavitor đều đi qua một triển khai Rust chuẩn được biên dịch sang WebAssembly và tải qua wazero khi khởi động.
Xử lý TLS
Proxy tạo một root CA ECDSA P-256 tự ký khi chạy lần đầu, được lưu trữ tại thư mục của binary với chế độ 0600. Đối với mỗi máy chủ thượng nguồn, một leaf certificate được cấp theo yêu cầu, được ký bởi CA này và được lưu vào bộ nhớ đệm với cơ chế eviction có giới hạn (1.000 máy chủ). Leaf certificate có hiệu lực trong 24 giờ và được tạo lại một cách minh bạch tại mốc 23 giờ để ngăn hết hạn giữa phiên.
Tác nhân phải tin tưởng chứng chỉ CA của proxy. Xuất nó bằng clavitor-proxy ca.
Các kết nối thượng nguồn sử dụng tối thiểu TLS 1.3 với đàm phán ALPN cho HTTP/2 và HTTP/1.1. Kho chứng chỉ hệ thống được sử dụng để xác minh thượng nguồn. Không ghim chứng chỉ — proxy tin tưởng bất cứ điều gì hệ điều hành tin tưởng.
Thông tin xác thực không bao giờ được lưu trữ trong bộ nhớ đệm, không bao giờ được ghi vào đĩa và không bao giờ được giữ lâu hơn một yêu cầu HTTP.
| Giai đoạn | Thông tin xác thực tồn tại ở đâu | Thời gian |
|---|---|---|
| Khi lưu trữ trong két an toàn | Bản mã AES-GCM trong cơ sở dữ liệu két an toàn | Cho đến khi bị xóa |
| Đang truyền đến proxy | Phản hồi JSON được mã hóa TLS từ API két an toàn | Một lượt đi-về HTTP |
| Được giải mã trong proxy | Bộ nhớ tiến trình (chuỗi Go trên heap) | Một yêu cầu HTTP |
| Được chèn vào yêu cầu thượng nguồn | Các byte được mã hóa TLS trên đường truyền tới thượng nguồn | Một yêu cầu HTTP |
Proxy giữ khóa giải mã thông tin xác thực của tác nhân (16 byte) trong bộ nhớ trong suốt thời gian chạy của nó. Nó được tải từ cấu hình sidecar được mã hóa (định dạng CLV1) khi khởi động và được xóa khi tắt tiến trình an toàn. Khóa không bao giờ rời khỏi tiến trình.
Cấu hình sidecar được mã hóa bằng AES-128-GCM và HMAC-SHA256 bằng cách sử dụng các khóa tất định được dẫn xuất từ một seed tĩnh. Đây là sự che khuất, không phải bảo mật — ranh giới bảo mật là phân quyền tệp (0600) và quyền sở hữu tệp. Định dạng CLV1 được chia sẻ giữa proxy, CLI và tiện ích mở rộng trình duyệt.
Chế độ truy xuất
Chế độ 1 — placeholder tường minh
Tác nhân bao gồm một tham chiếu clavitor://Entry/field trong header yêu cầu. Proxy tìm kiếm trong két an toàn entry theo tên, lấy nó, giải mã trường tương ứng và thay thế placeholder bằng giá trị thực.
Nếu tìm kiếm trả về 0 hoặc nhiều hơn 1 kết quả, proxy sẽ trả về 502 với mã lỗi ổn định. Placeholder không bao giờ bị loại bỏ và được chuyển tiếp nguyên trạng.
Chế độ 2 — khớp URL
Khi không có placeholder nào, proxy yêu cầu két an toàn các entry có trường URL khớp với máy chủ thượng nguồn. Nếu tồn tại chính xác một kết quả khớp với cấu trúc trường được nhận dạng, proxy sẽ tự động chèn thông tin xác thực.
0 kết quả khớp → passthrough (không yêu cầu thông tin xác thực). Nhiều kết quả khớp → 502 với hướng dẫn phân biệt. Cấu trúc trường không xác định → 502.
Cây quyết định là tất định: có placeholder → truy xuất hoặc thất bại. Không có placeholder → khớp URL hoặc passthrough. Không có cơ chế fallback ngầm nào mà việc truy xuất thất bại dẫn đến yêu cầu được gửi lên thượng nguồn mà không có thông tin xác thực.
Theo mặc định, két an toàn thấy ID tác nhân của proxy trên mỗi yêu cầu. Giới hạn tốc độ, kiểm tra phạm vi và mục nhật ký kiểm toán được gán cho proxy.
Khi nhiều tác nhân chia sẻ một phiên bản proxy, placeholder có thể bao gồm ID tác nhân: clavitor://agentid@Entry/field. Proxy gửi ID tác nhân này đến két an toàn, nơi nó áp dụng phạm vi và giới hạn tốc độ của tác nhân đó và ghi lại quyền truy cập cho tác nhân đó. ID tác nhân là giá trị thập lục phân 32 ký tự hiển thị trên trang chi tiết tác nhân trong giao diện người dùng két an toàn.
# Without agent ID — attributed to the proxy Authorization: Bearer clavitor://OpenAI/key # With agent ID — attributed to agent 0102030405060708090a0b0c0d0e0f10 Authorization: Bearer clavitor://0102030405060708090a0b0c0d0e0f10@OpenAI/key
| Triển khai | Mô hình danh tính | Cô lập |
|---|---|---|
| Một proxy cho mỗi tác nhân | ID Proxy = ID tác nhân (mặc định) | Đầy đủ — tệp nhị phân, cấu hình, phạm vi, giới hạn tốc độ riêng biệt |
| Proxy được chia sẻ, không có ID tác nhân trong URL | Tất cả các tác nhân chia sẻ ID của proxy | Phạm vi và giới hạn tốc độ được chia sẻ |
Proxy được chia sẻ + agentid@ trong URL | Danh tính theo từng tác nhân | Phạm vi, giới hạn tốc độ và nhật ký kiểm toán theo từng tác nhân |
ID tác nhân trong URL không phải là cơ chế xác thực — token CVT của proxy xác thực kết nối. ID tác nhân xác định việc quy kết: phạm vi nào được áp dụng, giới hạn tốc độ của ai được tính, nhật ký kiểm toán của ai ghi lại quyền truy cập. Két an toàn từ chối ID tác nhân không xác định với báo lỗi rõ ràng.
Bảo mật mạng
Bảo vệ khỏi SSRF
Theo mặc định, proxy chặn các kết nối thượng nguồn đến mạng riêng (RFC 1918), siêu dữ liệu phiên bản đám mây (169.254.169.254), loopback, link-local và các dải NAT cấp nhà mạng. DNS được phân giải trước; tất cả các IP được trả về đều được xác thực trước khi kết nối TCP được thực hiện, đóng cửa sổ TOCTOU của DNS rebinding.
Ghi đè bằng CLAVITOR_PROXY_ALLOW_PRIVATE=true cho các tác nhân có quyền truy cập hợp pháp vào API riêng.
Ghim mục tiêu
Máy chủ mục tiêu CONNECT được ghi lại khi thiết lập đường hầm và được sử dụng cho toàn bộ vòng đời của đường hầm. Các yêu cầu tiếp theo trong đường hầm không thể chuyển hướng đến một máy chủ khác bằng cách thao tác header Host. Sự không khớp dẫn đến 502.
Điều này ngăn tác nhân thiết lập một đường hầm đến api.openai.com và sau đó gửi yêu cầu đến internal-service.corp.
Xử lý tiêu đề
Các header hop-by-hop bị xóa khỏi cả yêu cầu và phản hồi theo RFC 7230 §6.1: Connection, Keep-Alive, Proxy-Authenticate, Proxy-Authorization, Proxy-Connection, TE, Trailers, Transfer-Encoding, Upgrade.
Set-Cookie bị xóa khỏi phản hồi thượng nguồn để ngăn chặn các máy chủ thượng nguồn đặt cookie vào HTTP client của tác nhân.
Phần thân yêu cầu và phản hồi được truyền trực tiếp mà không cần bộ đệm. Phần thân yêu cầu bị giới hạn ở mức 64 MB theo mặc định (CLAVITOR_PROXY_MAX_BODY_MB). Phần thân phản hồi được truyền trực tiếp mà không có giới hạn cứng; một cảnh báo log được phát ra khi Content-Length vượt quá 100 MB.
Ở chế độ khớp URL, proxy ánh xạ nhãn trường két an toàn tới các HTTP header:
| Nhãn trường | Header được chèn |
|---|---|
key, apikey, api_key, token, secret, bearer, access_token | Authorization: Bearer <value> |
x-api-key, api-key | X-API-Key: <value> |
username + password (cặp) | Authorization: Basic base64(user:pass) |
| Bất cứ thứ gì khác | Bị từ chối — ERR-PROXY-052 |
Ở chế độ placeholder, tác nhân kiểm soát trường nào được truy xuất và nó được đặt ở đâu. Ánh xạ trên chỉ áp dụng cho chế độ khớp URL.
Mọi lỗi đều tạo ra mã ERR-PROXY-NNN ổn định. Các mã này là một phần của giao diện công khai của proxy — tác nhân và người vận hành có thể khớp chúng để cảnh báo và gỡ lỗi.
| Phạm vi | Danh mục |
|---|---|
001–019 | Thiết lập (cấu hình, khởi tạo, tạo CA, WASM) |
020–029 | Vòng đời daemon |
030–049 | Truy xuất placeholder (URI clavitor://) |
050–069 | Chèn khớp URL |
070–089 | Thượng nguồn / TLS |
Các trường danh tính không thể truy cập được
Các entry két an toàn hỗ trợ ba cấp độ mã hóa. Các trường được Mã hóa két an toàn là siêu dữ liệu văn bản thuần túy. Các trường được Mã hóa thông tin xác thực được giải mã bằng khóa của tác nhân. Các trường được Mã hóa danh tính được mã hóa bằng khóa mà máy chủ và proxy chưa từng thấy. Chỉ chủ sở hữu két an toàn, thông qua khóa phần cứng của họ, mới có thể giải mã chúng.
Nếu một placeholder tham chiếu đến một trường Mã hóa danh tính, proxy sẽ trả về ERR-PROXY-035. Không có fallback, không có kết quả một phần. Trường này về mặt kiến trúc không thể truy cập được từ proxy.
Những gì proxy không bảo vệ khỏi
Mô hình mối đe dọa của proxy là một skill bị xâm phạm hoặc một cuộc tấn công prompt injection khiến một tác nhân đã được xác thực thu thập thông tin xác thực. Giới hạn tốc độ theo từng tác nhân của két an toàn, hạn ngạch entry duy nhất và cơ chế khóa sau hai lần vi phạm là các biện pháp phòng thủ chính. Proxy bổ sung một điểm thực thi lớp mạng nơi thông tin xác thực được truy xuất cho mỗi yêu cầu và không bao giờ được tác nhân giữ.
Proxy chạy trên cùng máy với tác nhân. Kẻ tấn công có quyền truy cập root có thể đọc bộ nhớ tiến trình, gắn debugger hoặc chặn lưu lượng loopback. Proxy là một lớp chèn thông tin xác thực, không phải là ranh giới bảo mật phần cứng.
Nếu API thượng nguồn trả lại thông tin xác thực trong phản hồi của nó (ví dụ: một endpoint "whoami"), tác nhân sẽ thấy nó. Proxy chèn thông tin xác thực vào yêu cầu, không phải phản hồi. Nó không lọc dữ liệu trả về.
Ghi log
Proxy ghi log một dòng cho mỗi CONNECT được chấp nhận và xuất các dòng lỗi cho các lỗi. Nó không bao giờ ghi log:
- Giá trị thông tin xác thực đã giải mã
- URL yêu cầu đầy đủ (query string có thể chứa secret — chỉ scheme + host + path được ghi log)
- Phần thân yêu cầu hoặc phản hồi
- Khóa giải mã thông tin xác thực hoặc nội dung cấu hình sidecar
Khi proxy phát hiện một phản hồi 400 từ thượng nguồn chứa các từ khóa liên quan đến xác thực (unauthorized, invalid token, v.v.), nó sẽ ghi một gợi ý chẩn đoán cho biết thông tin xác thực đã chèn có thể đã cũ. Phản hồi được chuyển tiếp không thay đổi.
Mật mã
Tất cả mật mã giao thức Clavitor — giải mã trường AES-GCM, dẫn xuất khóa HKDF, mã hóa base62, cấp token CVT, đóng gói/giải nén cấu hình CLV1 — thực thi bên trong một mô-đun WebAssembly duy nhất (clavis_crypto.wasm) được tải qua wazero, một trình chạy WASM thuần Go. Không có CGO. Không có triển khai lại các nguyên thủy Clavitor bằng Go.
Mô-đun WASM được biên dịch từ cùng một crate Rust (clavis-crypto) được sử dụng bởi trình duyệt, CLI và các tiện ích mở rộng trình duyệt. Một nguồn chân lý, một binary, một phạm vi kiểm toán.
Proxy sử dụng crypto/tls của Go cho đường truyền TLS và crypto/ecdsa để tạo chứng chỉ MITM. Đây là các vấn đề ở tầng truyền tải, không phải hoạt động giao thức Clavitor.
Secret (khóa giải mã thông tin xác thực, ID tác nhân, ID thiết bị, URL két an toàn) nằm trong cấu hình sidecar CLV1 được mã hóa, được ghi một lần trong quá trình clavitor-proxy init. Các cấu hình vận hành nằm trong các biến môi trường:
| Biến | Mặc định | Mục đích |
|---|---|---|
CLAVITOR_PROXY_LISTEN | 127.0.0.1 | Interface lắng nghe. Đặt thành 0.0.0.0 cho các triển khai được chia sẻ hoặc thành IP interface cụ thể. |
CLAVITOR_PROXY_PORT | 1983 | Cổng lắng nghe |
CLAVITOR_PROXY_ALLOW_PRIVATE | false | Cho phép kết nối đến mạng RFC-1918 / mạng riêng |
CLAVITOR_PROXY_MAX_BODY_MB | 64 | Giới hạn kích thước phần thân yêu cầu |
CLAVITOR_PROXY_WRITE_TIMEOUT | 300 | Thời gian chờ ghi phản hồi theo giây |
CLAVITOR_CONFIG | (thư mục exe) | Ghi đè đường dẫn cấu hình sidecar |
Các cấu hình vận hành không phải là secret. Chúng không thuộc về cấu hình được mã hóa. Chúng thuộc về nơi các công cụ triển khai đã quản lý chúng — môi trường.
Hãy tự đánh giá.
Mật mã là một artifact WASM duy nhất có thể kiểm toán. Mô hình mối đe dọa đã được tài liệu hóa. Nếu bạn tìm thấy điều gì đó chúng tôi đã bỏ sót, chúng tôi muốn nghe về điều đó.