Протокол транспортной безопасности TLS 1.3 гарантирует конфиденциальность передаваемых пакетов при их прохождении через узлы связи интернет-провайдеров. Однако под защитным слоем шифрования сохраняется фундаментальная уязвимость на уровне метаданных: целевой сервер всегда видит исходящий IP-адрес клиента.
В базовых сценариях взаимодействия это считается естественной частью сетевой маршрутизации. Но при выполнении конфиденциальных задач — отправке запросов к генеративным языковым моделям (LLM), передаче телеметрии сбоев, биометрической верификации или обращении к геолокационным службам — IP-адрес превращается в устойчивый цифровой идентификатор. Сопоставляя временные метки сессий и сетевые адреса, серверные системы формируют детальные профили активности пользователей даже при отсутствии авторизации в учетных записях.
Традиционные прокси-серверы лишь переносят точку наблюдения: оператор прокси видит одновременно реальный адрес клиента и открытый адрес назначения. Для разрыва этой связи IETF ратифицировала спецификацию RFC 9458 (Oblivious HTTP), дополненную стандартами RFC 9180 (Hybrid Public Key Encryption, HPKE) и RFC 9292 (Binary HTTP).
+--------------------------------------------------------------------------+
| АРХИТЕКТУРА RFC 9458 OBLIVIOUS HTTP |
+--------------------------------------------------------------------------+
| |
| +------------+ 1. Зашифрованный запрос (HPKE) +------------+ |
| | | --------------------------------------> | Шлюз | |
| | Клиент | <-------------------------------------- | ретрансля- | |
| | (Браузер / | 4. Зашифрованный ответ (HPKE) | ции (Relay)| |
| | AI Agent) | +------------+ |
| +------------+ | |
| | 2. Пересыл|3. Ответ|
| | (IP-адрес клиента виден ТОЛЬКО Relay) шифрован- |шифрован|
| | (Данные зашифрованы публичным ключом Target)ного тела|ного тела
| | v |
| | +------------+ |
| +----------------------------------------------> | Целевой | |
| (Сквозная криптографическая граница) | сервер | |
| Сервер расшифровывает тело через HPKE | (Target) | |
| Сервер видит ТОЛЬКО IP-АДРЕС ШЛЮЗА RELAY +------------+ |
| |
+--------------------------------------------------------------------------+
Криптографические основы: схема HPKE и бинарный формат Binary HTTP
Спецификация RFC 9458 опирается на принцип недопущения сговора между двумя независимыми инфраструктурными узлами: шлюзом ретрансляции (Relay) и целевым сервером (Target). Шлюз Relay пересылает зашифрованные бинарные контейнеры, не имея ключа для их вскрытия; целевой сервер Target обрабатывает полезную нагрузку, но видит исключительно сетевой адрес шлюза ретрансляции.
Надежность протокола базируется на двух ключевых компонентах:
1. Кадрирование Binary HTTP (RFC 9292)
Стандартные запросы HTTP состоят из текстовых строк заголовков и произвольного тела пакета. В протоколе OHTTP запрос целиком преобразуется в детерминированный бинарный массив байтов согласно спецификации RFC 9292 (BHTTP):
+--------------------+--------------------------------+--------------------+
| Управляющие поля | Индексированные заголовки | Тело полезной |
| (GET /api/v1/query)| (Host: target.example.com ...) | нагрузки (бинарное)|
+--------------------+--------------------------------+--------------------+
Бинарное представление исключает разночтения на уровне транспортных протоколов до выполнения криптографических процедур.
2. Гибридное шифрование с открытым ключом (HPKE, RFC 9180)
Для защиты бинарного HTTP-запроса от перехвата на шлюзе Relay клиент шифрует его с использованием конфигурации публичного ключа целевого сервера Target. Конфигурация включает:
key_id: 1-байтовый идентификатор для поддержки ротации ключей;kem_id: идентификатор механизма инкапсуляции ключей (0x0020для DHKEM над Curve25519);kdf_id: идентификатор функции деривации ключей (0x0001для HKDF-SHA256);aead_id: идентификатор шифра с аутентификацией данных (0x0001для AES-128-GCM или0x0003для ChaCha20-Poly1305);public_key: байтовая последовательность открытого ключа Target.
В базовом режиме HPKE клиент генерирует эфемерную пару ключей $(sk_E, pk_E)$ и вычисляет общий секрет с открытым ключом целевого сервера $pk_T$:
$$ ext{SharedSecret} = ext{DH}(sk_E, pk_T)$$
С помощью алгоритма HKDF клиент формирует ключ AEAD-шифрования $K_{ ext{req}}$ и вектор инициализации $N_{ ext{req}}$:
$$(K_{ ext{req}}, N_{ ext{req}}) = ext{KeyDerivation}( ext{SharedSecret}, ext{info})$$
Бинарный запрос BHTTP запечатывается в шифротекст $C_{ ext{req}}$:
$$C_{ ext{req}} = ext{Seal}(K_{ ext{req}}, N_{ ext{req}}, ext{aad}, ext{BinaryHTTPRequest})$$
Сообщение, направляемое на шлюз Relay, имеет медиа-тип message/ohttp-req и структуру:
[KeyID (1 байт)] || [KEM (2 байта)] || [KDF (2 байта)] || [AEAD (2 байта)] || [enc (32 байта)] || [Шифротекст]
Поскольку секретным ключом от $pk_T$ обладает только Target, шлюз Relay технически не способен прочитать или модифицировать полезную нагрузку.
+--------------------------------------------------------------------------+
| ВИДИМОСТЬ ДАННЫХ ДЛЯ УЧАСТНИКОВ ОБМЕНА |
+--------------------------------------------------------------------------+
| Субъект | Видит реальный IP клиента? | Видит тело запроса? | Видит ответ?|
+-------------+----------------------------+---------------------+-------------+
| Провайдер | Да | НЕТ (TLS-туннель) | НЕТ |
| Шлюз Relay | Да (или IP VPN) | НЕТ (Шифротекст) | НЕТ |
| Сервер Target| НЕТ (Видит адрес Relay) | ДА (Расшифровано) | ДА |
+--------------------------------------------------------------------------+
Жизненный цикл сессии Oblivious HTTP
Взаимодействие в рамках стандарта OHTTP состоит из пяти шагов:
- Получение конфигурации ключей: Клиент считывает конфигурацию открытых ключей Target через записи DNS HTTPS или доверенные службы каталогов.
- Формирование зашифрованного контейнера: Клиент сериализует запрос в Binary HTTP, создает эфемерную пару ключей HPKE, запечатывает пакет и формирует тело
message/ohttp-req. - Ретрансляция через Relay: Клиент отправляет пакет на Relay методом HTTPS
POST /relay. Шлюз Relay завершает входящую сессию TLS, удаляет сетевые заголовки клиента и направляет полезную нагрузку на Target по новому соединению. - Обработка на сервере Target: Целевой сервер сопоставляет
key_id, выполняет декапсуляциюenc, восстанавливает общий секрет, расшифровывает полезную нагрузку и извлекает Binary HTTP. Выполняется бизнес-логика (например, инференс AI), а результат упаковывается в Binary HTTP. - Инкапсуляция ответа: Target генерирует сессионный ключ $K_{ ext{res}}$ из контекста HPKE, запечатывает ответ в тело
message/ohttp-resи отправляет его обратно на Relay. Шлюз Relay пересылает контейнер клиенту для локальной расшифровки.
Интеграция с протоколом RiceGuard и сетевым уровнем L3
Хотя протокол Oblivious HTTP функционирует на прикладном уровне (L7), его объединение с туннелями третьего уровня (L3) обеспечивает эшелонированную защиту:
- Разрыв профилирования на стороне Relay: При передаче трафика через VPNRice и протокол RiceGuard сессия с шлюзом Relay устанавливается с общего пула IP-адресов VPN, а не с домашнего подключения. Даже при компрометации шлюза Relay сопоставить активность с конкретным абонентом невозможно.
- Защита от утечек DNS: Запросы к системе доменных имен при поиске шлюзов Relay и Target изолированы внутри сетевого пространства RiceGuard.
- Конфиденциальность локальных агентов AI: Автономные агенты искусственного интеллекта при вызове внешних API могут направлять сетевые запросы через OHTTP поверх туннелей RiceGuard, исключая сохранение клиентских IP-адресов поставщиками нейросетей.
Реализация клиента OHTTP на языке Go
Ниже приведен пример реализации клиентской части, выполняющей инкапсуляцию запроса Binary HTTP по стандарту RFC 9458:
package main
import (
"bytes"
"crypto/rand"
"fmt"
"io"
"net/http"
"github.com/cloudflare/circl/hpke"
)
type OHTTPEncapsulator struct {
suite hpke.Suite
targetPK hpke.PublicKey
keyID uint8
}
func NewOHTTPEncapsulator(keyID uint8, kemID hpke.KEM, kdfID hpke.KDF, aeadID hpke.AEAD, rawPubKey []byte) (*OHTTPEncapsulator, error) {
suite := hpke.NewSuite(kemID, kdfID, aeadID)
pk, err := suite.KEM().Scheme().UnmarshalBinaryPublicKey(rawPubKey)
if err != nil {
return nil, fmt.Errorf("ошибка парсинга открытого ключа: %w", err)
}
return &OHTTPEncapsulator{
suite: suite,
targetPK: pk,
keyID: keyID,
}, nil
}
// EncapsulateRequest упаковывает Binary HTTP в контейнер message/ohttp-req
func (oe *OHTTPEncapsulator) EncapsulateRequest(bhttpReq []byte) ([]byte, hpke.Context, error) {
sender, err := oe.suite.NewSender(oe.targetPK, []byte("message/bhttp request"))
if err != nil {
return nil, nil, fmt.Errorf("ошибка инициализации HPKE sender: %w", err)
}
enc, ctx, err := sender.Setup(rand.Reader)
if err != nil {
return nil, nil, fmt.Errorf("ошибка настройки HPKE: %w", err)
}
ciphertext, err := ctx.Seal(nil, bhttpReq)
if err != nil {
return nil, nil, fmt.Errorf("ошибка шифрования данных: %w", err)
}
var buf bytes.Buffer
buf.WriteByte(oe.keyID)
buf.Write([]byte{0x00, 0x20}) // DHKEM(X25519, HKDF-SHA256)
buf.Write([]byte{0x00, 0x01}) // HKDF-SHA256
buf.Write([]byte{0x00, 0x01}) // AES-128-GCM
buf.Write(enc)
buf.Write(ciphertext)
return buf.Bytes(), ctx, nil
}
func SendToRelay(relayURL string, targetURL string, ohttpPayload []byte) ([]byte, error) {
req, err := http.NewRequest("POST", relayURL, bytes.NewReader(ohttpPayload))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "message/ohttp-req")
req.Header.Set("Target", targetURL)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, fmt.Errorf("ошибка отправки на релей: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("ошибка обработки шлюзом: HTTP %d", resp.StatusCode)
}
return io.ReadAll(resp.Body)
}
Инженерные компромиссы и специфика внедрения
При проектировании систем с использованием RFC 9458 необходимо учитывать следующие факторы:
- Дополнительная сетевая задержка: Прохождение пакетов через два физических серверных узла (Клиент $ o$ Relay $ o$ Target) добавляет около 20–45 мс к общему времени отклика (RTT). Протокол оптимизирован для дискретных запросов к API и телеметрии, а не для интерактивного веб-серфинга.
- Особенности кэширования: Пограничные узлы CDN кэшируют ответы на основе анализа URL. Поскольку тела запросов в OHTTP непрозрачны, промежуточное кэширование требует специальных меток.
- Независимость субъектов: Надежность схемы аннулируется при нахождении Relay и Target под единым административным контролем. Обязательным условием является распределение ролей между независимыми операторами инфраструктуры.
Стандарт RFC 9458 подтверждает, что защита сетевой конфиденциальности достигается четким математическим разделением идентификаторов и данных.



