Core 사이드바에 Plugins → Server Diagnostics → Hash & Checksum 순서로 통합되어 있습니다. SSH 세션이나 다운로드한 플러그인이 필요하지 않습니다. 모든 런타임 코드, 테스트, 픽스처는 app/에 있으며, 이 모듈은 인접 저장소에 의존하지 않습니다. 저장소에 doc.md가 없으므로 이 문서와 두 README가 구현을 설명합니다.
사용자 작업 흐름
호스트 이름, IPv4, IPv6 또는 HTTP(S)/WS(S) URL을 입력하세요. 호스트 이름/IP만 입력하면 기본적으로 HTTPS를 사용하고, URL을 명시하면 요청하는 동안 경로, 쿼리, 포트가 유지됩니다. URL 안의 자격 증명, 지원되지 않는 스킴, 공백/제어 문자, 셸 같은 호스트 이름은 거부됩니다. IPv6 리터럴에는 자동으로 대괄호가 붙으며, 범위가 지정된/링크 로컬 영역 식별자는 URL 파서에서 지원하지 않습니다.
Auto(IPv4 우선, 안 되면 IPv6), IPv4, IPv6 또는 Both를 선택하세요. '주소 확인'을 사용하면 현재 응답 중 특정한 것을 고를 수 있습니다. 개요에는 확인된 모든 응답이 표시되며, 프로브는 선택한 주소 또는 요청한 주소 계열마다 하나의 주소를 테스트합니다. 두 주소 계열은 각각 독립적으로 측정됩니다. AAAA 레코드가 있다는 것만으로 IPv6 연결이 작동한다는 뜻은 아닙니다.
Run Diagnostics(진단 실행)는 DNS, ping, traceroute, HTTP, 압축, TLS, 선택한 TCP 포트를 점검합니다. WebSocket은 직접 선택해야 실행됩니다. 각 도구에는 별도의 실행/중지 버튼도 있습니다. 한 번에 하나의 진단만 실행할 수 있습니다. 실행이 완료되었다는 것은 도구들이 끝났다는 뜻일 뿐, 모든 프로브가 성공했다는 뜻이 아닙니다. 일괄적인 '서버 오프라인' 판정은 없습니다.
시간 제한, 패킷 수, 반복 횟수, 최대 홉 수, DNS 확인자, 프로토콜 선택, 웜 연결, HTTP/HTTPS 비교를 설정할 수 있습니다. 대상을 바꾸면 이전에 선택한 IP가 지워집니다. 기록에서는 다시 열기, 두 보고서 비교, 삭제, JSON 가져오기, 복사, 네이티브 Core 대화 상자를 통한 JSON/CSV/TXT 내보내기가 가능합니다. 밝은/어두운/시스템 테마는 진단 섹션에 적용되고 기존 UI 설정에 저장됩니다. CZ/DE/EN 표시는 애플리케이션 언어를 즉시 따릅니다.
구성 요소 및 프로토콜 동작
| 구성 요소 | 구현 및 해석 |
|---|---|
common.js |
대상/옵션, 제한, 열거 값을 검증하고 IDNA 변환을 수행합니다. 숫자 통계에서는 알 수 없는 값을 제외합니다. |
dnsDiagnostics.js |
시스템 주소 확인에는 운영체제 설정과 hosts 파일을 따르기 위해 dns.lookup을 사용합니다. 레코드 쿼리는 제한된 UDP DNS를 사용하고 응답이 잘린 경우 TCP로 대체하며, 대상은 dns.getServers() 또는 명시적으로 선택한 사용자 지정/공용 확인자입니다. 공용 DNS로 암묵적으로 전환하지 않습니다. |
processTools.js |
운영체제의 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은 기본적으로 개별 실행되는 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 상태가 보존됩니다. 운영체제 주소 확인으로는 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 단계는 가짜 0이 아니라 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 기능이 없으면 실패합니다. 운영체제 라이브러리만 동적으로 남습니다. Windows는 로컬에서 컴파일한 Windows 전송 스택이 아니라 고정된 공식 바이너리 압축 파일을 사용합니다. 번들 CA 파일에는 별도로 고정된 해시가 있으며, 구성 요소 라이선스와 업스트림 빌드 출처 정보가 런타임과 함께 제공됩니다.
클라이언트와 신뢰 저장소는 app.asar 바깥의 resources/native-runtime/<platform>-<arch>/에 설치됩니다. 진단할 때마다 사용 전에 구성 요소 해시, 아키텍처, 실행 파일 기능을 검증합니다. 설정 파일, 프록시, TLS 신뢰 관련 환경 변수 재정의, 라이브러리 주입 변수는 제외됩니다. curl은 절대 경로, 셸 비활성화, 검증된 CA 신뢰, 명시적으로 확인된 IP 주소 계열로 실행되며, 쿠키와 자동 리디렉션 없이 출력과 시간을 제한합니다. 리디렉션은 애플리케이션이 검증하고 다시 확인합니다. 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?) |
실행 중/대기 중인 도구 하나 또는 전체 실행을 취소합니다. |
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개, 도구당 최대 2개의 IP 주소 계열 프로브. TCP는 추가로 주소당 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를 보관합니다. 기록은 기존의 비공개 원자적 쓰기 기능으로
<userData>/diagnostics/history.json(모드 0600)에 저장됩니다. - 가져오기는 최대 2 MiB, 스키마 1이며, 중첩 깊이가 제한되고 결과 컬렉션이 검증됩니다. CSV 셀은 이스케이프되고 수식 접두사는 무력화됩니다. URL 쿼리/프래그먼트, 자격 증명, 쿠키, 인증 헤더, 원시 본문은 저장/복사/내보내기 보고서에서 제외됩니다. 원시 세부 정보에는 측정된 구조화 데이터가 표시되며, 패킷 캡처나 보관된 응답 본문이 아닙니다.
- 클라우드 동기화, 자동 로그인, 서버 설정 변경, 공격적/무제한 스캔은 없습니다. 대상/포트/확인자는 사용자가 명시적으로 선택합니다.
플랫폼 요구 사항 및 검증
| 플랫폼 | 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 픽스처, 누락/이중 계열 응답과 확인자 오류, CNAME/일관성, 운영체제 인수/분석 픽스처, 제한된 실제 하위 프로세스, 차단된 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, test/diagnostics*.test.js 파일 4개, 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 개인 키는 폐기했으며, 이 픽스처는 애플리케이션 런타임에서 사용되지 않습니다.