TLS証明書エラーの対処法|システム時刻のずれ・SNI設定ミスを確認

証明書エラーやTLSハンドシェイク失敗が起きたら、端末の時刻、SNIと偽装ドメインの一致、allowInsecure、フィンガープリントを順に確認しましょう。

この記事の要点

v2rayN、v2rayNG、v2flyNGの接続時に発生する証明書検証エラーやTLSハンドシェイクの中断が対象です。まずログから時刻・ドメイン・証明書チェーンの問題を切り分け、ノードの接続先、SNI、トランスポート層のHostを確認します。通常のTLSとREALITYは分けて調べましょう。一度に変更する項目は1つに絞り、証明書検証は有効のまま、実際のリクエストで接続を確認します。

1. まずログを確認:証明書エラーはポート接続エラーとは限らない

TLSハンドシェイクはトランスポート接続の確立後に行われます。TCP接続に成功しても、接続先ポートが応答したことしか分からず、証明書の信頼性やドメインの一致、プロキシ認証の成功までは確認できません。v2rayNのTCPingでは応答があるのに、実際の接続テストに失敗することもあります。矛盾ではないため、ローカルのプロキシポートを何度も切り替えないでください。

クライアント名とバージョン、実際に動作しているコアのバージョン、ノードのセキュリティ方式、失敗した時刻を記録します。バックグラウンドでの連続テストを止め、1つのノードで接続を1回だけ試し、ログから同じ時刻に発生した最も内側のエラーを探してください。外側に表示される failed to find an available destination は概要にすぎません。その後に記録された具体的な原因も確認しましょう。

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

原因:端末の時刻が証明書の有効期間から外れているか、サーバーの証明書が実際に期限切れになっています。対処:まず端末の時刻を同期し、次に証明書の有効期間を確認します。時刻が正しいのに解決しない場合は、サーバー側で証明書を更新するか、証明書の設定を修正してください。

エラー:x509: certificate signed by unknown authority

原因:証明書チェーンを検証できません。中間証明書の不足、自己署名証明書、ネットワーク上での証明書の差し替えなどが考えられます。対処:証明書の発行者とチェーン全体を確認し、検証を安易に無効にしないでください。

エラー:remote error: tls: handshake failure

原因:接続先がハンドシェイクを拒否しています。SNI、プロトコルのバージョン、クライアント証明書の要否、サーバー側のポリシーなどが関係している可能性があります。対処:サーバーが要求するセキュリティ方式とSNIを確認し、サーバーログも参照してください。このエラーだけで証明書の期限切れと判断することはできません。

2. システム時刻を同期:日付・タイムゾーン・証明書の有効期間を確認

証明書には notBefore と notAfter の時刻が記録されています。検証に使われるのはシステム時計が示す絶対時刻で、タスクバーに表示される時刻だけではありません。絶対時刻が正しいままタイムゾーンだけを変更しても、通常は証明書エラーになりません。一方、現地時刻を別のタイムゾーンの時刻に手動で合わせると、数時間のずれが生じることがあります。

  1. 日付を確認

    まず年・月・日が正しいか確認します。端末を長期間電源オフにした後や、スナップショットの復元後、マザーボードの時計に問題がある場合、日付が過去に戻っていることがあります。分だけを調整して近い時刻に合わせないでください。

  2. パソコンの時刻を同期

    Windows 11では「設定」→「時刻と言語」→「日付と時刻」を開き、「時刻を自動的に設定する」を有効にします。「タイムゾーン」を確認してから「今すぐ同期」をクリックしてください。macOSでは「システム設定」→「一般」→「日付と時刻」を開き、日付と時刻の自動設定を有効にします。

  3. Androidの時刻を同期

    Androidでは通常、「設定」→「システム」→「日付と時刻」から、「時刻を自動設定」とタイムゾーンの自動設定を有効にできます。項目名はシステムによって異なる場合があります。設定内で「日付と時刻」を検索してください。

  4. 再接続して結果を記録

    同期が完了したことを確認してから、クライアントを再起動して接続します。それでも期限切れのエラーが出る場合は、エラーに表示された現在時刻と証明書の有効期間を記録し、ノードの管理者にサーバーが実際に提供している証明書を確認してもらいましょう。

Windowsでは、ターミナルで w32tm /query /status を実行すると時刻同期の状態を確認できます。同期コマンド w32tm /resync の実行には通常、管理者権限が必要で、Windows Timeサービスも動作している必要があります。コマンドが失敗した場合は、サービスとネットワークを確認してください。コマンドを実行しただけで同期済みとは限りません。Linuxでは timedatectl status でシステム時計と時刻同期サービスの状態を確認できます。有効化の方法はディストリビューションによって異なります。

結論:時刻が正しいのに期限切れならサーバーを確認

同期が完了し、エラーに表示された現在の日付も正しければ、端末の時計を何度も調整するのはやめましょう。管理者に証明書の更新状況、サービスの再読み込み、接続先ごとに古い証明書が残っていないかを確認してもらってください。

3. SNI・接続先・Host:3つの項目を個別に確認

SNIはTLS ClientHelloで接続先のホスト名を示す拡張です。クライアント設定の serverName は通常、ハンドシェイクに使う名前と証明書名の検証に使われますが、具体的な動作はコアによって異なります。サーバー側の指定に合致し、証明書のSANに含まれるドメインを設定してください。「偽装ドメイン」は共通のプロトコル項目名ではありません。提供元に、それがSNI、WebSocketのHost、その他のトランスポート設定のどれを指すのか確認しましょう。

項目役割確認ポイント
接続先とポート実際に接続するサーバーの入口を指定ドメイン名またはIPアドレスを指定。ポートはノードの設定に従う
SNI / serverNameTLSハンドシェイク名。通常は証明書名の検証にも使用ドメイン名のみを入力。スキーム、パス、ポートは付けない
WebSocket HostWebSocketハンドシェイクで使うHTTPのHostヘッダーリバースプロキシまたは上流サイトのルーティング設定に合わせる
WebSocket pathWebSocketのリクエストパス先頭のスラッシュを残す。パスの誤りは通常、証明書名の不一致とは別問題

接続先にIPアドレス、SNIにドメイン名を設定するのは正常な構成です。たとえばIPアドレスに直接接続しながら、ドメイン名を使ってTLSの名前を検証できます。反対に、SNIを削除してIPアドレスで検証すると、証明書にドメイン名しか含まれていない場合、cannot validate certificate ... because it doesn't contain any IP SANs が発生することがあります。「接続先とSNIが異なる」だけで誤設定と判断しないでください。

以下は通常のTLSの部分的な設定例で、接続可能な完全なノード設定ではありません。REALITYにも適用できません。実際のノードで設定されているトランスポートの種類は変更しないでください。この例では接続先、認証情報、その他のアウトバウンド設定を省略しています。

{
  "streamSettings": {
    "network": "tcp",
    "security": "tls",
    "tlsSettings": {
      "serverName": "example.com",
      "allowInsecure": false
    }
  }
}

4. allowInsecure:証明書の修正には使えない

allowInsecure を true にすると、通常のサーバー証明書検証がスキップされます。画面上の「安全でない接続を許可」や「証明書の検証をスキップ」は、通常この動作に該当します。TLS暗号化が行われる場合でも、通常の証明書チェーンや名前の検証で接続先の正当性を確認できなくなります。互換性を高めるための万能な設定ではありません。

症状:検証を無効にすると接続できる

原因:問題はネットワーク品質ではなく、証明書の有効期間、ドメイン名の一致、信頼チェーンにある可能性があります。対処:検証を有効に戻し、該当する証明書の問題を1つずつ修正してください。この結果だけで接続先の正当性が確認できたとはいえません。

症状:検証を無効にしてもハンドシェイクに失敗する

原因:証明書の検証より前の段階で問題が起きている可能性があります。たとえば、ポートがTLSサービスではない、サーバーがSNIを拒否している、セキュリティ方式の設定が誤っているなどです。対処:アドレス、ポート、ハンドシェイク設定を確認し、安全性を下げる設定を追加しないでください。

5. フィンガープリントとREALITY:実際のコアに合わせて切り分ける

クライアントのフィンガープリントはTLSハンドシェイクの特徴を示すもので、証明書のドメイン名でも検証をスキップする設定でもありません。対応機能を備えたXray設定では、fingerprint に chrome など、コアがサポートする値を指定できます。変更しても期限切れの証明書は有効にならず、SANにないドメインが自動的に追加されることもありません。

設定の種類優先して確認する項目混同しない項目
通常のTLS端末の時刻、serverName、証明書の有効期間、証明書チェーン全体REALITYの公開鍵パラメーターを証明書設定の代わりに使わない
REALITYserverName、サーバーの公開鍵、shortId、フィンガープリント、サーバー側の指定通常のTLSと同じように証明書検証を無効にしない
TLSを使用しないノードまず、エラーがサブスクリプションの更新、接続テストの対象、または別の接続から発生していないか確認元のノードにTLSを安易に追加しない

v2rayNGはXrayコア、v2flyNGはV2Flyコアを使用します。機能や設定項目をそのまま流用することはできません。v2rayNでは、対象ノードが実際に使っているコアを確認してください。REALITYやXTLS Visionを使う場合は、選択したコアが対応していることを先に確認します。リンクをインポートできても、すべてのパラメーターが反映されているとは限りません。

6. ハンドシェイクツールで切り分け:ポート・証明書チェーン・サーバーを確認

OpenSSLがインストール済みの場合、通常のTLS接続先の証明書を直接確認できます。以下のコマンドにある example.com は形式例です。実行前に、実際の接続先とサーバーが要求するSNIに置き換えてください。接続ポートもノードの設定に従います。このテストで確認できるのはTLS層のみで、VMessやVLESSの認証は検証されません。

openssl s_client -connect example.com:443 -servername example.com -showcerts -verify_hostname example.com -verify_return_error
443
TLS接続先のポート例。すべてのノードで共通の値ではありません
TLS 1.2
一般的なネゴシエーション対象のバージョン。双方が対応している必要があります
TLS 1.3
もう1つの一般的なネゴシエーション対象のバージョン。フィンガープリント名ではありません

結論:ツールでの成功は、そのTLSテストが成功したことを示すだけ

証明書の検証に成功してもプロキシが使えない場合は、トランスポート経路、認証パラメーター、サーバー側のインバウンド設定を確認します。正しいことを確認済みのSNIを変更し続けたり、ハンドシェイク後の失敗をすべて証明書の問題と決めつけたりしないでください。

7. 修正後の確認とよくある質問

変更するたびにノードを保存してから接続し直してください。既存の長時間接続には新しい設定がすぐ反映されないことがあります。「コアが正常に起動 → ノードのハンドシェイク成功 → 実際のリクエストが利用可能」の順で確認します。クライアントログに証明書エラーがなくなったのにブラウザーで問題が続く場合は、システムプロキシ、アプリのプロキシ設定、ルーティングルールを確認してください。TLS設定全体を再び調べ直す必要はありません。

  1. 時刻の自動同期が成功し、端末を再起動した後も日付が正しいことを確認します。
  2. SNIがサーバーの指定と一致し、証明書検証が有効で、トランスポート層のHostとパスが誤って変更されていないことを確認します。
  3. 修正したノードを選び、実際の接続テストを1回行ってから、プロキシを正しく設定したアプリで対象サイトにアクセスします。
  4. 修正した項目と結果を記録します。サブスクリプションの設定を使っている場合は提供元に元データの修正を依頼し、次回の更新でローカルの変更が上書きされないようにしてください。
サブスクリプションの更新時に証明書エラーが出ます。ノードのSNIに問題がありますか?

必ずしもそうではありません。サブスクリプションの取得では、クライアントがサブスクリプションURLにHTTPSで接続し、サブスクリプションサイトの証明書を検証します。通常、ノード編集画面のSNIは使いません。まずエラーが「サブスクリプションの更新」と「ノードへの接続」のどちらで起きたかを確認し、該当するドメイン、システム時刻、証明書チェーンを調べてください。

同じノードが別の端末では使えます。サーバー側の問題を除外できますか?

完全には除外できません。2台の端末で接続先の入口、信頼ストア、コア、時刻設定が異なる場合があります。まず実際の接続先、SNI、証明書の発行者と有効期限を比べ、設定を1項目ずつ確認してください。システム設定を一式そのままコピーしないでください。

ブラウザーでは偽装ドメインを開けるのに、クライアントでは失敗するのはなぜですか?

ブラウザーは別のアドレスに接続している場合があり、異なる信頼ストアを使ったり、別のトランスポート経路を通ったりすることもあります。ページが開けたことから分かるのは、そのWebリクエストが成功したことだけです。クライアントではノードに指定されたアドレス、ポート、SNI、トランスポート設定、認証パラメーターを使って接続する必要があります。

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