# Server Diagnostics(サーバー診断) Core のサイドバーに Plugins → Server Diagnostics → Hash & Checksum の順で統合されています。SSH セッションやプラグインのダウンロードは不要です。ランタイムのコード、テスト、フィクスチャはすべて `app/` にあり、このモジュールは隣接するリポジトリに依存しません。リポジトリに `doc.md` はないため、このドキュメントと 2 つの README で実装を説明しています。 ## ユーザーの作業の流れ ホスト名、IPv4、IPv6、または HTTP(S)/WS(S) の URL を入力します。ホスト名/IP だけを入力した場合は、既定で HTTPS が使われます。URL を明示した場合は、リクエスト中もパス、クエリ、ポートが保持されます。URL 内の認証情報、未対応のスキーム、空白/制御文字、シェルのようなホスト名は拒否されます。IPv6 のリテラルには自動的に角かっこが付きます。スコープ付き/リンクローカルのゾーン識別子は、URL パーサーでは扱えません。 Auto(IPv4 を優先し、使えない場合は IPv6)、IPv4、IPv6、Both のいずれかを選びます。「アドレスを解決」を使うと、現在の応答のうち特定のものを選べます。概要には解決したすべての応答が表示されます。プローブは、選択したアドレス、または要求したアドレスファミリーごとに 1 つのアドレスをテストします。2 つのファミリーはそれぞれ独立して計測されます。AAAA レコードがあるだけでは、IPv6 で接続できることにはなりません。 Run Diagnostics(診断を実行)では、DNS、ping、traceroute、HTTP、圧縮、TLS、選択した TCP ポートを調べます。WebSocket は選択した場合のみ実行されます。各ツールには、個別の実行/停止の操作もあります。同時に実行できる診断は 1 つだけです。実行が完了したということは、ツールが終了したという意味であり、すべてのプローブが成功したという意味ではありません。一律に「サーバーがオフライン」と判定することはありません。 タイムアウト、パケット数、繰り返し回数、最大ホップ数、DNS リゾルバー、プロトコルの選択、ウォーム接続、HTTP/HTTPS の比較を設定できます。対象を変更すると、以前に選択した IP はクリアされます。履歴では、再表示、2 つのレポートの比較、削除、JSON のインポート、コピー、ネイティブの Core ダイアログを使った JSON/CSV/TXT へのエクスポートができます。ライト/ダーク/システムのテーマは診断セクションに適用され、既存の UI 設定に保存されます。CZ/DE/EN の表示は、アプリケーションの言語にすぐに追従します。 ## コンポーネントとプロトコルの動作 | コンポーネント | 実装と解釈 | | --- | --- | | `common.js` | 対象/オプション、制限、列挙値を検証します。IDNA の変換を行います。数値の統計では不明な値を除外します。 | | `dnsDiagnostics.js` | システムのアドレス解決には `dns.lookup` を使い、OS の設定と hosts ファイルに従います。レコードのクエリには範囲を限定した UDP DNS を使い、応答が切り詰められた場合は TCP にフォールバックします。問い合わせ先は `dns.getServers()`、または明示的に選んだカスタム/パブリックのリゾルバーです。パブリック DNS に暗黙に切り替えることはありません。 | | `processTools.js` | OS の ping/traceroute を引数配列と `shell: false` で実行し、出力を制限し、明示的なタイムアウトと中止/強制終了の後始末を行います。プロセスの実行時間を RTT として扱うのではなく、パケットの応答とホップを解析します。 | | `httpDiagnostics.js` | HTTP/1.1、HTTP/2、HTTP/3 には同梱の curl を使い、証明書を厳格に検証し、IP アドレスファミリーを固定します。各バージョンを個別にリクエストし、実際に使われたバージョンを記録します。 | | `socketDiagnostics.js` | 明示的な TLS バージョンのプローブ、範囲を限定した TCP 接続/受動的なバナー取得、既存の ssh2 依存関係を使った認証前の SSH ホスト鍵の確認、任意の RFC 6455 Upgrade の検証を行います。 | | `diagnosticsService.js` | ツールの実行とキャンセル、アドレスの選択/検証、進捗のストリーミング、部分的な計測結果の保持を行い、実行の期限を管理します。 | | `historyStore.js` | バージョン管理された容量制限付きのローカル履歴、マスキング、スキーマを確認したうえでのインポート、計測データのエクスポートを担います。 | ### ICMP と経路 Ping は既定で、個別に実行する 4 つの ICMP echo リクエストを送ります。結果には、パケットごとに計測した RTT、受信数/送信数、パケットロス、最小/平均/最大、母標準偏差、連続して計測した RTT の差の平均絶対値(ジッター)、出力された場合の TTL/Hop Limit、タイムスタンプが含まれます。`<1 ms` の応答は、RTT の数値をでっち上げることなく、上限値付きで受信として数えます。不明な RTT はレイテンシーの統計から除外されます。統計には保持している最大 500 パケットのウィンドウを使い、送信/受信/ロスの数は実行全体を対象とします。グラフには直近 200 件の観測結果が表示され、応答、分解能未満の応答、応答なし、明示的なリクエスト/プロセスのタイムアウトが、それぞれ異なる記号で示されます。 応答がない場合は、ICMP のフィルタリング、パケットロス、タイムアウトのいずれかを反映している可能性があります。これらの観測結果から、ファイアウォールがあると断定することはできません。実行ファイルがない、ローカルの権限の失敗、ツールの呼び出しが無効といった問題は、パケットロスやサーバーの停止ではなく、別のツールのエラーとして扱われます。権限の昇格は要求しません。 Traceroute では、ホップ、アドレス、個々のプローブ、平均値、観測された無応答プローブの割合を順次表示します。逆引き DNS は、経路の取得後に選択したリゾルバーで解決します。繰り返し実行すると、観測されたホップのアドレスの並びを比較します。違いはロードバランシングを反映している場合があります。途中のホップが応答しなくても、経路が壊れているとは言えません。生のプローブのメタデータと方式は、展開できる詳細に表示されます。macOS の traceroute では待ち時間を整数秒で指定する必要があるため、実際に使った丸めたタイムアウトを記録します。 ### DNS 12 種類のレコードは、A、AAAA、CNAME、MX、NS、TXT、SOA、SRV、CAA、PTR、DS、DNSKEY です。DNS のワイヤー形式の解析では、トランザクション/質問の一致、レコードのサイズ、圧縮ポインターのループ、メッセージの制限を確認します。応答には、レコードの TTL、クエリの所要時間、リゾルバー、NXDOMAIN/NODATA/SERVFAIL/refused/timeout の状態が保持されます。OS のアドレス解決では TTL は得られませんが、別途行うレコードのクエリでは得られます。 CNAME の追跡は最大 8 つまでで、循環を検出します。整合性チェックでは、選択したリゾルバーから A/AAAA の応答を繰り返し取得し、IP リテラルを対象とした DNS テストでは正引きで確認した PTR を確かめます。応答が変化しても、それは観測結果であり、DNS の障害の証拠ではありません。SRV のクエリには入力した対象名をそのまま使います。必要に応じて `_service._tcp.example.org` のようなサービス名を入力してください。DNSSEC は常に **未検証** です。DS/DNSKEY が存在すること、さらにはリゾルバーの AD フラグも、独立した検証とはみなしません。 ### HTTP、パフォーマンス、圧縮 HTTP/1.1 は、実際にそのバージョンで返された場合にのみ対応しているとみなします。HTTPS での HTTP/2 には、h2 がネゴシエートされることが必要です。フォールバックしたものに別のラベルを付け直すことはしません。平文の HTTP/2 では、HTTP/1.1 の Upgrade によるプローブではなく、事前知識(prior knowledge)を使います。すべての HTTP/WebSocket のリクエストで、TLS の検証は常に厳格です。 手動でのリダイレクトは 8 回までです。ループ、無効な宛先、多すぎるリダイレクトは、明示的に失敗として扱います。リダイレクトのチェーン全体で、ドメインをまたぐ変更や HTTPS からのダウングレードを記録します。スキームや www の変更は、元/先の URL から確認できます。認証情報や、HTTP(S) 以外のスキームへのリダイレクトは拒否されます。ホストをまたぐ各リダイレクトは、選択したリゾルバーと要求した IP アドレスファミリーで個別に解決されます。 計測項目には、DNS(実行した場合)、TCP、TLS、最終応答の TTFB、DNS/リダイレクトを含めた全体の TTFB、ダウンロード、リダイレクト、合計の経過時間、実際のエンティティのバイト数、転送速度、ステータス、レスポンスヘッダー、実際のサーバーのアドレス/ポート、ALPN、確認済みの接続の再利用が含まれます。固定または再利用された接続で実行されなかった DNS/TCP/TLS のフェーズは、偽のゼロではなく `N/A` と表示されます。QUIC には TCP のフェーズがなく、ハンドシェイクは別に記録されます。ヘッダーの転送やワイヤー全体のオーバーヘッドを、エンティティのバイト数の計測として扱うことはありません。これらはサーバー/ネットワークの所要時間であり、ページのレンダリング時間や Lighthouse のスコアではありません。 選択した各プロトコルは、同じ対象と繰り返し回数を使用します。IPv4/IPv6 と HTTP/HTTPS は、明示的な比較のオプションです。もう一方のスキームでは、その既定のポートを使います。どのプロトコルも、サンプルごとに同梱クライアントの独立したプロセスを起動します。接続が再利用されたとはみなしません。合計時間の統計には、最小/平均/中央値/最大/最近傍順位による P95 と、別に集計したトランスポート/プロトコルのエラー率が含まれます。サーバーが 4xx/5xx の応答を正常に返した場合でも、HTTP のステータスコードは表示されたままです。 圧縮の確認では、identity、gzip、deflate、br、および(ランタイムが対応している場合は)zstd を、それぞれ別の Accept-Encoding のリクエストとして送ります。Content-Encoding が一致し、範囲を限定した展開に成功する必要があります。圧縮率は、デコード後の本文のハッシュ、最終的な URL、ステータスが identity の基準と一致する場合にのみ計算されます。無視されたエンコーディングは未対応とみなし、変化する/動的な本文には圧縮率を出しません。これはその URL/ステータスについての観測結果であり、サーバー全体での対応状況を示すものではありません。 セキュリティヘッダーの確認では、HSTS、CSP、X-Content-Type-Options、Referrer-Policy、Permissions-Policy、X-Frame-Options の有無と値を表示します。CSP の frame-ancestors ディレクティブは後者に優先する場合があります。ヘッダーがあることは、ポリシーが正しく設定されていることや、ウェブサイトが安全であることを示すものではありません。 ### HTTP/3 の要件と証明 HTTP/1.1、HTTP/2、HTTP/3 は、同じ同梱の curl クライアントを使用します。macOS arm64 と Linux x64 では、curl 8.22.0、OpenSSL 3.5.9、nghttp2 1.70.0、ngtcp2 1.25.0、nghttp3 1.18.0 を使用します。Windows x64 では、curl.se 公式の curl-for-win 8.22.0_3 静的ビルドと LibreSSL 4.3.3、および同じ HTTP ライブラリを使用します。システムの curl へのフォールバック、実行時のダウンロード、管理者権限は不要です。Windows 向けアップストリームの再現可能なビルド手順は https://github.com/curl/curl-for-win/tree/9d77e31e にあります。 パッケージングの前に `python3 scripts/native/build.py`(Windows では `python scripts/native/build.py`)でビルドします。macOS/Linux には、C/C++ ツール、CMake、Ninja、Perl、make、pkg-config が必要です。ソースは、バージョンとアップストリームの SHA-256 によって `scripts/native/dependencies.lock.json` で固定されています。スクリプトはすべてのダウンロードを検証し、サードパーティのトランスポートライブラリを静的にリンクし、HTTP2/HTTP3/SSL の機能がない場合は失敗します。動的なままなのは OS のライブラリだけです。Windows では、ローカルでコンパイルした Windows 用トランスポートスタックではなく、固定された公式のバイナリアーカイブを使用します。同梱の CA ファイルには独自に固定されたハッシュがあり、コンポーネントのライセンスとアップストリームのビルドの出所情報がランタイムに付属します。 クライアントとトラストストアは、app.asar の外にある `resources/native-runtime/-/` にインストールされます。診断を実行するたびに、使用前にコンポーネントのハッシュ、アーキテクチャ、実行ファイルの機能を検証します。設定ファイル、プロキシ、TLS の信頼に関する環境変数による上書き、ライブラリのインジェクション用変数は除外されます。curl は、絶対パス、シェルの無効化、検証済みの CA による信頼、明示的に解決した IP アドレスファミリーを使い、Cookie なし、自動リダイレクトなし、出力と時間を制限して実行されます。リダイレクトはアプリケーションが検証し、名前解決をやり直します。443 以外のポートでの HTTPS にも対応しています。 HTTP/3 は `--http3-only` を使用し、HTTP バージョン 3 が報告され、証明書の検証にも成功した転送が完了した場合にのみ確認されます。404 のような HTTP エラー応答でも、プロトコルの確認になります。Alt-Svc は告知であり、証明ではありません。QUIC のタイムアウト、証明書のエラー、DNS のエラー、接続の拒否、互換性のないプロトコル、コンポーネントの障害は、それぞれ区別されます。UDP のタイムアウトでは、サーバーの対応状況は未確認のままです。QUIC のハンドシェイク時間が TCP の時間として報告されることはありません。 計測ごとに個別のプロセス/接続を開始します。warm オプションは、同梱クライアントで接続が再利用されたとはみなしません。これにより、プロトコルの比較に一貫性が保たれます。レポートにはランタイムのバージョン、機能、TLS の検証、QUIC のタイミングが含まれ、履歴/エクスポートでは本文、URL のクエリ、認証ヘッダーが削除されます。 トランスポートスタックや CA のトラストストアを更新するときは、これらの固定値を更新し、対応するすべてのプラットフォームでビルドし直してください。公開済みの成果物とソースのスナップショットは変更されません。 ## Core IPC Preload が公開するのは `window.chjCore.diagnostics` だけです。すべてのハンドラーは既存のメインウィンドウの送信元チェックを維持し、ネットワーク処理はメインプロセスで行われます。結果には `{ ok: true, value }` または `{ ok: false, error: { code, message } }` を使います。 | チャネル / preload のメソッド | ペイロード / 結果 | | --- | --- | | `diagnostics:resolve` / `resolve(options)` | 検証済みの対象/設定 → 対象と解決したアドレス。同時に処理できる解決リクエストは最大 2 件です。 | | `diagnostics:start` / `start(options)` | 検証済みの対象/設定/ツールの選択 → 不透明なジョブ ID と初期レポート。 | | `diagnostics:cancel` / `cancel(id, tool?)` | 実行中/待機中のツール 1 つ、または実行全体をキャンセルします。 | | `diagnostics:get` / `get(id)` | 既知の実行、または保存済みレポートのスナップショット。 | | `diagnostics:history` / `history()` | ローカルの履歴の概要。 | | `diagnostics:removeHistory` / `removeHistory(id)` | 選択した履歴の項目を削除します。 | | `diagnostics:copy` / `copy(id, format)` | メインプロセスが、マスキング済みの既知のレポートをクリップボードに書き込みます。 | | `diagnostics:export` / `export(id, format)` | ネイティブの保存ダイアログで JSON/CSV/TXT にエクスポートします。レンダラーがファイルシステムのパスを指定することはできません。 | | `diagnostics:import` / `import()` | ネイティブのファイル選択、保存前のサイズ/スキーマ/深さの検証とマスキング。 | | `diagnostics:progress` / `onProgress(callback)` | 解決したアドレス、ツールの開始/完了、パケット、ホップ、HTTP のサンプル、完了。購読を解除するコールバックを返します。 | 汎用のシェル、ファイルシステム、ネットワークの API は公開しません。コンテキストの分離、サンドボックス、Node 統合の無効化、既存のレンダラーの CSP は有効なままです。既存のプラグインとの取り決めや、アップデーターの検証/例外は変更していません。 ## 予算とローカルデータ - 実行は 1 つ、同時に動くツールは 2 つまで、ツールごとのプローブは IP アドレスファミリー 2 つまでです。TCP では、さらに 1 つのアドレスにつき 4 接続までに制限しています。 - 操作ごとのタイムアウトは 250–30000 ms、パケットは 1–100、繰り返しは 1–20、ホップは 1–40、ポートは 1–16 です。通常の実行は 5 分、連続 ping は 30 分で停止します。traceroute のサブプロセスには、さらに 180 秒の上限があります。 - プロセスの出力は通常 256 KiB、HTTP のエンティティ本文は 2 MiB、展開後の本文は 8 MiB で、HTTP ヘッダーにも上限があります。レスポンス本文が履歴に入ることはありません。 - 保持するのは最大 500 件のパケット/進捗イベント、メモリ内の 5 件の実行、30 件の履歴レポート、10 MiB の履歴です。履歴は、既存の非公開のアトミックな書き込み処理で `/diagnostics/history.json`(モード 0600)に保存されます。 - インポートできるのは最大 2 MiB、スキーマ 1 で、入れ子の深さが制限され、結果のコレクションが検証されたものです。CSV のセルはエスケープされ、数式の接頭辞は無害化されます。URL のクエリ/フラグメント、認証情報、Cookie、認証ヘッダー、生の本文は、保存/コピー/エクスポートするレポートから除外されます。生の詳細に表示されるのは計測した構造化データで、パケットキャプチャや保持されたレスポンス本文ではありません。 - クラウド同期、自動ログイン、サーバー設定の変更、攻撃的/無制限のスキャンは行いません。対象/ポート/リゾルバーはユーザーが明示的に選びます。 ## プラットフォームの要件と検証 | プラットフォーム | ICMP | 経路 | その他のプロトコル | | --- | --- | --- | --- | | Windows 10/11 | `ping.exe -4/-6` | `tracert.exe -4/-6`、ICMP | HTTP/2 と HTTP/3 に対応した同梱の curl.exe。ローカライズされた RTT の項目が「time」という単語に依存することはありません。 | | macOS | `/sbin/ping`、`/sbin/ping6` | `/usr/sbin/traceroute`、`/usr/sbin/traceroute6`、UDP、整数秒の待ち時間 | HTTP/2 と HTTP/3 に対応した同梱の curl。 | | Ubuntu/Linux | iputils の `ping -4/-6` | 標準の `traceroute -4/-6`、UDP | HTTP/2 と HTTP/3 に対応した同梱の curl。ICMP/経路のツールがない場合は個別に報告されます。 | 新しい npm の依存関係は追加していません。実装には、Node の組み込みモジュールとアプリケーションの既存の ssh2 を使用しています。システムのツールをインストールすることも、管理者権限を要求することもありません。ファイアウォールや UDP の制限によって、テストで対応状況を確認できないことがあります。タイムアウトだけから、それらを推測することはできません。 自動テストは `diagnosticsCore.test.js`、`diagnosticsNetwork.test.js`、`diagnosticsHttp.test.js`、`diagnosticsIpc.test.js` にあり、次を網羅しています:検証/IPv6 リテラル、ネイティブ/ローカルの DNS UDP+TCP のフィクスチャ、応答の欠落/2 ファミリーの応答とリゾルバーのエラー、CNAME/整合性、OS の引数/解析のフィクスチャ、範囲を限定した実際の子プロセス、ブロックされた ICMP の観測、実際のローカルの HTTP/1.1 と TLS h2、リダイレクト/本文の制限/タイムアウト/再利用、圧縮の有効/無視、HTTP3 の機能/成功結果の解析/フォールバックの拒否、ローカルの CA の信頼/不一致/期限切れと実際の IPv6 HTTP/HTTPS、TCP の接続/拒否/モックのタイムアウト、実際の WebSocket と SSH の認証前ハンドシェイク、キャンセル/後始末/部分的な結果、オフラインの状態、非公開の履歴の往復/インポートの拒否/エクスポート、信頼された IPC と preload の購読。 `npm test` は、公開のテストサーバーを使わずに決定的なテストを実行します。`npm run test:diagnostics:ui` は、グラフィカルな Electron のデスクトップで `scripts/smokeDiagnostics.js` を実行し、本番の UI/preload/IPC と、実際のローカルでの HTTP/圧縮のプローブを使用します。このテスト環境に限り、関係のないサービスはスタブ/オフラインにしています。ナビゲーションの順序、プロトコルの結果、永続化、CZ/DE/EN、両方のテーマ、狭いウィンドウでのはみ出し、サンドボックスの設定を確認します。シェルで ELECTRON_RUN_AS_NODE が設定されている場合は、このコマンドを実行する際に解除してください。 現在のランタイムの検証では、管理された環境での QUIC 転送、IPv4/IPv6、既定以外のポートでの HTTPS、404 応答、TLS の失敗、Alt-Svc を告知する TCP のみのサービスを確認しています。ビルドごとの結果は各リリースに付属します。 明示的な任意の制限:独立した DNSSEC の検証は行いません(完全な検証用リゾルバー/トラストアンカーのライフサイクルが必要なため)。Lighthouse による監査も行いません(サーバー/ネットワークの所要時間のみ)。非推奨の TLS の監査や失効/CT サービスの確認、HTTP3 のウォーム接続での再利用の主張、HTTP/3 のウォーム接続での再利用の計測も行いません。対応していない機能は、シミュレーションせずにそのまま表示します。 ## この変更に含まれるファイル 新規作成:`src/main/diagnostics/` の 7 つのサービスファイル、`src/renderer/diagnostics.js`、`diagnosticsI18n.js`、`diagnostics.css`、4 つの `test/diagnostics*.test.js` ファイル、`test/fixtures/diagnostics/` 配下の 5 つのファイル、`scripts/smokeDiagnostics.js`、このドキュメント。 統合/更新:`src/main/index.js`、`src/main/ipc/registerCoreIpc.js`、`src/preload/corePreload.js`、`src/renderer/index.html`、`app.js`、`i18n.js`、`package.json`、`app/README.md`、ルートの `README.md`、`.gitignore`(公開用フィクスチャの 4 つの例外)、そして意図的に公開している TLS テスト鍵のフィクスチャだけを限定的に指定した、ルートの gitleaks の許可リスト。署名用 CA の秘密鍵は破棄しました。このフィクスチャがアプリケーションのランタイムで使われることはありません。