Глава 28. SSL/TLS действия¶
Действия SSL/TLS управляют перехватом TLS-трафика (MITM), параметрами соединения, проверкой сертификатов и контролем протоколов поверх TLS. Доступны в слоях <SSL-Intercept> и <SSL>.
Аналоги BlueCoat:
ssl.forward_proxy(),detect_protocol(),server.certificate.validate().
28.1. ssl.forward_proxy(yes/no) — SSL forward proxy¶
Включает или отключает TLS-инспекцию (MITM) для совпавшего запроса. При yes прокси расшифровывает TLS-трафик, инспектирует содержимое и перешифровывает с использованием динамически сгенерированного сертификата (forged certificate). При no запрос туннелируется без расшифровки (TCP-level forwarding).
Синтаксис:
where: yes — перехватить (MITM); no — туннелировать без инспекции.
Тип: Нетерминальное. Обработка продолжается к следующим слоям.
Слои и транзакции: SSL-Intercept, SSL. Применяется к CONNECT-транзакциям и transparent TLS-соединениям.
Пример:
<SSL-Intercept>
; По умолчанию — перехватывать
ssl.forward_proxy(yes)
; Исключения: финансы и pinned-сертификаты
url.domain=*.bank.com ssl.forward_proxy(no)
category="Financial Services" ssl.forward_proxy(no)
См. также: ssl.intercept, Глава 15. Условия SSL/TLS
28.2. ssl.intercept(yes/no) — перехват TLS¶
Синоним ssl.forward_proxy. Управляет MITM-перехватом. Предпочтительная форма для слоя <SSL-Intercept>.
Синтаксис:
where: yes — перехватить; no — пропустить без инспекции.
Тип: Нетерминальное.
Слои и транзакции: SSL-Intercept. Применяется к CONNECT-транзакциям и transparent TLS-соединениям.
Примечание: Для работы TLS-инспекции необходима настройка
inspection_enabled = trueвproxy.toml.
Пример:
См. также: ssl.forward_proxy
28.3. server.certificate.validate(yes|no) — верификация сертификата сервера¶
Управляет проверкой сертификата upstream-сервера при TLS-соединении. При no прокси не проверяет валидность, срок действия и цепочку доверия сертификата сервера. Используется для внутренних серверов с self-signed сертификатами. Имя как в BlueCoat.
Синтаксис:
where: yes — проверять сертификат (поведение по умолчанию); no — не проверять.
Тип: Нетерминальное.
Слои и транзакции: <SSL>. Применяется ко всем HTTPS-транзакциям.
Пример:
См. также: client.certificate.validate
28.4. client.certificate.validate(yes|no|require) — верификация клиента¶
Запрашивает или требует клиентский сертификат для mTLS-аутентификации. Имя и значения yes|no как в BlueCoat; require — расширение Redcoat (TLS handshake завершается ошибкой, если клиент не предоставил сертификат).
Синтаксис:
where: yes — запросить сертификат (необязательно); no — не запрашивать; require — требовать (отказ без сертификата, расширение Redcoat).
Тип: Нетерминальное.
Слои и транзакции: <SSL>, <SSL-Intercept>. Применяется к входящим TLS-соединениям.
Пример:
<SSL>
; Требовать клиентский сертификат для админки
url.path=/admin client.certificate.validate(require)
; Запросить, но не требовать для остальных
client.certificate.validate(yes)
Полный сценарий mTLS через SSL-перехват (каноническая форма)¶
Это эталонная политика «требовать валидный клиентский сертификат для всего HTTPS-трафика». Поведение: валидный сертификат → 200, без сертификата → 403.
<SSL-Intercept>
ssl.intercept(yes)
client.certificate.validate(require)
<Proxy>
client.certificate.presented=no deny
allow
Вариант с проверкой Common Name (авторизация по атрибуту сертификата):
<SSL-Intercept>
ssl.intercept(yes)
client.certificate.validate(yes)
<Proxy>
client.certificate.common_name="trusted-client" allow
deny
Имена условий: CN проверяется через
client.certificate.common_name=(каноническое имя как в BlueCoat);client.certificate.subject.cn=принимается как алиас на то же условие. OU — черезclient.certificate.subject.ou=.
Почему именно в этих слоях (важные нюансы):
| Слой | Фаза | Что доступно | Семантика правил | Назначение |
|---|---|---|---|---|
<SSL-Intercept> |
до TLS handshake | только SNI + IP клиента/сервера; клиентского сертификата ещё нет (TLS не расшифрован) | аккумуляция — применяются ВСЕ совпавшие правила | решение о перехвате (ssl.intercept) + требование сертификата (client.certificate.validate) |
<Proxy> / <SSL> |
после MITM-handshake, на расшифрованном запросе | полный URL, заголовки, клиентский сертификат предъявлен | выигрывает первое совпадение — побеждает первое совпавшее правило | проверка наличия/атрибутов сертификата (client.certificate.presented, ...subject.cn и т.п.) |
-
<SSL-Intercept>— независимые настройки, поэтому их можно (и нужно) задавать отдельными строками.ssl.intercept(yes)иclient.certificate.validate(require)— две разные настройки конфигурации TLS-перехвата, и обе обязаны примениться. Этот слой аккумулирует решения всех совпавших правил (в отличие от<Proxy>). -
Проверку сертификата размещают в
<Proxy>или<SSL>, НЕ в<SSL-Intercept>. В<SSL-Intercept>сертификата физически ещё нет (handshake не выполнен) — условиеclient.certificate.presentedтам всегда ложно. Сертификат становится доступен только после MITM-handshake, на расшифрованном внутреннем запросе. Для CONNECT-трафика движок специально откладывает решение<Proxy>до этого момента. -
В
<Proxy>порядок правил важен (выигрывает первое совпадение): защитное правило (client.certificate.presented=no deny) всегда ставится ПЕРЕД завершающимallow. Если поменять местами —allowсработает первым и сертификат проверяться не будет. -
Глубокая защита (несколько уровней):
client.certificate.validate(require)принуждает на уровне TLS (handshake завершается ошибкой без сертификата), аclient.certificate.presented=no deny— на уровне доступа (отдаёт корректный403с блок-страницей). Достаточно одного механизма, но вместе они надёжнее; форма с явнымdenyдаёт более понятный для клиента ответ, чем сырой обрыв TLS.
Типичная ошибка. Если записать обе настройки
<SSL-Intercept>так, чтобы перехват «терялся», соединение туннелируется без MITM и требование сертификата молча не применяется. В канонической форме вышеssl.intercept(yes)указан явно и применяется всегда.
Отзыв (revocation) клиентского сертификата — check_revocation()¶
Проверка отзыва клиентского сертификата (CRL по CDP-URL из сертификата + локальные CRL-файлы; OCSP) реализована и принудительно применяется при проверке клиентских сертификатов (config: crl_check + crl_files). Поведение: отозванный сертификат → отказ; при включённой проверке без доступного CRL → безопасный отказ (блокировка).
CPL-свойство client.certificate.validate.check_revocation(auto|ocsp|local|no) поддерживается и переопределяет режим отзыва per-rule поверх дефолта cert-realm:
<SSL>
client.certificate.validate(yes) client.certificate.validate.check_revocation(ocsp)
; для доверенного домена — без проверки отзыва
url.domain=internal.lan client.certificate.validate.check_revocation(no)
| Режим | Эффект |
|---|---|
no |
пропустить проверку отзыва для совпавшего трафика |
ocsp |
проверять через OCSP |
local |
локальные CRL-файлы + CDP-URL из сертификата |
auto |
проверять обоими способами (отзыв любым → отказ) |
Применение: проверка отзыва выполняется только при перехвате (MITM) — на расшифрованном клиентском сертификате, по всей цепочке сертификатов.
CCL (выбор списка CA) — ccl()¶
CPL-свойство
client.certificate.validate.ccl(ccl_id)(выбор именованного CA-списка для отдельного правила) пока не поддерживается (политика с ним отклоняется — безопасный отказ). Требуется реестр именованных CCL (ccl_id → набор CA), которого ещё нет. Сейчас проверка клиентского сертификата использует единственный набор CA realm'а. Это сознательный безопасный отказ (а не молчаливое бездействие), чтобы политика не «делала вид».
См. также: ssl.intercept, client.certificate.presented=, server.certificate.validate, Глава 12. Условия аутентификации
28.5. ssl.client_certificate(cert) — клиентский сертификат¶
Статус: планируется. Использование в CPL файле приведёт к ошибке парсинга.
Указывает именованный сертификат, используемый прокси для mTLS-соединения с upstream-сервером (client certificate presentation).
Синтаксис:
where: certificate_name — имя сертификата из keyring прокси.
Тип: Нетерминальное.
Слои и транзакции: SSL. Применяется к исходящим HTTPS-соединениям.
Пример:
См. также: ssl.verify_client
28.6. ssl.cipher_suites(suite1, suite2, ...) — наборы шифров¶
Ограничивает допустимые наборы шифров для TLS-соединения. Поддерживаются имена наборов, группы (gost, gost_modern) и hex-идентификаторы (0xC100).
Синтаксис:
where: suite — имя набора шифров (например, TLS_AES_256_GCM_SHA384), группа (gost) или hex ID (0xC100).
Тип: Нетерминальное.
Слои и транзакции: SSL. Применяется ко всем TLS-соединениям.
Пример:
См. также: ssl.min_version / ssl.max_version
28.7. ssl.version(version1, version2, ...) — допустимые версии TLS¶
Указывает список допустимых версий протокола TLS. Запросы с другими версиями будут отклонены.
Синтаксис:
where: version — версия TLS (например, TLSv1.2, TLSv1.3).
Тип: Нетерминальное.
Слои и транзакции: SSL. Применяется ко всем TLS-соединениям.
Пример:
См. также: ssl.min_version / ssl.max_version
28.8. {server,client}.connection.min_ssl_version / max_ssl_version — версии TLS¶
Устанавливают минимальную и максимальную допустимую версию TLS. Есть две независимые пары — для каждой стороны MITM-перехвата (имена как в BlueCoat):
server.connection.*— соединение с upstream-сервером (применяется к upstream-коннектору).client.connection.*— соединение с клиентом (применяется к MITM-acceptor'у).
Синтаксис:
server.connection.min_ssl_version(version)
server.connection.max_ssl_version(version)
client.connection.min_ssl_version(version)
client.connection.max_ssl_version(version)
where: version — preserve, sslv3, tlsv1, tlsv1.1, tlsv1.2, tlsv1.3. Значение preserve (по умолчанию в BlueCoat) означает «не ограничивать, сохранить версию, предложенную пиром» — в Redcoat при preserve ограничение НЕ применяется.
Тип: Нетерминальное.
Слои и транзакции: <SSL-Intercept> / <SSL>. Серверная пара — к upstream TLS; клиентская — к клиентскому (MITM) TLS.
Пример:
<SSL-Intercept>
; upstream: только TLS 1.2–1.3
server.connection.min_ssl_version(tlsv1.2)
server.connection.max_ssl_version(tlsv1.3)
; клиент: не принимать ниже TLS 1.2 для конкретного хоста
client.connection.ssl_server_name=www.example.com client.connection.min_ssl_version(tlsv1.2)
Реализация в Redcoat: обе стороны реализованы. Серверная → CplDecision::SslMin/MaxVersion → upstream-коннектор; клиентская → CplDecision::ClientSslMin/MaxVersion → MITM-acceptor (apply_client_version, preserve пропускается).
См. также: ssl.cipher_suites
28.9. http2.client.accept(yes|no|preserve) — управление HTTP/2 на клиентском соединении¶
Определяет, принимает ли прокси HTTP/2 от клиента. no → клиент работает по HTTP/1.1. Имя и значения как в BlueCoat.
Синтаксис:
where:
yes— принимать HTTP/2 от клиента (поведение по умолчанию);no— HTTP/2-запросы клиента обрабатываются как HTTP/1.1 (понижение версии);preserve— если сервер поддерживает HTTP/2, клиентское соединение апгрейдится до HTTP/2; эквивалентноyes, когда поддержку сервера определить нельзя.
Что реально делает: при no прокси убирает h2 из ALPN (и на стороне клиента, и на upstream-соединении) → согласуется HTTP/1.1 (понижение версии). yes/preserve оставляют h2 в ALPN.
Тип: Нетерминальное.
Слой <SSL-Intercept>, решение по SNI; применяется там, где прокси терминирует клиентский TLS
ALPN согласуется в TLS-рукопожатии (до того как известен URL), поэтому правило размещается в слое <SSL-Intercept> и гейтится по client.connection.ssl_server_name= (SNI) или client.address=. В слое <SSL> (после рукопожатия) — не повлияет.
Где работает: при SSL-инспекции (MITM) — да; на сквозном CONNECT-туннеле без инспекции — нет (прокси не в TLS, ALPN согласуется между клиентом и сервером назначения напрямую). Поддержка терминирующих слушающих сокетов без MITM (reverse / forward-HTTPS) пока в работе.
Пример:
<SSL-Intercept>
; Принудить клиентов example.com к HTTP/1.1
client.connection.ssl_server_name=example.com http2.client.accept(no)
28.10. ssl.quic(action) — управление QUIC/HTTP3¶
Статус: в процессе реализации. Принимается парсером, но пока не применяется — управление QUIC для отдельных правил ещё не подключено.
Управляет QUIC-соединениями (HTTP/3).
Синтаксис:
where: значения: inspect|allow|bypass|block|deny|log.
Тип: Нетерминальное.
Слои и транзакции: SSL. Применяется к UDP-транзакциям QUIC.
Пример:
См. также: http2.client.accept
28.11. ssl.ech(action) — управление Encrypted Client Hello¶
Статус: в процессе реализации. Принимается парсером, но пока не применяется — управление ECH для отдельных правил ещё не подключено.
Управляет ECH (Encrypted Client Hello), расширением TLS, скрывающим SNI.
Синтаксис:
where: значения: inspect|allow|bypass|block|deny|log.
Тип: Нетерминальное.
Слои и транзакции: SSL, SSL-Intercept. Применяется к TLS-соединениям с расширением ECH.
Пример:
См. также: ssl.dns_over_tls
28.12. ssl.dns_over_tls(action) — управление DNS over TLS¶
Управляет DNS over TLS (DoT) соединениями на порту 853.
Синтаксис:
where: значения: inspect|allow|bypass|block|deny|log.
Тип: Нетерминальное.
Слои и транзакции: SSL. Применяется к TLS-соединениям на порту 853.
Пример:
См. также: Глава 31. Управление DNS
28.13. Гранулярный контроль сертификатов (расширения Redcoat)¶
Расширения Redcoat. В BlueCoat валидация сертификата сервера — это один коарс-переключатель
server.certificate.validate(yes|no)(он покрывает trust chain, срок действия, well-formedness разом). Redcoat добавляет гранулярные переключатели — блокировать только по конкретной причине. Нетерминальные, слой<SSL-Intercept>/<SSL>.
| Действие | Описание |
|---|---|
ssl.block_expired_cert(yes\|no) |
блокировать серверы с истёкшим сертификатом |
ssl.block_invalid_cert(yes\|no) |
блокировать серверы с невалидным сертификатом |
ssl.block_weak_cert(yes\|no) |
блокировать серверы со слабым сертификатом |
ssl.min_key_size(bits) |
минимальный размер ключа сертификата (BlueCoat регулирует силу через cipher-suite strength) |
Ещё в процессе (пока не поддерживаются в политике): ssl.subordinate_ca(ca_name) (BlueCoat: ssl.forward_proxy.issuer_keyring()), ssl.allowed_sig_algorithms=(...), ssl.client_certificate(...).
Пример комплексной SSL-политики:
<SSL-Intercept>
; По умолчанию — перехватывать
ssl.forward_proxy(yes)
; Исключения: финансы, медицина, pinned-сертификаты
url.domain=*.bank.com ssl.forward_proxy(no)
category="Financial Services" ssl.forward_proxy(no)
category="Health and Medicine" ssl.forward_proxy(no)
<SSL>
; Запрет устаревших версий TLS
client.connection.negotiated_ssl_version=TLSv1.0 deny
client.connection.negotiated_ssl_version=TLSv1.1 deny
; Минимальная версия TLS
ssl.min_version(TLSv1.2)
; Блокировка QUIC, принуждение к HTTP/2
ssl.quic(deny)
http2.client.accept(yes)
; Блокировка ECH и DoT
ssl.ech(block)
ssl.dns_over_tls(deny)