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

V2Rayクライアントで証明書エラーやTLSハンドシェイク失敗が起きる主な原因を整理し、システム時刻、SNIと偽装ドメイン、フィンガープリント、証明書検証を無効にするリスクを順に確認します。

この記事の要点

v2rayN、v2rayNG、v2flyNGでTLSハンドシェイク失敗、証明書の期限切れ、ドメイン不一致が起きた場合に役立つ記事です。まずログがサブスクリプション更新時のものか、ノード接続時のものかを確認し、時刻、アドレスとポート、SNI、証明書チェーン、通信設定を順に調べます。読み終えると、クライアント側で直せる設定とノード管理者に対応を依頼すべき問題を見分け、allowInsecureを常用すべきでない理由も理解できます。

TLSエラーがどの接続で起きたかを確認する

「ハンドシェイク失敗」は結果であり、原因は一つではありません。通常のTLS接続では、サーバーアドレスを名前解決し、TCP接続を確立してからTLSパラメーターをネゴシエートし、証明書を検証します。プロキシプロトコルの認証や実際の通信転送は通常その後です。ドメインの名前解決失敗、443番ポートへの接続不可、プロトコル認証の拒否も、クライアント上では接続失敗と表示されることがありますが、証明書設定を変えても解決しません。

アドレスの名前解決 ポートへの接続 TLSネゴシエーション 証明書の検証 プロトコル認証 リクエストの転送

エラーがどの操作の後に発生したかをまず確認します。「サブスクリプションを更新」をクリックしたときの証明書エラーは、サブスクリプションサーバーへのHTTPS接続に関するものです。ノードを選択してウェブサイトにアクセスし、コアのログにx509が記録されている場合は、プロキシの送信側でTLS検証に失敗した可能性があります。ノード編集画面のallowInsecureを変更しても、通常はサブスクリプション取得時のHTTPS検証には影響しません。

エラーメッセージから原因を絞り込む

コアやバージョンによって、エラー原文の前後に接続情報が付くことがあります。以下はよく見られるコアのエラーメッセージで、ログ全体が完全に一致する必要はありません。原因の候補は絞れますが、単一のエラーだけで最終的な原因を断定することはできません。

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

原因と対処:端末の時刻が証明書の有効期間外か、サーバーの証明書が実際に期限切れです。まずシステム時刻を同期します。時刻が正しいのに再発する場合は、管理者に証明書の有効期間と、更新後にサービスが再読み込みされたかを確認してもらいます。

エラー:x509: certificate is valid for edge.example, not node.example

原因と対処:クライアントが検証した名前が、証明書の対象範囲に含まれていません。サーバー側が指定するSNIと証明書のSANを確認してください。接続先がnode.exampleだからといって、SNIも同じ値に設定しないでください。

エラー:x509: certificate signed by unknown authority

原因と対処:証明書の信頼チェーンを構築できません。中間証明書の不足、自己署名証明書、古い信頼ストア、ネットワーク上での証明書差し替えなどが考えられます。別の端末やネットワークでの結果を比較し、サーバーが完全な証明書チェーンを送信しているか確認してください。

エラー:remote error: tls: handshake failure

原因と対処:接続先がTLSハンドシェイクを拒否しています。SNI、プロトコルバージョン、クライアントフィンガープリント、サーバー側のポリシーなどが関係する場合があります。元のノード設定を基準にパラメーターを一つずつ戻し、証明書の期限切れと即断しないでください。

エラー:tls: first record does not look like a TLS handshake

原因と対処:接続先ポートからTLS以外のデータが返されています。ポートとTLSの設定を確認してください。たとえば、平文HTTPを提供する80番ポートを、TLSサービス用の443番ポートとして扱わないでください。

EOF、connection reset by peer、i/o timeoutは、より幅広い原因で発生します。通信の途中切断、ファイアウォール、ポートの誤り、サーバー停止などが考えられます。これらのメッセージだけを根拠に証明書検証を無効にしないでください。まずTCP接続を確立できるかを確認し、その後TLS層を調べます。

システム時刻とノード設定を5段階で確認

一度に変更するのは一つの項目だけにし、同じテストリクエストを繰り返します。最初に元の設定を保存してください。アドレス、ポート、SNI、フィンガープリントをまとめて変更すると、接続できても何が解決につながったのか分からなくなります。以下のWindowsの手順はWindows 11の日本語画面を例にしています。クライアントのバージョンやデスクトップ版・モバイル版によって項目の場所は異なりますが、各項目の意味は同じです。

  1. 時刻を同期する

    Windowsでは「設定」→「時刻と言語」→「日付と時刻」を開き、「時刻を自動的に設定する」をオンにして「今すぐ同期」をクリックします。Androidでは通常、「設定」→「システム」→「日付と時刻」で自動設定をオンにします。メーカーによっては「その他の設定」にあります。タイムゾーン名だけでなく、実際の日付と時刻も確認してください。

  2. ポートを確認する

    v2rayNではメイン画面で現在のノードをダブルクリックし、編集画面を開きます。v2rayNGではノード一覧から該当ノードの編集アイコンをタップします。ノード提供元が案内する「アドレス」と「ポート」を照合してください。TLSでは443番ポートがよく使われますが、8443番など別のポートも正常です。証明書エラーが出たからといって、一律に443番へ変更しないでください。

  3. SNIを確認する

    ノード編集画面のTLSまたは通信セキュリティ欄を開き、「SNI」または「serverName」の値を確認します。サーバー側が指定するドメインを入力し、https://、ポート、パス、空白は含めません。接続先アドレスとSNIは異なる場合があります。ノードの設定情報を確認せず、推測で値を設定しないでください。

  4. 証明書検証を有効に戻す

    「安全でない接続を許可」または「allowInsecure」を確認します。通常の利用ではオフ、つまりfalseにしてください。提供元が指定するフィンガープリントとALPNも元の設定に戻します。元の設定に値がなければ、エラーを消すためにむやみに追加しないでください。

  5. 再接続してログを確認する

    ノードを保存して接続を再起動します。v2rayNGでは接続をいったん停止してから再開します。v2rayNでは保存後、変更したノードが選択されていることを確認して、再度テストします。証明書エラーが接続タイムアウトやプロトコル認証エラーに変わった場合は、失敗した段階が変化しています。

証明書の検証では、その時点の実際の時刻が使われます。表示上のタイムゾーンだけを変更して、誤ったシステム時刻を直さないままでは、有効期間の問題は通常解決しません。たとえば、システムの日付が2025年のままで、証明書の有効期間が2026年から始まる場合、「まだ有効ではない」と判定されます。逆に、システムの日付が未来になっていると、有効な証明書が期限切れと判定されることがあります。

# Linux:システム時刻と同期状態を確認
timedatectl status

# Linux:システムがサポートするネットワーク時刻同期を有効化(通常は管理者権限が必要)
sudo timedatectl set-ntp true

Linuxで2つ目のコマンドを実行するには、利用可能な時刻同期サービスがシステムに用意されている必要があります。設定後も、同期状態を改めて確認してください。macOSでは「システム設定」→「一般」→「日付と時刻」で自動設定を確認できます。時刻が正確で、エラーが出るのが一つのノードだけなら、端末の時刻を何度も変更する必要はありません。サーバー証明書とノード設定を確認しましょう。

SNI・接続先アドレス・Hostは別の項目

SNIはTLSハンドシェイクでクライアントがサーバーに伝える名前で、仮想ホストや証明書の選択に使われます。通常のTLS設定にあるserverNameは、証明書の検証名を指定する役割も持ちます。接続先アドレスはサーバーへの接続に使われ、HTTP Hostはより上位のHTTPリクエストに属します。3つの値は同じ場合も、サーバーの構成に応じて別々の場合もあります。

項目使用される段階設定値の確認方法よくある間違い
アドレスとポート名前解決と接続の確立443や8443など、ノードの実際の接続先サブスクリプションサイトのアドレスをノードのアドレスとして使う
SNI / serverNameTLSハンドシェイクと名前の検証サーバーが許可する名前と証明書のSANプロトコルのプレフィックスやパスを付ける、またはドメインを推測で変更する
WebSocket HostHTTP Upgradeリクエストリバースプロキシの仮想ホスト設定Hostを変更すればSNIも自動で修正されると思い込む
WebSocket pathリクエストパスの照合サーバー側で設定されたパスパスの誤りなのに証明書だけを調べる

たとえば、接続先アドレスがnode.exampleで、サーバーが要求するSNIがedge.exampleの場合、接続は接続先アドレスに対して行われますが、通常のTLSでは証明書がedge.exampleをカバーしている必要があります。ここに示した.exampleのドメインは予約済みの例示用で、実際に使えるノードではありません。IPアドレスで直接接続して正しい検証名を設定しない場合、証明書の対象がドメイン名だけであれば名前が一致しないことがあります。

要点:項目を照合してからドメインを変更する

名前が一致しない場合は、アドレス、SNI、HTTP Hostそれぞれの値を管理者に確認してください。意味があるのは、証明書が実際にカバーし、サーバーが受け入れる名前だけです。有名サイトのドメインに変更しても、通常のTLS設定の問題は解決しません。

「偽装ドメイン」は、すべての設定で同じ項目を指す言葉ではありません。SNIを指す場合もあれば、HTTP Hostを指す場合や、REALITYのサーバー名に関係する場合もあります。まず通信セキュリティ方式を確認してください。通常のTLSにおけるCA証明書の検証と、REALITYで使う認証パラメーターは、別の手順で調べる必要があります。

証明書チェーン・フィンガープリント・通信設定を確認する

同じドメインにブラウザーからアクセスできても、プロキシノードのTLS設定が正しいとは限りません。ブラウザーは443番ポートに接続していても、ノードは8443番ポートに接続している場合があります。また、SNI、接続先アドレス、信頼ストアが異なる可能性もあります。診断には、同じ接続先と同じ名前を使った結果を比較してください。

OpenSSLがインストールされている端末では、次のコマンドで通常のTLS接続先を確認できます。例では予約済みのドメインを使っています。実行前に実際の接続先とSNIに合わせて変更してください。これはプロキシプロトコルのテストではなく、REALITYノードの利用可否も確認できません。

openssl s_client \
  -connect node.example:443 \
  -servername edge.example \
  -verify_hostname edge.example \
  -verify_return_error \
  -showcerts

-connectは接続先を指定し、-servernameはSNIを送信し、-verify_hostnameは検証する名前を明示します。SNIを送信しただけでは、ドメイン名の照合を実行したことにはなりません。証明書の有効期間、名前、検証結果を確認してください。ツールが使う信頼ストアはクライアントと異なる場合があるため、結果は原因を絞る手掛かりとして扱い、唯一の判断材料にしないでください。

allowInsecureを常時オンにすべきでない理由

一般的なV2Ray/Xrayの通常のTLS設定では、allowInsecure: trueにすると、サーバー証明書チェーンと名前の通常の検証がスキップされます。接続の暗号化が続く場合でも、クライアントは接続先の身元を確実に確認できなくなります。通信が暗号化されていても、相手が意図したサーバーとは限りません。

問題有効にすると変化する可能性適切な対処
証明書の期限切れ・名前の不一致検証エラーを回避できる場合がある時刻やSNIを修正するか、サーバー証明書を更新する
自己署名証明書が信頼されない信頼チェーンのエラーを回避できる場合がある管理された環境の要件に従い、信頼できる証明書または対応する信頼方式を設定する
ポートに接続できない・接続がタイムアウトするネットワークの接続性は修復できないポート、ネットワーク、サービスの状態を確認する
パスや認証パラメーターの誤り上位プロトコルの設定は修復できない正しいパスとノードの認証情報に戻す
REALITY認証の失敗REALITYの認証手順には代用できないREALITY専用のパラメーターとコアの対応状況を確認する

管理された環境での診断中に一時的に有効にして接続できた場合、証明書検証が失敗に関係している可能性を示すだけです。ノードが安全であることや、すべての問題が解決したことを証明するものではありません。診断中は機密情報を送信せず、終了後すぐに無効にし、元のエラーに基づいて原因を修正してください。長期間検証をスキップして「接続できる」状態にするのではなく、ログと証明書を確認して原因を特定する方が安全です。

要点:証明書検証を戻して初めて修復完了

allowInsecureをfalseに戻し、同じノードで接続を再試行してください。エラーが続く場合は、時刻、名前、信頼チェーンを引き続き修正します。通常の証明書検証を通過し、実際のリクエストも成功して初めて、証明書エラーの対処が完了します。

よくある質問と問い合わせ時に共有する情報

PCでは接続できるのに、Androidで証明書が信頼されないと表示されるのはなぜ?

まず2台で同じノード、SNI、ネットワークを使い、自動時刻設定が有効になっていることを確認します。設定が一致している場合は、システムの信頼ストアの違いや、サーバーの中間証明書不足を確認してください。PCで証明書検証をスキップする設定を、そのままコピーしないでください。

サブスクリプション更新後に突然ハンドシェイクに失敗します。再インストールが必要ですか?

まずノード編集画面で、アドレス、ポート、TLSの種類、SNIが変わっていないか比較し、古いコピーではなく新しいノードが選択されていることを確認します。再インストールでは、サーバー証明書の期限切れは通常直りません。エラー原文を保存し、管理者に設定を確認してもらいましょう。

スマートフォンのテザリングに切り替えると正常になるのはなぜ?

ネットワーク経路が接続に影響している可能性を示しますが、原因を断定することはできません。ノードの設定は変えず、2つのネットワークで発生したエラーをそれぞれ記録してください。特定のネットワークでunknown authorityが出る場合は、HTTPS検査や証明書の差し替えがないか確認します。出所不明のルート証明書をむやみに信頼しないでください。

遅延テストに成功すれば、証明書も正常ということですか?

必ずしもそうではありません。TCP遅延テストで分かるのは、ポートに接続できたことだけで、TLS検証やプロキシ経由のリクエストが行われたとは限りません。テストの種類を確認してから、実際にリクエストを送り、コアのログを確認してください。遅延の数値だけで接続全体が正常と判断しないでください。

証明書を更新したのに、クライアントで期限切れと表示されるのはなぜ?

管理者に、新しい証明書がサービスで再読み込みされているか、接続先によって古い証明書が提供されていないか確認してもらってください。クライアント側では時刻と接続先アドレスも確認します。複数サーバーやIPv4・IPv6の接続先で設定が異なると、一部の接続だけ失敗することがあります。

さらにサポートが必要な場合は、問題を再現できる最小限の情報を共有してください。設定ファイル全体を貼る必要はなく、サブスクリプションのURLをスクリーンショットに含めないでください。以下の項目を整理してから、当サイトのトラブル対処で原因を調べてください。項目の意味が分からない場合は、用語クイックガイドをご覧ください。

v2rayN をダウンロード