mTLS
mTLS (Mutual TLS) — расширение TLS где не только сервер, но и клиент предъявляет свой сертификат. Гарантирует что обе стороны — те, за кого себя выдают. Стандарт для service-to-service внутри Kubernetes, микросервисов, API-gateway'ев, платёжных сетей, IoT.
Как отличается от обычного TLS
Обычный TLS:
Client → ClientHello
Server → ServerHello, Certificate, ...
Server ← аутентифицирован по своему серверному серту
Client ← остаётся анонимным (или проверяется отдельно паролем/токеном)
mTLS:
Client → ClientHello
Server → ServerHello, Certificate, CertificateRequest, ...
Client → Certificate (свой!), CertificateVerify, ...
Обе стороны проверены криптографически
Handshake TLS 1.3 с mTLS
- Client →
ClientHello. - Server →
ServerHello,EncryptedExtensions,CertificateRequest,Certificate,CertificateVerify,Finished. - Client проверяет серверный сертификат.
- Client →
Certificate(свой сертификат с private-key),CertificateVerify(подпись доказывающая владение ключом),Finished. - Server проверяет клиентский сертификат и подпись.
- Обмен данными.
Аутентификация против авторизации
mTLS даёт только аутентификацию — «этот клиент имеет ключ соответствующий CN=service-A». Что разрешено service-A делать — уже логика приложения (или policy engine типа OPA, Istio AuthorizationPolicy).
Где используется
- Service Mesh (Istio, Linkerd, Consul Connect) — все pod'ы получают сертификаты, весь трафик между ними mTLS.
- Kubernetes API — kubelet/kube-apiserver говорят по mTLS.
- etcd — cluster members mTLS.
- Financial APIs — Visa, MasterCard, банковские шлюзы часто требуют клиентский серт.
- IoT — устройство идентифицируется сертификатом, не логин/паролем.
- Enterprise VPN — WireGuard, OpenVPN с certificate auth.
- Zero Trust Network Access (Cloudflare Access, BeyondCorp).
Настройка на nginx
server {
listen 443 ssl http2;
server_name api.example.com;
# Серверный серт
ssl_certificate /etc/nginx/certs/server.crt;
ssl_certificate_key /etc/nginx/certs/server.key;
# CA чтобы проверять клиентские серты
ssl_client_certificate /etc/nginx/certs/ca.crt;
ssl_verify_client on; # обязательно
# ssl_verify_client optional; # клиент может, но не обязан
ssl_verify_depth 2;
location / {
proxy_pass http://backend;
proxy_set_header X-Client-Cert-CN $ssl_client_s_dn;
proxy_set_header X-Client-Cert-Fingerprint $ssl_client_fingerprint;
}
}
curl с клиентским сертом
curl --cert client.crt --key client.key \
--cacert ca.crt \
https://api.example.com/v1/data
Генерация клиентского серта
# CA
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 \
-nodes -keyout ca.key -out ca.crt \
-subj "/CN=My CA"
# Клиентский CSR
openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr \
-subj "/CN=service-a"
# Подписать CA
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out client.crt -days 365 -sha256
PKI-инфраструктура
При масштабе mTLS нужен полноценный PKI:
- Root CA — offline, только для подписания intermediate.
- Intermediate CA — подписывает сертификаты клиентов.
- Автоматическая ротация — короткоживущие серты (несколько часов) через SPIFFE/SPIRE, cert-manager, Vault PKI.
- OCSP / CRL — отзыв сертов. Часто пропускают — короткий TTL решает.
SPIFFE / SPIRE
SPIFFE (Secure Production Identity Framework For Everyone) — стандарт идентичности для service mesh. Формат ID: spiffe://example.com/service-a.
SPIRE — reference implementation. Автоматически выдаёт короткие сертификаты (SVID) каждому workload'у. Ротирует, отзывает при завершении.
Плюсы / минусы
| Плюс | Минус | |
|---|---|---|
| Безопасность | Строгая криптоидентификация обоих концов | Утечка private-key = полное владение |
| Отсутствие shared secrets | Нет паролей/API-ключей | Управление ключами и PKI сложнее |
| Замена паролям | Нельзя «случайно запушить в git» текстом | Приложение должно уметь TLS-клиентские серты |
| Zero Trust | Каждое соединение — новая проверка | Overhead: handshake CPU |
| Аудит | По CN легко трекать какой сервис делал запрос | Ротация сертов операционная работа |
Не путать с
- TLS with client auth «Basic» — просто TLS + логин/пароль в приложении. Это НЕ mTLS.
- OAuth2 / OIDC — токены. Приложение аутентифицируется, не сессия.
- mTLS ≠ SNI — SNI это как клиент сообщает «я хочу этот хост», mTLS — как клиент доказывает кто он.