V2Ray TLSハンドシェイク失敗・証明書エラーの対処法|時刻・SNI・allowInsecure設定

V2RayのTLS証明書エラーを原因別に解説。端末の時刻ずれ、SNIとホスト名の不一致、証明書チェーンの不備を確認し、allowInsecureのリスクと正しい使い方を紹介します。

この記事の要点

v2rayNで通常のTLSノードに接続した際に、証明書の期限切れ、ホスト名の不一致、信頼されていない認証局などのエラーが出る場合に役立ちます。まず、サブスクリプションの取得エラーとノードのハンドシェイクエラーを切り分け、システム時刻、サーバー名、サーバー証明書チェーンの順に確認します。最後に、allowInsecureを無効のまま修正を確認する方法を説明します。REALITYを使用するノードでは、通常の証明書チェーンの手順ではなく、該当する認証パラメーターを確認してください。

サブスクリプションとノード接続のどちらで起きたエラーか確認

TLSエラーが出たら、まず発生した操作を記録します。「サブスクリプションを更新」をクリックした際のHTTPS証明書エラーは、通常、サブスクリプションURLへの接続で発生しています。ノードを選択してウェブページにアクセスした際にコアのログに記録されるハンドシェイクエラーは、プロキシノード側の問題である可能性があります。接続先のホスト名はそれぞれ異なるため、ノードのSNIを変更してもサブスクリプションサイトの証明書エラーは解消しません。

接続先アドレスの名前解決 TCP接続 TLSハンドシェイク 証明書の検証 プロトコル認証

通常のTLSプロキシ接続は、この流れで考えると分かりやすくなります。TCPポートに接続できても、確認できるのは応答するサービスがあることだけです。証明書が正しいこと、プロキシ認証に成功すること、ウェブページを開けることまでは保証されません。VMessとVLESSはプロキシプロトコルで、TLSは組み合わせて使える通信の保護層です。すべてのノードがTLSを使うわけではありません。

エラーメッセージから確認箇所を絞り込む

コアやバージョンによっては、エラーの外側に接続情報が付加されることがあります。外側の「接続失敗」だけを見てクライアントを繰り返し再起動せず、内側にあるx509やtlsの原因を確認してください。以下はよくある英語のエラー例です。実際のログには証明書の有効期間や具体的なホスト名が付くことがあります。

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

原因:端末の時刻が証明書の有効期間から外れています。端末の時計がずれている場合も、サーバー証明書が期限切れの場合もあります。

対処法:まずシステム時刻を同期し、証明書の有効開始日時と有効期限を確認します。期限切れが確認できた場合は、サーバー管理者が証明書を更新してサービスを再読み込みしてください。

エラー:x509: certificate signed by unknown authority

原因:信頼できるルート証明書までの証明書チェーンを構築できません。中間証明書の不足、自己署名証明書、信頼ストアの異常などが原因として考えられます。

対処法:まずサーバーが送信する証明書チェーンを確認し、次に端末の信頼ストアを確認します。入手元が不明なルート証明書はインストールしないでください。

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

原因:検証に使われたサーバー名が、証明書で許可されたホスト名の範囲に含まれていません。ここに示したホスト名は形式の例です。

対処法:ノードの提供元が指定したSNIと証明書のSANを確認してください。wwwを安易に追加したり削除したりしないでください。

エラー:remote error: tls: handshake failure

原因:接続先がハンドシェイクを終了しています。SNI、TLSパラメーター、クライアント認証の要件、サーバー側のポリシーなどが関係する可能性があり、証明書が信頼されていないことを直接示すものではありません。

対処法:接続パラメーターを確認し、サーバー側のログと照らし合わせて原因を特定します。検証をスキップする設定だけでは、接続先がハンドシェイクを拒否する問題は通常解決しません。

システム時刻を合わせてから証明書の期限を確認

TLSの検証では、実際の時刻と証明書の有効期間を照合します。タスクバーに表示されるタイムゾーンを変更するだけでは、端末の時計が正しく設定されたとは限りません。一方、表示されるタイムゾーンが異なるだけで証明書エラーになるわけでもありません。スリープからの復帰、マザーボードの電池の異常、手動での日付変更などにより、時計がずれることがあります。

  1. 日付を確認

    Windows 11で「設定」→「時刻と言語」→「日付と時刻」を開き、まず年、月、日を確認します。特に年が誤っていないか注意してください。

  2. 時刻を同期

    「時刻を自動的に設定する」をオンにし、「その他の設定」の「今すぐ同期」をクリックします。同期に失敗した場合は、まずネットワークや時刻サービスの問題を解決してください。「自動設定」がオンであることだけで、同期済みとは判断できません。

  3. 接続を再試行

    v2rayNに戻り、対象ノードを再度有効にしてリクエストを送信します。古いエラーを修正後の結果と取り違えないよう、新しい時刻のログを確認してください。

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

    期限切れのエラーが続く場合は、証明書のnotBeforeとnotAfterを確認してください。端末の時刻が正しくても証明書の有効期間外であれば、サーバー管理者に証明書の更新を依頼します。

Android端末では、システム設定で「日付と時刻」を検索し、自動設定をオンにしてからv2rayNGまたはv2flyNGで再試行してください。メニューの位置は端末によって異なります。重要なのは、スイッチを切り替えることだけでなく、同期後の日付が正しいことを確認することです。証明書の有効期間内に収まるようシステムの日付を過去に戻す方法は、恒久的な解決策として使わないでください。

SNI、接続先アドレス、通信のHostを確認

SNIはTLSハンドシェイクでサーバーに通知する名前で、サーバーはその名前に応じて証明書を選択できます。通常のTLS設定にあるserverNameも、証明書検証の対象名を指定するために使われます。「偽装ドメイン」は意味が混同されやすい表現です。TLSのSNIを指す場合も、WebSocketのHostを指す場合もあるため、変更前に対象の項目を確認してください。

項目役割確認ポイント
サーバーアドレス接続先のリモートホストを指定ドメインまたはIPが正しい接続先を示しているか
サーバーポート接続先のリモートサービスを指定提供元の設定と一致しているか(例:443)
SNI / serverNameTLSで使用する名前と検証に影響接続先サービス名と証明書のSANが一致しているか
WebSocket HostHTTPリクエストの仮想ホストのルーティングに影響通常のTLS証明書検証を切り替える設定ではない
WebSocketパスサーバー側の通信入口と一致させるパスが誤っているとHTTPステータスコードエラーになることがある

v2rayNのメイン画面で対象ノードをダブルクリックし、ノード編集画面で「アドレス」「ポート」を確認してから、TLS欄のSNIと証明書検証のスキップ設定を確認します。項目名は画面のバージョンによって多少異なる場合があります。「設定」→「パラメーター設定」の全体設定を変更して、対象ノードの設定確認に代えることは避けてください。

接続先アドレスにIPを使う場合でも、SNIには提供元指定のドメイン名が必要なことがあります。IPで証明書を検証するには、そのIPアドレスを含むIP型のSANが証明書に必要です。ドメイン名だけを含む証明書では条件を満たしません。ワイルドカードにも制限があり、通常*.example.comはexample.comやa.b.example.comには適用されません。

注意:ウェブサイトのドメインを安易にSNIに設定しない

まずノードの提供元に指定されたサーバー名を確認し、証明書のSANと照合してください。ウェブサイトを開けるからといって、そのドメインをプロキシノードのSNIに使えるとは限りません。HTTP Hostが正しくても、TLSの名前検証の代わりにはなりません。

証明書チェーンとサーバーの実際の応答を確認

サーバーは通常、リーフ証明書と必要な中間証明書を送信し、ルート証明書はクライアントの信頼ストアから提供されます。リーフ証明書だけを設定しても動作する環境はありますが、別の端末では信頼されていない認証局のエラーになることがあります。ブラウザーが中間証明書をキャッシュしている場合もあるため、「ブラウザーでは正常に開ける」だけでは、サーバーの証明書チェーンが完全であるとは確認できません。

自分でサーバーを管理している場合は、OpenSSLをインストールした環境で次のコマンドを実行できます。example.comは予約済みの例示用ドメインです。実行前に2か所の名前を実際のTLSドメインに、ポートをノードの実際のポートに置き換えてください。このコマンドで確認できるのは通常のTLS接続先であり、その後のVMessまたはVLESSの認証ではありません。

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

allowInsecureの意味:検証を有効に保ち、設定で問題を隠さない

allowInsecureは、通常のTLS証明書検証をスキップするかどうかを設定します。trueにすると接続が暗号化される場合はありますが、通常の証明書チェーンとホスト名の検証によるサーバーの身元確認は行われません。証明書の問題が修正されるわけではなく、意図したサーバーに接続できる保証もありません。

以下は通常のTLSアウトバウンド設定にあるtlsSettingsの項目例で、ノード全体をそのままインポートできる設定ではありません。例示用ドメインは実際のサーバー名に置き換えてください。サブスクリプションで管理するノードは、次回更新時にローカルの変更が上書きされないよう、まず配信元の設定を修正してください。

{
  "tlsSettings": {
    "serverName": "example.com",
    "allowInsecure": false
  }
}

修正確認:検証を戻してからテスト

allowInsecureをfalseのままにして再接続し、証明書エラーが再発しないことを確認してから、ウェブページへの接続と想定した出口を検証します。検証をスキップした場合にしか接続できないなら、問題はまだ解決していません。

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

サブスクリプション更新時に証明書エラーが出た場合も、ノードのSNIを変更すべきですか?

まずノードの設定を変更するのは避けてください。サブスクリプションURLのホスト名、端末の時刻、そのHTTPSサービスの証明書を確認します。更新時にプロキシ経由で接続している場合は、プロキシの経路とサブスクリプションサイトを分けて検証し、どの段階で失敗しているか確認してください。

パソコンでは使えるのに、Androidでは証明書を信頼できないと表示されます。どうすればよいですか?

まず両方の端末でアドレス、ポート、SNI、証明書検証の設定を比較し、次にAndroidのシステム時刻とシステム更新を確認します。設定が一致している場合は、中間証明書が不足していないかサーバー管理者に確認してもらってください。出所の分からないルート証明書を端末にインストールしないでください。

REALITY接続に失敗した場合も、中間証明書を追加すべきですか?

通常のTLS向けの修正手順をそのまま適用しないでください。まずノードのセキュリティ方式がREALITYであることを確認し、サーバー名、公鍵、shortIdなど、提供元が指定するパラメーターとコアの互換性を順に確認します。allowInsecureを有効にしても、これらの認証パラメーターの代わりにはなりません。

一度は接続できるようになりました。復旧したことをどう確認できますか?

証明書検証を有効にしたまま現在の接続を再起動し、実際のウェブページへのリクエストを数回続けて送信します。新しいログに同じエラーがないことを確認し、システムプロキシまたはTUNが適用される範囲も確認してください。TCPの遅延が表示されても、これらの確認の代わりにはなりません。

最後に、操作の内容、エラーの種類と全文、変更前後の設定項目、再テストの時刻と結果を簡潔に記録してください。それでも解決しない場合は、機密情報を伏せたログと記録をサーバー管理者に渡し、「ノードが使えない」と伝えるだけでなく、実際の接続先が返す証明書を確認するよう依頼します。プロキシが反映されているか確認する手順は、接続テストの説明を参照してください。

v2rayNをダウンロード