Проксі для облікових даних — технічні аспекти

Як працює проксі.

Від чого він захищає. Від чого ні.

Ця сторінка призначена для оглядачів безпеки, тестувальників на проникнення та інженерів, які оцінюють модель загроз проксі. Вона описує, що робить проксі на рівні протоколу, де облікові дані зберігаються в пам'яті та які поверхні атаки залишаються.

Архітектура

Проксі є проксі-сервером HTTPS MITM на основі CONNECT. ШІ-агент встановлює HTTPS_PROXY для вказівки на нього. Коли агент робить HTTPS-запит, проксі перехоплює TLS-з'єднання, перевіряє заголовки запиту на наявність посилань на облікові дані, розпізнає їх у сховищі Clavitor та пересилає запит із вставленими обліковими даними до вихідного API.

За замовчуванням проксі прослуховує 127.0.0.1:1983 — шаблон sidecar, де проксі та агент спільно використовують хост. Для спільних розгортань (один проксі обслуговує кілька агентів у приватній мережі, контейнерний sidecar для кількох робочих навантажень, виділений хост проксі) інтерфейс прослуховування можна налаштувати за допомогою CLAVITOR_PROXY_LISTEN.

illustration: unknown name=proxy-sequence

Проксі є окремим бінарним файлом Go. Без CGO. Уся криптографія протоколу Clavitor проходить через канонічну реалізацію Rust, скомпільовану в WebAssembly та завантажену через wazero під час запуску.

Обробка TLS

Проксі генерує самопідписаний кореневий ЦС ECDSA P-256 під час першого запуску, зберігаючи його в каталозі бінарного файлу з правами доступу 0600. Для кожного вихідного хоста сертифікат листа створюється за запитом, підписується цим ЦС і кешується в пам'яті з обмеженим витісненням (1000 хостів). Сертифікати листів дійсні протягом 24 годин і прозоро перегенеруються на 23-й годині, щоб запобігти закінченню терміну дії під час сесії.

Агент повинен довіряти сертифікату ЦС проксі. Експортуйте його за допомогою clavitor-proxy ca.

Вихідні з'єднання використовують мінімум TLS 1.3 з узгодженням ALPN для HTTP/2 та HTTP/1.1. Для перевірки вихідних з'єднань використовується системний пул сертифікатів. Без закріплення сертифікатів — проксі довіряє всьому, чому довіряє ОС.

Credential lifecycle

Облікові дані ніколи не кешуються, ніколи не записуються на диск і ніколи не зберігаються довше одного HTTP-запиту.

ФазаДе зберігаються облікові даніТривалість
У стані спокою у сховищіШифротекст AES-GCM у базі даних сховищаДо видалення
Під час передачі до проксіJSON-відповідь від API сховища, зашифрована TLSОдин повний цикл HTTP-запиту
Розшифровано в проксіПам'ять процесу (рядок Go в купі)Один HTTP-запит
Вставлено в вихідний запитБайти, зашифровані TLS, у мережі до вихідного сервераОдин HTTP-запит

Проксі зберігає ключ розшифрування облікових даних агента (16 байтів) у пам'яті протягом усього часу роботи. Він завантажується з зашифрованої конфігурації sidecar (формат CLV1) під час запуску та очищається під час коректного завершення роботи. Ключ ніколи не залишає процес.

Конфігурація sidecar шифрується за допомогою AES-128-GCM та HMAC-SHA256 з використанням детермінованих ключів, отриманих зі статичного насіння. Це обфускація, а не конфіденційність — межа безпеки — це дозволи файлів (0600) та володіння файлом. Формат CLV1 є спільним для проксі, CLI та розширення браузера.

Режими розпізнавання

Режим 1 — явний плейсхолдер

Агент включає посилання clavitor://Entry/field у заголовку запиту. Проксі шукає запис у сховищі за назвою, отримує його, розшифровує назване поле та замінює плейсхолдер фактичним значенням.

Якщо пошук повертає нуль або більше одного результату, проксі повертає 502 зі стабільним кодом помилки. Плейсхолдер ніколи не видаляється та не пересилається як є.

Режим 2 — відповідність URL

Коли плейсхолдер відсутній, проксі запитує у сховища записи, поле URL яких відповідає вихідному хосту. Якщо існує рівно один збіг із розпізнаваною формою поля, проксі автоматично вставляє облікові дані.

Нуль збігів → пропуск (без очікування облікових даних). Кілька збігів → 502 з рекомендаціями щодо усунення неоднозначності. Невідома форма поля → 502.

Дерево рішень є детермінованим: плейсхолдер присутній → розпізнати або помилка. Плейсхолдер відсутній → відповідність URL або пропуск. Немає шляху мовчазного резервного варіанту, коли невдале розпізнавання призводить до надсилання запиту до вихідного сервера без облікових даних.

Agent identity

За замовчуванням сховище бачить власний ідентифікатор агента проксі з кожним запитом. Обмеження швидкості, перевірки області дії та записи аудиту приписуються проксі.

Коли кілька агентів спільно використовують один екземпляр проксі, плейсхолдер може включати ідентифікатор агента: clavitor://agentid@Entry/field. Проксі надсилає цей ідентифікатор агента до сховища, яке застосовує області дії та обмеження швидкості цього агента та реєструє доступ до нього. Ідентифікатор агента — це 32-символьне шістнадцяткове значення, показане на сторінці деталей агента в інтерфейсі користувача сховища.

# 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
РозгортанняМодель ідентифікаціїІзоляція
Один проксі на агентаID проксі = ID агента (за замовчуванням)Повна — окремий бінарний файл, конфігурація, область дії, обмеження швидкості
Спільний проксі, без ID агента в URLУсі агенти спільно використовують ID проксіСпільна область дії та обмеження швидкості
Спільний проксі + agentid@ в URLІдентифікатор на агентаОбласть дії, обмеження швидкості та аудит на агента

Ідентифікатор агента в URL не є механізмом автентифікації — токен CVT проксі автентифікує з'єднання. Ідентифікатор агента визначає приписування: чиї області дії застосовуються, чиї обмеження швидкості враховуються, чий журнал аудиту записує доступ. Сховище відхиляє невідомі ідентифікатори агентів з гучним збоєм.

Мережева безпека

Захист від SSRF

За замовчуванням проксі блокує вихідні з'єднання до приватних мереж (RFC 1918), метаданих екземплярів хмари (169.254.169.254), петльових, канальних та діапазонів NAT операторського класу. DNS розпізнається першим; усі повернуті IP-адреси перевіряються перед встановленням TCP-з'єднання, закриваючи вікно TOCTOU для прив'язки DNS.

Перевизначте за допомогою CLAVITOR_PROXY_ALLOW_PRIVATE=true для агентів, які законно досягають приватних API.

Закріплення цілі

Цільовий хост CONNECT захоплюється під час встановлення тунелю та використовується протягом усього терміну дії тунелю. Наступні запити в межах тунелю не можуть перенаправлятися на інший хост шляхом маніпулювання заголовком Host. Невідповідність призводить до 502.

Це запобігає встановленню агентом тунелю до api.openai.com з подальшим надсиланням запитів до internal-service.corp.

Обробка заголовків

Заголовки "hop-by-hop" видаляються з запитів та відповідей відповідно до RFC 7230 §6.1: Connection, Keep-Alive, Proxy-Authenticate, Proxy-Authorization, Proxy-Connection, TE, Trailers, Transfer-Encoding, Upgrade.

Set-Cookie видаляється з відповідей вихідних серверів, щоб запобігти розміщенню файлів cookie у HTTP-клієнті агента.

Тіла запитів і відповідей передаються без буферизації. Тіла запитів обмежені 64 МБ за замовчуванням (CLAVITOR_PROXY_MAX_BODY_MB). Тіла відповідей передаються без жорсткого обмеження; попередження в журналі видається, коли Content-Length перевищує 100 МБ.

Field-to-header mapping

У режимі відповідності URL проксі зіставляє мітки полів сховища з HTTP-заголовками:

Мітка поляВставлений заголовок
key, apikey, api_key, token, secret, bearer, access_tokenAuthorization: Bearer <value>
x-api-key, api-keyX-API-Key: <value>
username + password (у парі)Authorization: Basic base64(user:pass)
Будь-що іншеВідхилено — ERR-PROXY-052

У режимі плейсхолдера агент контролює, яке поле розпізнається і куди воно йде. Наведене вище зіставлення застосовується лише до режиму відповідності URL.

Error codes

Кожен збій генерує стабільний код ERR-PROXY-NNN. Ці коди є частиною публічного інтерфейсу проксі — агенти та оператори можуть зіставляти їх для сповіщень та налагодження.

ДіапазонКатегорія
001–019Налаштування (конфігурація, ініціалізація, генерація ЦС, WASM)
020–029Життєвий цикл демона
030–049Розпізнавання плейсхолдерів (URI clavitor://)
050–069Вставка за відповідністю URL
070–089Вихідний / TLS

Поля ідентифікації недоступні

Записи сховища підтримують три рівні шифрування. Поля, зашифровані сховищем, є метаданими у відкритому тексті. Поля, зашифровані обліковими даними, розшифровуються ключем агента. Поля, зашифровані ідентифікаційними даними, шифруються ключем, якого сервер і проксі ніколи не бачили. Лише власник сховища за допомогою свого апаратного ключа безпеки може їх розшифрувати.

Якщо плейсхолдер посилається на поле, зашифроване ідентифікаційними даними, проксі повертає ERR-PROXY-035. Без резервного варіанту, без часткового результату. Поле архітектурно недоступне з проксі.

Те, від чого проксі не захищає

Модель загроз проксі — це компрометація навички або впровадження підказки, що змушує автентифікованого агента збирати облікові дані. Первинними засобами захисту є обмеження швидкості для кожного агента у сховищі, унікальні квоти на записи та блокування після двох порушень. Проксі додає точку примусового виконання на рівні мережі, де облікові дані розпізнаються для кожного запиту і ніколи не зберігаються агентом.

Компрометація хоста

Проксі працює на тій самій машині, що й агент. Зловмисник з root-доступом може читати пам'ять процесу, підключати налагоджувач або перехоплювати трафік зворотного виклику. Проксі є рівнем вставки облікових даних, а не межею апаратного забезпечення безпеки.

Витік облікових даних через відповідь API

Якщо вихідний API повертає облікові дані у своїй відповіді (наприклад, кінцева точка "хто я"), агент їх бачить. Проксі вставляє облікові дані в запити, а не у відповіді. Він не фільтрує те, що повертається.

Журналювання

Проксі реєструє один рядок на прийнятий CONNECT і виводить рядки помилок для збоїв. Він ніколи не реєструє:

  • Розшифровані значення облікових даних
  • Повні URL-адреси запитів (рядки запитів можуть містити секрети — реєструються лише схема + хост + шлях)
  • Тіла запитів або відповідей
  • Ключ розшифрування облікових даних або вміст конфігурації sidecar

Коли проксі виявляє, що відповідь 400 від вихідного сервера містить ключові слова, пов'язані з автентифікацією (unauthorized, invalid token тощо), він реєструє діагностичну підказку, яка припускає, що вставлені облікові дані можуть бути застарілими. Відповідь пересилається без змін.

Криптографія

Уся криптографія протоколу Clavitor — розшифрування полів AES-GCM, виведення ключів HKDF, кодування base62, створення токенів CVT, пакування/розпакування конфігурації CLV1 — виконується в одному модулі WebAssembly (clavis_crypto.wasm), завантаженому через wazero, чистий WASM-рантайм Go. Без CGO. Без реалізації примітивів Clavitor на Go.

Модуль WASM скомпільований з того самого крейту Rust (clavis-crypto), який використовується браузером, CLI та розширеннями браузера. Одне джерело правди, один бінарний файл, одна поверхня аудиту.

Проксі використовує crypto/tls Go для TLS-трафіку та crypto/ecdsa для генерації сертифікатів MITM. Це транспортні аспекти, а не операції протоколу Clavitor.

Configuration

Секрети (ключ розшифрування облікових даних, ID агента, ID пристрою, URL сховища) зберігаються в зашифрованій конфігурації sidecar CLV1, записаній один раз під час clavitor-proxy init. Операційні важелі знаходяться в змінних середовища:

ЗміннаЗа замовчуваннямПризначення
CLAVITOR_PROXY_LISTEN127.0.0.1Інтерфейс прослуховування. Встановіть 0.0.0.0 для спільних розгортань або для конкретної IP-адреси інтерфейсу.
CLAVITOR_PROXY_PORT1983Порт прослуховування
CLAVITOR_PROXY_ALLOW_PRIVATEfalseДозволити з'єднання до приватних мереж / RFC-1918
CLAVITOR_PROXY_MAX_BODY_MB64Обмеження розміру тіла запиту
CLAVITOR_PROXY_WRITE_TIMEOUT300Час очікування запису відповіді в секундах
CLAVITOR_CONFIG(каталог exe)Перевизначити шлях до конфігурації sidecar

Операційні важелі не є секретами. Вони не належать до зашифрованої конфігурації. Вони належать туди, де інструменти розгортання вже керують ними — у середовище.

Перегляньте це самостійно.

Криптографія — це єдиний артефакт WASM, який можна перевірити. Модель загроз задокументована. Якщо ви знайдете щось, що ми пропустили, ми хочемо про це почути.