TLS証明書エラーの対処法

V2Ray接続時のx509エラーやTLSハンドシェイク失敗を解説。システム時刻、SNIとホスト名、証明書チェーンを確認する手順を紹介します。

この記事の概要

v2rayN、v2rayNG、v2flyNGで通常のTLSを使うノードが対象です。まず接続ログから証明書エラーを確認し、システム時刻、TLSのserverName/SNI、サーバー証明書チェーンの順に調べます。一度に変更するのは1項目だけにして再接続すれば、端末側の設定ミスか、ノードの管理者による対応が必要かを切り分けられます。REALITYを使うノードは個別のパラメーターを確認し、通常の証明書チェーンの修正手順をそのまま適用しないでください。

1. ログから証明書エラーと接続失敗を見分ける

「TLSハンドシェイク失敗」は結果を示すもので、具体的な原因ではありません。まずv2rayNのメイン画面下部にあるログ欄で、直近の接続に関するエラー全文を確認します。ログ欄が折りたたまれている場合は、該当パネルを開いてください。バージョンによって画面上の位置は異なりますが、ブラウザーに表示された「接続がリセットされました」だけでなく、x509、tls、certificateを含むコアのログを確認してください。

ノードを1つ選び、接続時刻を記録して、リクエストを1回だけ送信します。以下はよくある英語のエラー例です。実際のログにはコアのモジュール名や接続先、詳細な原因が追加される場合があります。ログを共有する際は、サブスクリプションURL、ユーザー識別情報、アクセス先に含まれる機密情報を削除してください。

エラー:x509: certificate has expired or is not yet valid

原因と対処:端末の現在時刻が証明書の有効期間外か、サーバーの証明書が実際に期限切れです。まず端末の時刻を同期し、証明書の有効期間を確認してください。

エラー:x509: certificate is valid for example.com, not www.example.com

原因と対処:検証に使われたホスト名が証明書の対象外です。ノードで指定されたSNIと証明書のSANを確認し、名前が似ているだけで置き換えないでください。

エラー:x509: certificate signed by unknown authority

原因と対処:証明書チェーンが信頼されたルート証明書までつながっていません。中間証明書の不足や、信頼されていない認証局が原因の可能性があります。サーバーの証明書チェーン全体と、端末の信頼ストアを確認してください。

2. システム時刻を同期して証明書の期限を確認する

TLSでは現在時刻を証明書のnotBefore、notAfterと照合します。停電後に時計がリセットされた、仮想マシンを古いスナップショットに戻した、日付を手動で変更したなどの理由で、有効な証明書が「まだ有効ではない」または「期限切れ」と判定されることがあります。タスクバーの時刻だけでなく、年月日と分まで確認してください。

  1. 日付と時刻を確認

    Windows 11では「設定」→「時刻と言語」→「日付と時刻」を開き、日付、時刻、現在のタイムゾーンを確認します。時刻が正しく同期されている別の端末とも比較してください。

  2. 時刻を今すぐ同期

    「時刻を自動的に設定する」を有効にし、「その他の設定」で「今すぐ同期」をクリックします。同期に失敗する場合は、まず通常のネットワーク接続に戻してから、Windowsの時刻サービスを再試行してください。

  3. 再接続

    クライアントに戻り、現在のノードを再度有効にして新しいリクエストを送信します。同期前に記録された古いエラーではなく、新しいログを確認してください。

  4. 証明書の有効期間を確認

    時刻が正確なのに期限切れと表示される場合は、サーバーから実際に返された証明書の有効期間を確認します。現在時刻が本当にnotAfterを過ぎている場合は、管理者が証明書を更新し、TLSサービスに再読み込みさせる必要があります。

Androidでは、システムの「設定」で「日付と時刻」を検索し、自動設定を有効にします。メニューの位置はOSによって異なります。タイムゾーンは時刻の表示方法に影響しますが、基準となる時刻が正しければ、タイムゾーンを変えただけで証明書エラーが発生することは通常ありません。反対に、時計を過去に戻すと一時的に接続できても、ほかのサービスに影響するため修正方法として使わないでください。

443 / TCP
TLSでよく使われるサーバーポート(実際のポートはノード設定を確認)
123 / UDP
NTPの時刻同期でよく使われるポート(プロキシ用ではありません)

時刻同期とノードへの接続は別の通信経路です。ノードが443番ポートを使っていても、時刻同期が同じポートを使うとは限りません。同期サービスのネットワーク設定を調べる場合は、実際に使われている時刻サーバーとプロトコルを確認し、端末の受信ポートをむやみに開放しないでください。

3. SNI、サーバーアドレス、Hostを確認する

ノードの「アドレス」、TLSの「サーバー名」、WebSocketの「Host」はそれぞれ別の項目です。サーバーアドレスは接続先を指定し、SNIはTLSハンドシェイクでサーバーにサイトと証明書を選択させます。HTTPのHostやHTTP/2のauthorityはアプリケーション層のリクエストで使われます。Hostを変更しても、証明書検証に使う名前は自動では修正されません。

項目役割確認ポイント
アドレス、address接続先サーバーを指定ドメイン名またはIPアドレスを指定。ポートは別に入力
serverName、SNITLSサーバー名を送信し、通常は名前の検証にも使用管理者が指定した、証明書の対象となるホスト名を使用
Hostトランスポート層で使うHTTPリクエストのホスト名サーバー側のWebSocketまたはリバースプロキシ設定に合わせる
SAN証明書で検証できるドメイン名またはIPアドレスの一覧証明書の名前照合ルールに合致していること

v2rayNのメイン画面でノードをダブルクリックし、サーバー編集画面でTLSが選択されていることを確認してから、「SNI」またはサーバー名にあたる項目を確認します。バージョンによって項目名が異なるため、serverNameの意味と照らし合わせてください。v2rayNGではノードカードの編集画面を開き、TLS設定のSNIを確認します。ホスト名の欄にhttps://、:443、URLのパスを含めないでください。

結論:名前が一致しない場合は、DNSを変える前にSNIを確認

ログに「証明書はAに有効だが、現在はBを検証している」と明記されている場合は、まずBの設定が正しいか確認してください。名前の設定が正しいのに誤ったサーバーや証明書に接続している場合は、名前解決の結果、リバースプロキシ、サイトの振り分けを順に調べます。

4. 証明書チェーンとサーバーから返される証明書を確認する

「unknown authority」は「証明書の期限切れ」と同じではありません。ドメイン証明書が有効でも、中間証明書が送信されないと、クライアントが信頼チェーンを構築できないことがあります。ブラウザーで開けても、この問題がないとは限りません。ブラウザーとプロキシコアでは、信頼ストア、キャッシュ、中間証明書の取得方法が異なる場合があります。

OpenSSLがインストールされている場合は、次のコマンドでサーバーを確認できます。ここでのexample.comは説明用の予約ドメインで、このサイトのノードではありません。実行前にコマンド内のドメイン名とポートを実際の値に変更してください。接続先とSNIが異なる場合、-connectには実際の接続先を、-servernameと-verify_hostnameにはTLSで使用するホスト名を指定します。

openssl s_client -connect example.com:443 -servername example.com -showcerts -verify_hostname example.com -verify_return_error

管理者は、実際にTLSを終端するサービスに完全な証明書チェーンを設定してください。たとえば前段にリバースプロキシがある場合は、バックエンドのコアのディレクトリだけでなく、リバースプロキシが読み込む証明書を更新します。証明書の更新後は関連サービスを再読み込みし、外部から再度ハンドシェイクして新しい証明書が返されることを確認してください。

5. 修正後は同じ条件で再テストする

ノードの変更、SNIの修正、DNSの切り替え、Tunの有効化を同時に行うと、結果を比較できなくなります。同じノードとテスト先を使い、変更は一度に1つだけにしてください。次の手順なら、設定の修正による改善か、たまたま別の経路で接続できただけなのかを見分けられます。

  1. 修正前の状態を記録:ノードのアドレス、ポート、TLSの種類、SNI、エラー発生時刻を記録します。ノードの認証情報は公開しないでください。
  2. 時刻同期後に再テスト:ノードの設定は変えず、システム時刻だけを同期します。有効期間のエラーが解消したら、名前や信頼チェーンに関するエラーが残っていないか確認してください。
  3. SNI修正後に再テスト:管理者から指定された値にSNIを修正して再接続し、新しいログで検証対象の名前が想定どおりか確認します。
  4. ネットワークを変えて比較:同じ端末とノードを別のネットワークで試します。特定のネットワークだけ異なる証明書が返される場合は、通信の遮断、名前解決、中間機器を確認してください。
  5. 修正が維持されるか確認:サブスクリプションを更新し、クライアントを再起動してからもう一度テストします。修正値がサブスクリプションで上書きされていないか、サーバーが古い証明書を返し続けていないか確認してください。

正しい時刻とSNIを設定しても証明書の期限切れやチェーン不備が表示される場合、クライアント側で解決できる範囲は限られます。管理者には、エラーの原文、テスト時刻、クライアントとコアのバージョン、接続ポート、想定するSNIを伝えると、「ノードが使えない」というスクリーンショットだけより原因を特定しやすくなります。ネットワークやコアに関する問題はトラブルシューティングガイドもご覧ください。

6. よくある質問:検証のスキップとハンドシェイクの中断

allowInsecureや「証明書の検証をスキップ」を有効にすれば解決しますか?

証明書による認証を回避するだけで、時刻、ドメイン名、証明書チェーンの問題は解決しません。接続できるようになっても、証明書の検証が障害に関係している可能性が分かるだけで、正しいサーバーに接続できた証明にはなりません。検証は有効のままにし、ログを見て原因を修正してください。この設定を常用しないでください。

TLS handshake failureだけが表示され、x509がない場合は何を確認すればよいですか?

まず、クライアントのTLSの種類がサーバーと一致しているか確認し、SNI、ALPN、トランスポート方式を順に確認します。サーバーが証明書を送信する前に接続を切断している可能性もあります。サーバーのログも確認し、システム時刻の問題と決めつけたり、TLSのセキュリティ設定をすぐに下げたりしないでください。

ブラウザーではノードのドメインにアクセスできるのに、クライアントでエラーになるのはなぜですか?

ブラウザーが接続したアドレス、ポート、名前解決の結果、SNIはノードの設定と異なる場合があり、ブラウザーが中間証明書をキャッシュしていることもあります。同じ接続先と同じ名前を使って比較してください。ドメインのトップページが開けても、そのブラウザーのリクエストが成功したことを示すだけで、ノードのTLS設定が正しいとは限りません。

REALITYノードでも通常の証明書チェーンを確認する必要がありますか?

REALITYは通常のTLSとは設定や検証の仕組みが異なります。まずトランスポートのセキュリティ方式を確認し、サーバーが指定するserverName、公鍵、shortIdなどのパラメーターを確認してください。通常のTLS向けの証明書更新手順をそのままREALITYに適用したり、エラーを消すために安易にTLSへ変更したりしないでください。

クライアントをダウンロード