Gymterview
middle

Что такое mTLS и зачем нужна двусторонняя аутентификация?

mTLS (Mutual TLS) — расширение TLS, при котором не только клиент проверяет сертификат сервера, но и сервер проверяет сертификат клиента. Обе стороны аутентифицируют друг друга на уровне транспорта.

Отличие от обычного TLS

Параметр TLS mTLS
Сервер предъявляет сертификат Да Да
Клиент предъявляет сертификат Нет Да
Аутентификация сервера Да Да
Аутентификация клиента Нет (другие механизмы) Да (на уровне TLS)

Процесс mTLS Handshake

Пример
Клиент                                          Сервер
   │──── ClientHello ──────────────────────────────>│
   │<─── ServerHello + Certificate ─────────────────│
   │<─── CertificateRequest ───────────────────────│  <- сервер запрашивает
   │<─── ServerHelloDone ──────────────────────────│     сертификат клиента
   │──── Certificate (сертификат клиента) ─────────>│  <- клиент предъявляет
   │──── ClientKeyExchange ────────────────────────>│     свой сертификат
   │──── CertificateVerify ────────────────────────>│
   │──── Finished ─────────────────────────────────>│
   │<─── Finished ─────────────────────────────────│

Когда используется mTLS

  • Межсервисное взаимодействие — микросервисы аутентифицируют друг друга
  • Банковские интеграции — взаимодействие с платёжными системами (SWIFT, НСПК)
  • API для партнёров — контрагенты подключаются с использованием клиентских сертификатов
  • Service Mesh — Istio/Linkerd автоматически обеспечивают mTLS между подами

Настройка mTLS в Spring Boot

Пример
server:
  ssl:
    key-store: classpath:server-keystore.p12
    key-store-password: ${SSL_KEYSTORE_PASSWORD}
    key-store-type: PKCS12
    trust-store: classpath:truststore.jks
    trust-store-password: ${SSL_TRUSTSTORE_PASSWORD}
    client-auth: need  # need = обязательно, want = опционально

Настройка RestTemplate для mTLS

Пример Java-кода
@Bean
public RestTemplate restTemplate() throws Exception {
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    keyStore.load(new FileInputStream("client-keystore.p12"),
                  "password".toCharArray());

    KeyStore trustStore = KeyStore.getInstance("JKS");
    trustStore.load(new FileInputStream("truststore.jks"),
                    "password".toCharArray());

    SSLContext sslContext = SSLContextBuilder.create()
        .loadKeyMaterial(keyStore, "password".toCharArray())
        .loadTrustMaterial(trustStore, null)
        .build();

    HttpClient httpClient = HttpClients.custom()
        .setSSLContext(sslContext)
        .build();

    return new RestTemplateBuilder()
        .requestFactory(() -> new HttpComponentsClientHttpRequestFactory(httpClient))
        .build();
}

mTLS является стандартом для критичных интеграций, так как обеспечивает взаимную аутентификацию сторон на уровне транспорта ещё до обработки бизнес-логики.

На собеседовании: интервьюер хочет услышать разницу между TLS и mTLS и знание реальных сценариев применения (межсервисное взаимодействие, Service Mesh). Частая ошибка — не упомянуть client-auth: need в Spring Boot и не объяснить, зачем нужен TrustStore.