6 分で読了 #networking #TLSとPKI
このページの目次

mTLS と双方向認証

サーバーが「自分自身」を証明するには TLS 証明書を使用し、クライアントが「自分自身」を証明するには mTLS を使用します。双方が証明書を表示し、検証し合います。ゼロトラストアーキテクチャにおいて、mTLS はサービス間通信のアイデンティティの基盤ですが、証明書の配布とローテーションの運用コストが主な障壁となっています。

概要

標準的な TLS はサーバーのアイデンティティのみを検証します。mTLS(mutual TLS)はクライアント証明書の検証を追加します。サーバーはハンドシェイク中に CertificateRequest を送信し、クライアントは証明書を提示する必要があります。これにより、IP やネットワーク位置に依存せずに双方向でアイデンティティを証明する「ゼロトラスト」ネットワークの基盤が実現します。SPIFFE はサービスアイデンティティを標準化し、Istio/Linkerd は mTLS を使用して service mesh 内の各 pod 間の通信を自動的に暗号化します。独自 CA の構築は mTLS の必須条件です。証明書の発行と失効を完全に制御する必要があります。

TLS vs mTLS: ハンドシェイクの違い

TLS vs mTLS: 単方向の信頼から双方向の相互検証へ

TLS サーバーが証明書を提供 クライアントがサーバーを検証 → 単方向の信頼

mTLS サーバー証明書 + CertificateRequest クライアントも証明書を提供する必要あり → 双方向の相互検証

TLS 1.3 mTLS 簡略化ハンドシェイク

Client → Server: ClientHello + key_share Server → Client: ServerHello + key_share + {EncryptedExtensions + CertificateRequest + ...} Client → Server: {Certificate + CertificateVerify + Finished}

↑ 標準的な TLS 1.3 に加え、Certificate + CertificateVerify(クライアント提供)が追加される

CertificateRequest に含まれる内容: certificate_authorities(空=任意の CA) signature_algorithms · certificate_extensions(例: SPIFFE OID)

プライベート CA の管理

mTLS をデプロイする最初のステップ: プライベート CA を構築する

# 1. ルート CA の作成(オフライン、ハードウェアセキュリティモジュールまたはエアギャップ環境のマシン):
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out ca.key
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
  -subj "/CN=Private CA" -extensions v3_ca

# 2. サーバー/クライアント証明書の発行:
openssl genpkey -algorithm EC -out server.key
openssl req -new -key server.key -out server.csr \
  -subj "/CN=metrics-agent-001"
openssl x509 -req -days 90 -in server.csr -CA ca.crt -CAkey ca.key \
  -out server.crt -set_serial 0x01

# 3. 失効(侵害された証明書がある場合):
openssl ca -revoke server.crt -keyfile ca.key -cert ca.crt

SPIFFE

mTLS の証明書 CN/SAN に SPIFFE ID を含めるための標準化されたサービスアイデンティティフレームワーク:

SPIFFE ID: spiffe://trust-domain/path
  trust-domain: 組織/クラスターの識別子
  path: サービス/インスタンスの識別子

例: spiffe://liz6.com/metrics-agent/li-cn-node-2

X.509 証明書内:
  SAN URI: spiffe://liz6.com/metrics-agent/li-cn-node-2
  → URI SAN によって検証可能(CN のみではない)

SVID (SPIFFE Verifiable Identity Document):
  = X.509 証明書(短期間: デフォルト 1 時間)+ 秘密鍵
  → SPIRE agent によって自動的にローテーションされる

Service Mesh (Istio/Linkerd)

Service Mesh における mTLS: アプリケーションコードは意識しない control plane (istiod / linkerd-identity) 短期証明書の発行 · 自動ローテーション Pod A sidecar proxy Envoy / linkerd-proxy mTLS sidecar proxy Envoy / linkerd-proxy Pod B アプリケーションコードは mTLS の存在を知る必要がない 各 sidecar は control plane から短期証明書を取得し、自動ローテーション、自動 mTLS を実行する

比較

mTLSAPI KeyJWT (OAuth2)
トランスポート層L4 (TLS ハンドシェイク段階)L7 (HTTP ヘッダー)L7 (HTTP ヘッダー)
アイデンティティの紐付け証明書 (CN/SAN + 有効期限)key 文字列claims (sub, exp, aud)
ローテーションCA による再発行新規 key の生成短命 TTL + refresh
失効CRL / OCSP失効 DB による失効短命 TTL(自然失効)
ミドルウェアのオーバーヘッド低い (TLS そのもの)中程度 (key の検証)中程度 (JWT の検証)
ゼロトラスト互換性✓ (SPIFFE)△ (トークン署名に PKI が必要)

参考

  • RFC: 8446, 8705
  • SPIFFE: spiffe.io, github.com/spiffe/spire
  • Istio: istio.io/latest/docs/concepts/security/#mutual-tls-authentication

Keywords: mTLS, client certificate, SPIFFE, SPIRE, service mesh, private CA, certificate revocation, SVID