heymaikol/network-doctor

GitHub: heymaikol/network-doctor

一款跨平台终端网络诊断工具,通过依赖图逐层探测 DNS、TCP、TLS、HTTP 及代理路径,用通俗语言精准定位连接断点并建议修复方案。

Stars: 15 | Forks: 0

# 网络 Doctor 这是一个终端 UI 工具,用于诊断您的网络连接,并用通俗易懂的语言告诉您**连接断在哪里**——而不仅仅是输出一大堆工具日志。 ![Network Doctor 诊断 github.com:443](https://static.pigsec.cn/wp-content/uploads/repos/cas/eb/ebc20585edb4fb33ef8f7c43a7256bf8e6eb4127f0ccc10d1bc9365d1cbfbb03.gif) ## 安装 可运行于 **Linux、macOS 和 Windows**。项目名为 `network-doctor`;安装后的二进制文件为 `netdoc`。 ### Arch Linux (AUR) [`network-doctor`](https://aur.archlinux.org/packages/network-doctor) 软件包会从源码构建: ``` yay -S network-doctor # or: paru -S network-doctor ``` 或者在不使用 AUR 助手的情况下手动构建: ``` git clone https://aur.archlinux.org/network-doctor.git cd network-doctor makepkg -si ``` ### macOS (Homebrew) 使用 Homebrew 安装可以避免 Gatekeeper 的“未经验证的开发者”提示: ``` brew tap heymaikol/tap brew install --cask network-doctor ``` ### 其他平台 从[最新发布版本](https://github.com/heymaikol/network-doctor/releases/latest)下载预构建的二进制文件,或使用 Go 1.26+ 安装: ``` go install github.com/heymaikol/network-doctor@latest ``` (`go install` 会按照模块名将二进制文件命名为 `network-doctor`;如果需要,您可以将其重命名为 `netdoc`。)使用 `netdoc --version` 查看正在运行的版本。 或者从克隆的代码构建: ``` git clone https://github.com/heymaikol/network-doctor cd network-doctor go build -o netdoc . ``` ## 诊断原理 探针构成了一个**具有独立分支的依赖图**,因此不相关的失败永远不会掩盖正常工作的部分: - **直接出口路径**(独立于 DNS):`Interface → Internet (TCP egress)`。始终运行,因此“DNS 宕机但互联网正常”的情况也可以被诊断出来。 - **代理出口路径**(独立于上述两者):`Interface → Internet (env proxy)`。原生探针有意绕过代理,因此该行会单独报告环境配置的代理——在仅使用代理的企业网络中,状态会显示为“通过代理在线”而不是离线。 - **普通 HTTP 路径**:`Interface → DNS → HTTP :80`。 - **选定目标路径**:对于安全的 Web 目标为 `Interface → DNS → TCP → TLS → HTTPS`,或对于其他端口显示适用的协议行。 每一行都处于以下五种状态之一:**✓ Pass**、**! Warn**(可达但性能下降——高延迟、部分地址解析失败、源接口不明确)、**✗ Fail**、**⊘ Skip**(前置条件失败)或 **– N/A**(不适用——例如字面量 IP 上的 DNS)。Warn 永远不会算作失败。 | 探针 | 通过条件 | 备注 | |-------|-------------|-------| | **Interface** | 非环回接口已启动并运行 | | | **Internet (TCP egress)** | 成功建立到知名任播 `:443` 端点的 TCP 连接 | IPv4 和 IPv6 并行独立探测;任一协议族通过即算通过,同时报告两者的状态 | | **Internet (env proxy)** | `HTTPS_PROXY`/`HTTP_PROXY` 代理授予 `CONNECT` 隧道 | 未配置代理时为 N/A;遵循 `NO_PROXY` 设置 | | **DNS** | 主机解析为 IPv4 或 IPv6 地址(系统解析) | 字面量 IP 目标为 N/A;保留所有 A/AAAA 记录 | | **TCP** | 成功建立到目标端口的 TCP 连接 | 竞速 A/AAAA 记录(Happy-Eyeballs 风格,RFC 8305),锁定获胜的地址 | | **TLS** | TLS 握手(SNI + 证书验证)成功 | 错误/过期证书、时钟偏差或中间人攻击 (MITM) → Fail | | **HTTP** | 80 端口返回任何 HTTP 响应(包括 3xx/4xx/5xx) | 在 DNS 解析后独立发起 HEAD 请求,关闭重定向,关闭代理 | | **HTTPS** | 选定的 TLS 端口返回任何 HTTP 响应 | 针对通过 TLS 验证的 IP 发起 HEAD 请求,关闭重定向,关闭代理 | | **SSH/SMTP banner** | TCP 连接成功(尽最大努力读取横幅) | 限时读取;已连接但无响应 → Warn(不算作失败) | RTT 是通过 TCP 连接握手测量的(无需 ICMP,无需 root 权限)。源 IP 和接口是从获胜连接的 `LocalAddr` 中读取的,在连接失败时则使用 UDP 连接回退(不发送数据包)来确定路径身份。每个探针都受限于 4 秒的超时时间。 ## 用法 ``` netdoc # generic local + internet diagnosis netdoc github.com # diagnose the path to a host (→ HTTP + TLS + HTTPS) netdoc github.com:22 # port selects the protocol rows (→ SSH banner) netdoc https://host:80 # explicit scheme selects the protocol (→ TLS + HTTPS on :80) netdoc --json host # headless: one JSON report on stdout (scripts, CI, bug reports) ``` `--timeout` 会覆盖每次检查的探针超时时间;请参阅 `netdoc --help` 获取默认值。 目标解析器有两个独立的维度:**端口**(显式指定 `:port` > scheme 默认值 > 443)和**协议行**(显式指定的 `http`/`https` scheme 优先;否则根据端口推断——`443/8443`→HTTP+TLS+HTTPS,`80`→HTTP,`22`→SSH,`25/587`→SMTP)。主机会经过严格的白名单验证;接受裸露的 IPv6 字面量(`::1`)或带端口的括号形式(`[::1]:443`)。 | 按键 | 动作 | |-----|--------| | `↑`/`↓` (`k`/`j`) | 选择探针行 | | `v` | 运行局域网扫描并显示本地私有 `/24` 网段的网络映射图(无需特权即可运行的 `nmap`) | | `enter` | 在可滚动的全屏查看器中打开当前工具任务的输出 | | `y` (查看器中) | 复制查看器保留的完整输出(最多 5,000 行) | | `r` | 重启——打开提示符以编辑 `netdoc` 参数(`enter` 运行,`esc` 退出) | | `y` / `w` | yank / write (复制 / 保存) 包含诊断链和已完成工具输出的报告 | | `q` | 退出 | ## 深入分析工具 诊断中的每一行都是*证据*;当您需要确凿的证明时,可以运行真实的工具作为可取消的流式任务(一次只能运行一个)。上下文工具箱显示了当前目标可用的工具及其快捷键——缺失的二进制文件会显示为灰色,并附带安装提示。输出内容是有界限且经过净化的(防止来自恶意服务器的终端转义注入);工具运行完成后,最后的 15 行输出将被包含在报告中。 相同的快捷键对应于每个操作系统内置的工具: | 按键 | Linux | macOS | Windows | |-----|-------|-------|---------| | `i` | `ip route` | `netstat -rn` | `route print -4` | | `s` | `ss -tunp` | `netstat -an -p tcp` | `netnet -ano` | | `p` | `ping -c 4 -W 2` | `ping -c 4` | `ping -n 4 -w 2000` | | `d` | `dig +time=2 +tries=1` | `dig +time=2 +tries=1` | `nslookup` | | `c` | `curl … -w '…'` (简洁摘要) | 同左 | `curl.exe` (绕过 PowerShell 5.1 的 `curl` 别名) | | `c` (SSH 目标) | `ssh -v -o BatchMode=yes …` (限时的横幅/握手检查) | 同左 | 同左 | | `c` (SMTP 目标) | `openssl s_client -starttls smtp` | 同左 | 同左 | | `t` | `traceroute -w 2 -q 1 -m 20` | 同左 | `tracert -w 2000 -h 20` | | `m` | `mtr --report --report-cycles 5` | 同左 (通过 brew) | `pathping -h 20 -q 5 -p 100 -w 500` (自带的 90 秒时间预算) | | `n` | `nmap -sT -T2 -Pn` (显式指定目标端口,否则扫描前 100 个) | 同左 | 同左 | `n` 在其主动探针运行前需要经过明确的确认。它使用带有礼貌计时的普通连接扫描,且不进行版本/操作系统检测。`v` 会立即进行主机发现,无需原始套接字或 root 权限,并将范围限制在源地址的 `/24` 网段内。 `c` 槽位具有协议感知能力:HTTP(S) 和未知端口的目标会使用 `curl`,而 SSH (端口 22) 和 SMTP (端口 25/587) 的目标则会使用符合其协议的握手探针——绝不会使用面向 HTTPS 的 `curl` 命令行。SSH 检查使用一次性的已知主机文件(无提示,不写入文件),并且在密钥碰巧通过身份验证时运行一个简单的 `exit`。 路由/套接字工具是独立于目标的;其他工具则需要指定主机。工具会通过参数切片(绝不是 shell 字符串)运行,在 Unix 上运行于各自的进程组中(取消操作也会同时终止子进程),并且不会进行权限提升。显示的命令可以在 POSIX shell(Linux/macOS)或 PowerShell(Windows;不支持 cmd.exe 粘贴)中直接复制使用。 `--toolbox []` 会直接进入工具箱,而不会自动运行诊断链(按 `r` 运行)。如果没有指定主机,则仅提供与目标无关的工具。 ### JSON 输出 `--json` 会以无头模式运行相同的探针 DAG——没有 TUI——并向 stdout 打印一个 JSON 文档: ``` { "version": "1.2.3", "target": {"host": "github.com", "port": 443, "protocol": "tls+http"}, "checks": [ {"id": "dns", "name": "DNS github.com", "status": "PASS", "detail": "github.com → 140.82.113.3", "addrs": ["140.82.113.3"]} ], "summary": "All checks passed — github.com:443 looks healthy.", "ok": true } ``` `status` 是 `PASS`、`WARN`、`FAIL`、`SKIP`、`N/A` 其中之一。在通用(无目标)模式下,`target` 为 `null`。如果为空,则省略可选的逐项检查字段(`fix`、`addrs`、`selected_ip`、`source`、`iface`、`network`、`attempts`)。字段名称和状态词汇是稳定的——可以放心使用脚本进行解析。退出码遵循下表规定(`ok: false` ⇒ 退出码 `1`)。 ### 退出码 | 情况 | 退出码 | |---|---| | 诊断链已完成,没有失败的行(允许 Skip) | `0` | | 任何失败的行 | `1` | | 诊断链完成前退出 | `1` | | 错误的参数 / 验证被拒绝 | `2` | ``` netdoc github.com || echo "path to github is broken" ``` ## 平台支持 所有的探针、诊断引擎和 TUI 都是纯 Go 编写的,并且在 Linux、macOS 和 Windows 上的表现完全一致。特定平台的辅助信息(默认网关、Wi-Fi SSID)在 Linux 上直接使用内核(`/proc/net/route`、无线 ioctl),在其他系统上则使用操作系统内置的命令(macOS 上使用 `route`/`networksetup`,Windows 上使用 `route print`/`netsh wlan`);当这些命令失败时,相应字段会降级为空,而不会导致探针失败。 **Windows 本地化注意事项**:控制台工具会输出 OEM 代码页,因此原始工具输出中的非 ASCII 本地化文本会显示为可见的 `?` 替换字符。所有关键内容(路由表单元格、未翻译的 `SSID` 标签、nslookup 地址)的解析均与本地化设置无关。 ## 路线图 已实现:原生 DAG 探针 + 诊断引擎 + 双窗格 UI、可取消的流式工具任务(`ping`/`dig`/`curl`/`traceroute`/`mtr`/`ss`/`ip`/`nmap`)+ 可滚动的输出查看器 + `--toolbox` 模式、`Warn` 状态、支持代理感知的诊断、`--json` 输出,以及报告的复制/保存。 即将推出:mtr 解析的路由质量评估以及对多个并发任务的支持。 ## 构建基于 [Bubble Tea](https://github.com/charmbracelet/bubbletea)、 [Bubbles](https://github.com/charmbracelet/bubbles) 和 [Lip Gloss](https://github.com/charmbracelet/lipgloss)。 ## 测试 ``` go test ./... # unit + DAG scheduler + parser + diagnosis go test -race ./... # concurrency go test -fuzz=FuzzSanitize -fuzztime=10s # terminal-escape sanitizer ``` ## 开发 代码按职责进行了拆分: - `main.go` 负责 CLI 参数、进程 I/O 和应用程序启动。 - `internal/diagnostic` 负责目标解析、原生探针、基于操作系统的路由/SSID 查询以及判定逻辑,且不依赖于终端展示层。 - `internal/ui` 负责 Bubble Tea 状态、渲染和工具任务。 - `internal/textsafe` 负责净化由这两层共享的、不受信任的远程及子进程文本。 UI 依赖于诊断层;诊断层不依赖于 UI。请在 `internal/diagnostic` 中添加网络语义相关的代码,并在 `internal/ui` 中添加交互或渲染行为相关的代码。
标签:EVTX分析, Go语言, TCP/IP, TUI, 情报分析, 日志审计, 程序破解, 网络诊断, 运维工具