ゲームラグ白書 › L13 サーバー構成と運用
TLS証明書の期限切れ・設定ミス TLS certificate expiry / misconfiguration
原因ID in-cert · 主担当 インフラチーム・ネットワークインフラ · 副担当 インフラチーム・サーバーインフラ, ゲーム開発チーム・クライアント開発
図と実験のあるメインページでこのカードを開く →
ログイン・API・アップデートサーバーの証明書が期限切れになったり中間証明書が抜けていたりすると、その瞬間から新たに接続するクライアントのTLS接続が失敗します。
なぜ 証明書の有効期限が切れている、サーバーが中間証明書を含めずに送っている、またはユーザー端末の日付・時刻がずれている → すると クライアントが証明書の検証に失敗し、TLS接続を切断 → 画面では ログイン・アップデートの段階で接続不可・無限ロード、ショップなどHTTPSの機能だけ失敗。すでに接続していた人はたいてい問題なし
- 症状
- 接続不可・無限ロード, 不発・ロールバック
- 要因
- ストール
- 誰に起きるか
- サーバー全体, 特定の機能だけ, 自分だけ
- いつ
- 接続直後・メンテ明け, 特定の操作をしたとき
- 担当
- 主担当 インフラチーム・ネットワークインフラ · 副担当 インフラチーム・サーバーインフラ, ゲーム開発チーム・クライアント開発
- ゲーム開発チームの対応
- 証明書エラーをほかの接続失敗と区別できるエラーコードで記録して案内、日付のずれが原因なら端末の日付・時刻を自動設定にするよう案内、証明書ピンニング(pinning)を使うなら予備の鍵も一緒に組み込み、証明書の差し替え日程をインフラチームと合わせる。
- インフラチームの対応
- ネットワーク:ロードバランサー・CDNでTLSを終端する場合、マネージド証明書の自動更新の状態と残り日数のアラート(ACMではDaysToExpiry)、検証用DNSレコードの維持。サーバー機器・OS:サーバーでTLSを終端する場合、更新の自動化と更新後の設定の再読み込み、中間証明書まで含めたチェーンで設定、ログイン・API・アップデートの各アドレスについて残りの有効期間を外部から定期的に検査してアラート。
- 数値の目安
- Let’s Encryptの証明書は有効期間が90日で、60日ごとの更新が推奨されています。AWS Certificate Managerは、DNSで検証した証明書を期限の45日前に確認して自動更新します。自動更新が気づかれないまま失敗すると、ちょうど期限の時刻に新規接続が一斉にできなくなります。
- グラフでは
- 接続が一斉に切れる · ログイン成功数、TLSハンドシェイクのエラー数
- 確認箇所
- openssl s_client -connect HOST:443 -showcertsでサーバーが実際に送る証明書の一覧を確認し、各証明書の有効期限(notAfter)をopenssl x509 -noout -enddateで確認。ロードバランサーでTLSを終端しているなら、TLSネゴシエーションのエラー数(AWS ALB・NLBではClientTLSNegotiationErrorCount)とログイン成功数
- 該当する場合
- 有効期限が過ぎているか、サーバーが送った一覧に中間証明書が含まれておらず、エラーが増え始めた時刻が期限の時刻か証明書を差し替えた時刻と重なる
- 該当しない場合
- 証明書の一覧と有効期限が正常なのに一部のユーザーだけ失敗するなら、そのユーザー端末の日付・時刻か、古いOSのルート証明書リストを確認
- 確認手段
- インフラのツールで確認(ゲームコード不要)
- もっと詳しく
- 中間証明書が抜けた設定は、PCのブラウザで開くと問題なく見えることがあります。ブラウザはほかのサイトで受け取った中間証明書を覚えていて欠けた部分を補いますが、Androidアプリのようにその記憶を持たないクライアントは失敗します。有効期間も短くなりつつあります。Let’s Encryptはデフォルトの有効期間を2027年に64日、2028年に45日へ短縮する予定で、60日ごとに更新するよう固定した設定では、64日の証明書だと余裕が4日しかなく、45日の証明書では期限を過ぎてしまいます。AWS Certificate Managerも、インポートした証明書は自動更新せず、検証用のDNSレコードを消すと更新に失敗します。ログインできなくなる様子は「DNSの障害・遅延」と似ていますが、証明書の問題はサーバーのアドレスを解決した後のTLSハンドシェイクで失敗し、始まった時刻が期限の時刻や証明書を差し替えた時刻と重なります。
出典
- RFC 5280: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile IETF
証明書の有効期間はnotBeforeからnotAfterまで、パス検証ではチェーンの証明書ごとに現在時刻が有効期間内かを確認(検証する側の時計がずれていると失敗) - FAQ Let's Encrypt
デフォルトの証明書有効期間は90日、60日ごとの更新を推奨 - Decreasing Certificate Lifetimes to 45 Days Let's Encrypt
デフォルトの有効期間を2027年2月に64日、2028年2月に45日へ短縮、60日の固定間隔での更新では足りなくなるため、有効期間の約3分の2の時点での更新を推奨 - Renewal for domains validated by DNS AWS
期限の45日前に、AWSサービスで使用中かと検証用CNAMEレコードがあるかを確認して自動更新、検証できなければ期限の30・15・7・3・1日前に通知 - Managed certificate renewal in AWS Certificate Manager AWS
インポートした証明書とすでに期限切れの証明書は、自動更新の対象外 - Supported CloudWatch metrics AWS
DaysToExpiry:証明書の期限までの残り日数、期限まで1日2回発行 - Security with network protocols Android (Google)
サーバーが中間証明書を含めずに送ると、AndroidアプリはSSLHandshakeExceptionで失敗するが、PCのブラウザは保持している中間証明書で補うためエラーにならないことがある、openssl s_clientでサーバーが送るチェーンを確認 - Network security configuration Android (Google)
証明書ピンニングを使うなら、鍵の差し替え・CAの変更に備えて予備の鍵も組み込む必要があり、そうしないとアプリを更新するまで接続できなくなる - openssl-s_client OpenSSL
-showcerts:サーバーが送った証明書の一覧を送られた順のまま表示(検証済みのチェーンではない) - openssl-x509 OpenSSL
-enddate:証明書の有効期限(notAfter)を出力、-checkend:指定した秒数以内に期限が切れるかを検査 - CloudWatch metrics for your Application Load Balancer AWS
ClientTLSNegotiationErrorCount:クライアントがサーバー証明書の検証に失敗して接続を切った場合など、TLSセッションを確立できなかった接続の数 - CloudWatch metrics for your Network Load Balancer AWS
ClientTLSNegotiationErrorCount:クライアントとTLSリスナーの間のネゴシエーションに失敗したTLSハンドシェイクの数
あわせて読みたい原因
同じ層:L13 サーバー構成と運用
同じ症状(接続不可・無限ロード)を起こすほかの層の原因
図と実験のあるメインページでこのカードを見る