V2RayのTLS証明書エラー対処チェックリスト:システム時刻のずれとSNI設定を確認
TLSハンドシェイクの失敗は、ノードが原因とは限りません。まずシステム時刻、次にSNIとserverName、最後にallowInsecureとポートを確認し、証明書エラーを順番に切り分けます。
V2Ray、Xray、V2FlyのコアはTLS接続を確立する際、まずリモート証明書を検証し、その後にVMess、VLESSなどのプロトコルでデータ交換を行います。証明書の有効期間、ドメイン名、証明書チェーン、ハンドシェイクパラメーターのいずれかが要件を満たさないと、プロトコル認証前に接続が中断されます。そのため、ログに証明書エラーが出ている場合は、先にユーザーID、暗号化方式、ルーティング規則を変更するべきではありません。通常、これらは現在の接続処理にまだ関与していません。
証明書関連の障害では、3つの対象を区別することが重要です。実際に接続するサーバーアドレス、TLSハンドシェイクで送信するサーバー名、証明書に記載された有効ドメインです。ノードが入口アドレス、リバースプロキシ、コンテンツ配信構成を使う場合、3つの値は一致することもあれば異なることもあります。判断基準は「近そうか」ではなく、設定提供元の各項目が証明書と正確に対応しているかどうかです。
1. エラーが本当にTLS段階で発生しているか確認する
まずクライアントのログを開いてから接続を試します。v2rayNではログ欄からコアの出力を確認できます。v2rayNGとv2flyNGでは、接続後に実行ログを確認できます。今回のテストで生成された記録だけを残し、数時間前のエラーを現在の結果と取り違えないようにしてください。
よくある表示には、certificate、x509、handshake、unknown authority、expired、not yet valid、hostname、server nameなどのキーワードが含まれます。コアのバージョンによって文言は異なりますが、意味ごとに分類できます。
| ログの意味 | 優先して確認する項目 | よくある原因 |
|---|---|---|
| 証明書がまだ有効になっていない | 端末の日付、時刻、タイムゾーン | システム時刻の遅れ、またはタイムゾーンの設定ミス |
| 証明書の有効期限切れ | 端末時刻とリモート証明書の状態 | システム時刻の進み、またはサーバー証明書の更新漏れ |
| ドメイン名が一致しない | SNI、serverName、アドレス欄 | ハンドシェイクのドメイン名がない、またはアドレス欄のIPを誤って入力している |
| 不明な認証局 | システムの証明書ストア、ネットワークによる遮断、証明書チェーン | ルート証明書が古い、またはリモート側が中間証明書を完全には送信していない |
| ハンドシェイクが切断またはリセットされた | ポート、TLS設定、トランスポート種別 | TLS非対応ポートに接続している、またはノードのパラメーターの組み合わせが誤っている |
ログにタイムアウト、ドメイン名を解決できない、接続拒否だけが表示される場合は、まずネットワークの到達性、DNS、ポートの待ち受けを確認します。これらは証明書の検証前に発生する現象です。ログに証明書の日付や名前の不一致が明記されている場合は、以下の順番で対処してください。
2. システム時刻、タイムゾーン、自動同期を確認する
TLS証明書には有効開始時刻と有効期限が含まれています。クライアントは端末の時計を使って、証明書が有効期間内かどうかを判断します。数分のずれなら通常のWebページは開ける場合もありますが、発行直後や更新直後の証明書は、まだ有効でないと判定されることがあります。スリープからの復帰、マザーボード時計の異常、仮想環境の一時停止、自動同期の長期無効化などが時刻のずれを引き起こします。
- システムに表示されている年、月、日、時刻、分を確認し、まず明らかな誤りを除外します。
- タイムゾーンが現在地と一致していることを確認します。表示される時刻が正しくても、タイムゾーンが間違っていると実際の時刻がずれることがあります。
- 時刻の自動設定とタイムゾーンの自動設定を有効にし、その後すぐに手動同期を一度実行します。
- クライアントを完全に終了して再起動し、新しい時刻の状態でコアが接続を確立できるようにします。
- ログを再確認し、「まだ有効ではない」または「期限切れ」の表示が消えたか確認します。
Windowsでは日付と時刻の設定から自動同期の状態を確認できます。macOSでは日付と時刻の設定で時刻の取得元を確認します。Androidでは日付と時刻の自動設定とタイムゾーンの自動設定を両方確認してください。Linuxのデスクトップ環境では通常、システム設定から同期できます。さらに確認が必要な場合は、端末でシステム時刻の同期状態を確認します。
timedatectl status
ローカル時刻、協定世界時、タイムゾーン、システム時計が同期済みかを重点的に確認します。クライアント画面の設定だけを修正してもシステム時刻の調整にはなりません。証明書の検証はコアとシステム時刻の両方に依存するためです。
3. SNI、serverName、サーバーアドレスを順番に確認する
SNIは、TLSハンドシェイクで送信されるサーバー名です。1つの入口アドレスで複数のドメインを提供する場合、サーバーはSNIをもとに返す証明書を選択します。V2RayとXrayの設定でよく見られるserverNameは、通常このハンドシェイク名を指定する項目です。クライアントによってはSNI、サーバー名、TLS Server Nameなどと表示されます。
サーバーアドレスはTCP、WebSocket、gRPCなどの基盤接続を確立し、serverNameはTLSの名前検証を担います。用途は異なります。ノードアドレスはドメイン名の場合もIPの場合もありますが、serverNameには通常、証明書が対象とするドメイン名を入力します。接続アドレスがIPだからといって、そのIPをSNI欄にそのままコピーしないでください。
次の4項目を照合する
- アドレス欄:余分な空白、プロトコルの接頭辞、パス、ポートがないことを確認します。アドレス欄には通常、ドメイン名またはIPだけを入力します。
- ポート欄:ノード情報と値が一致していることを確認し、一般的なポートだからという理由で勝手に変更しないでください。
- TLS設定:ノード情報でTLSが指定されている場合は必ず有効にし、TLSを使わない構成では追加で有効にしないでください。
- serverName欄:ノード情報に記載された証明書のドメイン名をそのまま入力し、アドレス欄の値に勝手に変更しないでください。
ドメイン名の一致判定は証明書のルールに従います。証明書がnode.example.comを対象としていても、必ずしもexample.comやapi.node.example.comを対象にするとは限りません。ワイルドカード証明書も、規定された階層だけを対象とします。複数のドメインが最終的に同じIPへ解決されても、証明書名の検証はドメイン名単位で行われます。
サブスクリプションからインポートした直後は、項目を手動で「簡略化」しないでください。サブスクリプションでは、アドレス、host、path、SNI、トランスポート種別が別々に指定されることがあります。それらを1つのドメイン名にまとめると、元の組み合わせが壊れやすくなります。サブスクリプションが古いと思われる場合は、まず更新し、重複する古いノードを削除してから、新しくインポートしたノードを一度テストします。
WebSocketではHostとSNIを混同しない
WebSocket設定のHostはHTTPリクエストヘッダーで、SNIはTLSハンドシェイクの項目です。2つの値が同じ場合もありますが、同じパラメーターではありません。gRPCのサービス名もserverNameとは別物です。確認時は各欄を個別に照合し、パス、Host、サービス名をSNI欄に入力しないでください。
典型的な関係は次のとおりです。
接続アドレス:入口ドメインまたは入口IP
接続ポート:ノード指定のTLSポート
TLS:有効
serverName / SNI:証明書が対象とするドメイン名
WebSocket Host:ノード指定のHTTP Host
WebSocket Path:ノード指定のリクエストパス
serverNameを変更した後、ログが「証明書のドメイン名が一致しない」から「WebSocketの異常なステータス」や「サービス名が存在しない」に変わった場合、TLS段階は通過した可能性があります。障害がトランスポート層へ移ったということです。この場合は証明書関連の設定を何度も調整せず、Host、パス、gRPCサービス名を確認します。
4. ポート、TLS設定、トランスポートを一体で確認する
証明書エラーの原因が証明書そのものとは限りません。TLS非対応サービスへTLSハンドシェイクを送ったり、TLS入口へ通常の接続を送ったりすると、ハンドシェイク失敗、接続リセット、予期しない応答が発生します。最もよくある原因は、ノードを手動編集した際にポートだけを変更し、TLS設定とトランスポート種別を変更し忘れることです。
- ノードをコピーする際に、VMessまたはVLESSのプロトコル種別を誤って変更していないことを確認します。
- TCP、WebSocket、gRPCなど、トランスポート種別が資料と一致していることを確認します。
- TLS関連の設定とポートが、同じノードパラメーターの組み合わせになっていることを確認します。
- WebSocketのパスを正しい形式で入力し、ドメイン欄に貼り付けていないことを確認します。
- gRPCのサービス名が元の大文字・小文字と文字列のまま保持されていることを確認します。
- ローカルの待ち受けポートをリモートサーバーのポート欄に入力していないことを確認します。
ルーティングによって通常、証明書のドメイン名判定が変わることはありません。ただし、ルーティングによって異なる出口を経由する場合があります。切り分けでは、まず対象ノード自体が接続を確立できることを確認し、その後で複雑なルールを戻します。特定のルールに一致した場合だけ失敗するなら、そのルールが選択するアウトバウンドが想定したノードを指しているか確認し、証明書検証を直接無効にしないでください。
同様に、システムプロキシの状態は主にアプリの通信をクライアントへ送るかどうかを決めるもので、ノード証明書の有効性を決めるものではありません。ログにコアがリモートへ接続中と表示されているなら、テスト要求はすでにクライアントへ到達しています。この段階でシステムプロキシのモードを切り替えても、証明書の期限切れやSNIエラーを直接修正することはできません。
5. allowInsecureの用途を正しく理解する
allowInsecureは、リモート証明書の検証をクライアントが緩和するかどうかを制御します。通常の利用では無効にしてください。有効にすると、証明書名、認証チェーン、有効性の検証を迂回できる場合があります。エラーが一時的に消えても、元の設定が正しいことの証明にはならず、サーバー証明書が修復されるわけでもありません。
切り分けでは、範囲の限られた診断用スイッチとして扱えます。無効時に明確な証明書検証エラーが出て、有効にすると次の段階へ進めるなら、問題は証明書検証経路に集中していると判断できます。特定後はすぐに無効へ戻し、システム時刻、serverName、証明書チェーン、サーバー設定を修正してください。
allowInsecureを「接続できればよい」という理由で常用することは推奨しません。TLSの名前検証と発行元検証は、想定したサービスへ接続していることを確認するためのものです。検証を省略すると、クライアントは通常のルールでリモートの身元を確認できません。特に公共ネットワークや通信転送が存在する環境では、完全な検証を維持してください。
6. 証明書チェーン、システム証明書ストア、ネットワーク遮断を確認する
ログに不明な認証局や信頼チェーンを構築できないという表示がある場合は、まずOSを更新してから端末を再起動します。システムのルート証明書ストアが長期間更新されていないと、新しい発行チェーンを認識できないことがあります。クライアントとコアも現在メンテナンスされているバージョンを使用してください。古いバージョンには、旧式のTLSコンポーネントや証明書処理ロジックが含まれている可能性があります。
同じノードがモバイルネットワークでは使えるのに、会社、学校、公共ネットワークでは証明書エラーになる場合は、2つのネットワークでログに表示される証明書名と発行情報を比較します。ネットワークによっては認証ゲートウェイが独自のログインページを返すため、クライアントが受け取るのは対象サーバーの証明書ではありません。その場合はまずネットワーク認証を完了するか、ネットワーク管理者にアクセス方針を確認してください。
すべての端末とネットワークで同じノードの証明書チェーンが不完全と報告され、他のノードは正常な場合、問題はサーバー側にある可能性があります。サーバーでTLSを設定する際は、サイト証明書だけでなく必要な中間証明書チェーンも送信する必要があります。クライアントはサイト証明書だけを使って、欠落したすべての要素を自動で補完できるわけではありません。一般利用者は完全なログを保存してノードの管理者へ報告し、クライアントの再インストールを繰り返してサーバー側の問題を隠さないようにしてください。
7. 比較テストで障害範囲を絞り込む
比較テストは、手当たり次第に試すより効果的です。以前正常に使えたノードを基準として用意し、端末、ネットワーク、ノードの3つの観点でテストします。毎回、変更する変数は1つだけにしてください。
| テスト結果 | 優先して判断する項目 | 次の対応 |
|---|---|---|
| 同じ端末で1つのノードだけ失敗する | ノードのパラメーターまたはリモート証明書 | SNI、ポート、トランスポート、証明書の状態を確認 |
| 同じノードが1台の端末だけで失敗する | 端末の時刻、証明書ストア、クライアント設定 | 時刻を同期し、システムを更新して、サブスクリプションを再インポート |
| 同じノードが1つのネットワークだけで失敗する | ネットワーク認証、DNS、中間ネットワーク機器 | 認証を完了し、異なるネットワークのログを比較 |
| すべてのTLSノードが同時に失敗する | システム時刻、システム証明書ストア、ネットワーク環境 | まず時刻を合わせ、別のネットワークでテスト |
| TLS通過後にプロトコル認証が失敗する | ユーザーパラメーターまたはプロトコル設定 | ID、プロトコル種別、サブスクリプション内容を確認 |
テスト中は、サブスクリプションの頻繁な更新やノードの一括変更をいったん控えます。更新によって手動設定が上書きされたり、同名ノードが作成されたりして、テスト対象が変わることがあります。ノードの更新時刻、クライアント名、コアの種類、ネットワーク環境、エラーが発生した正確な時刻を記録してください。問題を報告する際は、これらの情報が「接続できない」という説明よりも原因の特定に役立ちます。
8. 最終チェックリスト
- システムの日付、時刻、タイムゾーンが正しく、自動同期が完了している。
- クライアントログに今回の接続で発生したエラーが表示されている。
- サーバーアドレスには正しいドメイン名またはIPだけが含まれ、パスが混入していない。
- リモートポートがノード情報と一致し、ローカルプロキシポートを誤入力していない。
- TLS設定、トランスポート種別、ポートが同じ構成に基づいている。
- serverNameまたはSNIが証明書の対象ドメインと一致している。
- WebSocketのHost、パス、gRPCサービス名を誤った欄に入力していない。
- サブスクリプションが更新され、テスト対象が古い同名ノードの残骸ではない。
- allowInsecureが無効に戻され、常用設定として残っていない。
- システム、クライアント、コアが現在メンテナンスされているバージョンになっている。
- 別の端末または別のネットワークで比較テストを一度実施している。
- 特定のノードだけが継続して失敗する場合、ログを保存して管理者へ報告している。
TLS切り分けの要点は、時刻、名前、ポート、トランスポート、証明書チェーンの順です。まず端末の時刻を確認し、次にserverNameが証明書と一致するかを判断します。その後、TLSが正しいポートへ接続しているかを確認し、最後に証明書チェーンとネットワーク環境を調べます。この順番で確認すれば、VMess、VLESS、サブスクリプション、ルーティング設定まで関係なく作り直す必要はありません。