Files
cs-note/hhs/NETWORK/07-网络工具与诊断/01-连通性与状态探测工具.md
T
2026-05-24 11:42:38 +08:00

225 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
tags: [计算机网络, ping, traceroute, ss, telnet, nc, netstat]
create time: 2026-05-18 04:45
---
# 连通性与状态探测工具
## 概述
排查网络问题时,正确的第一步是判断"到底通不通"。本章覆盖从物理连通性到应用端口层的基础探测工具。
## ping —— ICMP Echo Request/Reply
### 基本用法速查
```bash
$ ping -c 4 example.com # 发 4 个包后自动停止
$ ping -i 0.2 example.com # 每 0.2s 发一个(需 root)
$ ping -s 1472 example.com # 载荷 1472 bytes (接近 MTU 1500)
$ ping -t 64 example.com # 指定初始 TTL
$ ping -q example.com # 静默模式,仅显示统计摘要
$ ping -W 2 example.com # 每个包的超时等待 2 秒
```
### 解读输出指标
```
PING example.com (93.184.216.34) 56(84) bytes of data.
64 bytes from 93.184.216.34: icmp_seq=1 ttl=56 time=14.2 ms
64 bytes from 93.184.216.34: icmp_seq=2 ttl=56 time=13.8 ms
--- example.com ping statistics ---
packets transmitted: 2 # 发送包数
packet loss: 0% # 丢包率
rtt min/avg/max/mdev = 13.8/14.0/14.2/0.2 ms # 往返时间统计
```
| 指标 | 含义 | 合格阈值 |
|------|------|---------|
| packet loss | 丢包率 | 0% ~ 0.1%(局域网不应有丢包)|
| rtt avg | 平均 RTT | LAN < 1ms / 同城 < 20ms / 跨省 30-80ms / 跨洋 80-150ms |
| mdev | RTT 标准差 | < 5ms 正常;抖动大说明拥塞或不稳定 |
> [!warning] ping 不通 ≠ 网络故障
>
> 很多服务器禁用了 ICMP Echo Reply(防火墙策略),此时 ping 不通不代表服务不可用。需要结合 `telnet port` 或 `curl` 综合判断。
```bash
# Linux 内置的 ICMP 防御(防 DDoS flood)
$ sysctl net.ipv4.icmp_ratelimit=1000 # 每秒最多处理 1000 个 ICMP 包
$ sysctl net.ipv4.icmp_ratemask=65535 # 允许的 ICMP 类型掩码
$ sysctl net.ipv4.icmp_echo_ignore_all=1 # 完全忽略所有 ping(极端场景)
```
## telnet / nc —— 端口连通测试
### telnet —— 最原始的端口探测
```bash
# 纯测试端口是否开放
$ telnet example.com 80
Trying 93.184.216.34...
Connected to example.com. # ← Connected = 端口开放 ✅
Escape character is '^]'.
# 手动发 HTTP 请求测试
GET / HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Accept: */*
(blank line 回车)
HTTP/1.1 200 OK # ← 收到响应 = 链路完整 ✅
Content-Type: text/html
...
```
### nc (Netcat) —— 更强大的瑞士军刀
```bash
# 仅测试端口连通 (-z = zero-I/O 模式)
$ nc -zv example.com 80
Connection to example.com port 80 [http] succeeded! # ✅ TCP 3次握手成功
$ nc -zv example.com 443
Connection to example.com port 443 [https] succeeded! # ✅
$ nc -zv example.com 8443
nc: connect to example.com port 8443 (tcp): Connection refused # ❌
# 发送数据并等待响应
$ echo "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n" | nc -w 2 example.com 80 | head -5
# DNS 反向查询
$ nc -dvl 0.0.0.0 12345 # 监听模式
$ nc -u -z localhost 53 # UDP 端口测试 (DNS 常用)
```
## ss —— 连接状态快照(取代 netstat)
### ss 基础用法
```bash
# 查看所有 TCP 连接(数字格式,不解析域名)
$ ss -tan
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
ESTAB 0 0 192.168.1.10:45678 93.184.216.34:443 users:(("chrome",pid=1234,fd=42))
SYN-SENT 0 1 192.168.1.10:54321 10.0.0.1:8080 # 正在尝试握手
LISTEN 0 128 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=5678,fd=6))
TIME-WAIT 0 0 192.168.1.10:443 93.184.216.34:52341 # 等待 2MSL
# 查看特定端口的监听
$ ss -tlnp sport = :80
LISTEN 0 128 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=5678,fd=6))
# 查看所有 TIME_WAIT 连接数(高并发服务器常见问题)
$ ss -tan state time-wait | wc -l
1247
# 查看某进程的所有连接
$ ss -tnp | grep nginx | wc -l
# 诊断 CLOSE_WAIT 堆积(⚠️ 代码 Bug!)
$ ss -tan state close-wait
CLOSE-WAIT 0 0 server:8080 client:54321 # ← 对端已关闭,本地未 close()!
```
### ss 状态速查表
| ss 状态 | 含义 | 严重程度 |
|---------|------|---------|
| ESTABLISHED | 正常通信中 | ✅ 正常 |
| LISTEN | 等待接受连接 | ✅ 正常 |
| SYN-SENT | 客户端发出的 SYN 未收到回复 | ⚠️ 检查对端是否存活 |
| SYN-RECV | 收到 SYN 但未完成三次握手 | ⚠️ 可能 SYN Flood |
| TIME-WAIT | 己方主动关闭后等待 2MSL | ⚠️ 可调 tcp_tw_reuse |
| CLOSE-WAIT | 对端关闭但己方未 close() | 🔴 **Bug!** 检查代码 |
| LAST-ACK | 等待最后一个 ACK | ⚠️ 短暂状态,持续则异常 |
| CLOSING | 同时关闭,互等对方 ACK | ⚠️ 罕见 |
```bash
# 按状态过滤
$ ss -tan state established # 仅已建立
$ ss -tan state syn-sent # 仅半连接中
$ ss -tan state closing # 仅 CLOSING
# 按源/目标 IP 过滤
$ ss -tn daddr 10.0.0.0/8 # 只看内网连接
$ ss -tn src :80 # 只看来自 80 端的
```
> [!tip] ss vs netstat
> `ss` 使用 netlink socket 替代 `/proc/net/tcp`,速度更快、信息更全。Linux 5.x+ 系统上 netstat 已被标记为 deprecated。
## traceroute —— 逐跳路径探测
### 三种实现方式
```bash
# UDP 模式(默认)—— 向高端口发 UDP 包递增 TTL
$ traceroute -n example.com
1 192.168.1.1 0.5ms 0.3ms 0.4ms
2 10.0.0.1 10.2ms 9.8ms 10.1ms
12 93.184.216.34 45.1ms 44.8ms 45.0ms
# ICMP 模式(更可靠,不容易被防火墙拦截)
$ traceroute -I example.com
# 现代替代:tracepath(不需要 root,自动 PMTUD)
$ tracepath example.com
1: 192.168.1.1 0ms reached
2: 10.0.0.1 10ms
...
12: 93.184.216.34 45ms Ascent peak pmtu 1452
```
### traceroute 原理
```mermaid
flowchart LR
P1["TTL=1 → 第1跳路由器<br/>回 ICMP Time Exceeded"] -->|"RTT₁"| R1["第1跳: 192.168.1.1"]
P2["TTL=2 → 第2跳路由器<br/>回 ICMP Time Exceeded"] -->|"RTT₂"| R2["第2跳: 10.0.0.1"]
P3["TTL=N → 到达目标<br/>回 ICMP Port Unreachable"] -->|"RTTN"| Rn["目的地: 93.184.216.34"]
style R1 fill:#DDA0DD,color:#000
style R2 fill:#FFD700,color:#000
style Rn fill:#98FB98,color:#000
```
```bash
# 识别路由问题
$ traceroute -n 8.8.8.8
...
5 * * * # ← 这里丢了?→ 路由器禁了 ICMP
6 * * * # ← 可能是运营商之间互联点
7 108.170.xxx.xxx 50ms 48ms 51ms # ← 回到 Google 边缘
# Windows 等价命令
tracert 8.8.8.8
# macOS 等价命令
traceroute 8.8.8.8
```
## 排错黄金思路回顾
```
问题: 无法访问服务
↓
ping 通吗? → 否 → traceroute 定位断在哪一跳
↓ 是
telnet port 通吗? → 否 → 检查防火墙/selinux → ss 看是否监听
↓ 是
curl 正常吗? → 否 → 应用层问题 → 读日志
↓ 是
浏览器缓存/Cookie/Header 问题
```
## 关联笔记
- [[hhs/NETWORK/ICMP与Ping-Traceroute]] — ping/traceroute 的协议底层原理
- [[hhs/NETWORK/TCP三次握手与四次挥手]] — ss 中看到的状态都对应 TCP 状态机中的某个节点
- [[hhs/NETWORK/DNS与DHCP与WebSocket]] — DNS 解析慢会影响 ping/curl 的表现
- [[hhs/NETWORK/抓包HTTPDNS诊断工具]] — 进一步分析可用 tcpdump/curl/dig