路线图

网络诊断工具

星辉 2026-07-02 阅读 7 min 1,389 字 路线图
网络诊断工具 封面

Linux 运维基础 · 第十一章 目标:掌握从连通性到应用层排查网络问题的全套工具


1. 概述#

运维排障的金字塔:从底层到应用层依次检查。网络排障贯穿全部。

text
应用层 (HTTP)    → curl / wget
传输层 (TCP/UDP) → ss / nc / telnet
网络层 (IP)      → ping / traceroute / mtr / ip route
链路层           → ip link / ethtool
DNS              → dig / resolvectl

工具选型(2026):现代发行版(Rocky/Alma 9、Ubuntu 22.04+)默认已不再预装 net-toolsnetstat/ifconfig/route),改用 iproute2ss/ip)。 本章一律以 ss/ip/resolvectl 为首选,netstat/ifconfig/nslookup 仅作对照。


2. 连通性测试#

2.1 ping — 通了没?#

bash
ping 8.8.8.8                        # 发 ICMP Echo Request
ping -c 4 8.8.8.8                   # 只发 4 个包(不然 Ctrl+C 才停)
ping -i 0.5 8.8.8.8                 # 每 0.5 秒发一个
ping -s 1400 8.8.8.8                # 指定包大小(默认 56 字节)

# 分析输出
# 64 bytes from 8.8.8.8: icmp_seq=1 ttl=117 time=36.3 ms
#                                              ^^^ TTL 说明经过多少跳
#                                                   ^^^^^^^ 往返时间

# 故障解释
# Request timeout     → 不通(防火墙/路由/目标不响应 ICMP)
# 高延迟             → 网络拥堵/远距离
# 有丢包             → 丢包率 > 0% 说明不稳定

注意:很多云服务器禁了 ICMP,ping 不通不代表服务不可用。

2.2 traceroute — 经过哪里?#

bash
traceroute 8.8.8.8                 # 显示每跳路由
traceroute -n 8.8.8.8              # 不解析域名(更快)
traceroute -T -p 443 example.com   # 用 TCP SYN 代替 ICMP(穿透防火墙)

# 输出解读
# 1  192.168.1.1  1.23ms
# 2  10.0.0.1     5.67ms
# 3  * * *                          ← * * * 表示这一跳不响应
# 4  72.14.237.130  36.3ms

首选 mtr:traceroute 只跑一趟,看不出丢包是偶发还是持续。mtr = traceroute + ping, 持续探测每一跳,是排查"路由中间某跳丢包/抖动"的利器。

bash
mtr 8.8.8.8                        # 交互界面,实时刷新每跳丢包率和延迟
mtr -n 8.8.8.8                     # 不解析域名
mtr -rwc 100 8.8.8.8               # 报告模式:发 100 个包后输出统计(-r 报告 -w 宽 -c 次数)
mtr -T -P 443 example.com          # 用 TCP 探测 443 端口

# 关键看 Loss% 列
# 中间某跳丢包但末跳不丢 → 常是该跳路由器限速 ICMP,不代表真丢包
# 从某跳开始一直丢到末跳    → 那一跳往后才是真问题

2.3 nc (netcat) — 端口通不通?#

bash
# TCP 端口测试
nc -zv example.com 80               # 测试 80 端口
# Connection to example.com 80 port [tcp/http] succeeded!

nc -zv example.com 22-25            # 测试 22-25 范围端口
nc -v -w 3 example.com 443          # -w 3 = 超时 3 秒

# 简易 TCP 服务端(测防火墙用)
# 在目标机器上:
nc -l -p 8080                       # 监听 8080 端口
# 在测试机器上:
nc -v target_host 8080              # 尝试连接
# 两边都看到 Connected → 端口可达
bash
# nc 不止是测试工具,还能"说话"
# 场景:手动和 Redis 交互
echo "PING" | nc localhost 6379
# +PONG

# 发送 HTTP 请求
printf "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n" | nc example.com 80

3. HTTP 调试:curl#

curl 是运维调试 HTTP API 的标配工具。

3.1 基本用法#

bash
curl https://example.com             # GET 请求,输出响应体
curl -I https://example.com          # 只看响应头(HEAD 请求)
curl -o output.html https://example.com  # 下载到文件
curl -O https://example.com/file.tar.gz  # 按远程文件名保存

3.2 常用参数#

参数含义示例
-X指定 HTTP 方法curl -X POST https://api.example.com/data
-H添加请求头curl -H "Authorization: Bearer xxx"
-d发送 POST 数据curl -d "name=test&value=123"
--data-raw发送 JSONcurl -H "Content-Type: application/json" -d '{"name":"test"}'
-v详细模式(看连接过程)curl -v https://example.com
-k忽略证书错误curl -k https://self-signed.badssl.com/
-L跟踪重定向curl -L http://example.com(跟着 301/302 跳)
-x走代理curl -x http://127.0.0.1:8080 https://example.com(也读 HTTPS_PROXY 等环境变量)
-s静默模式curl -s https://api.example.com | jq
-w输出格式化信息curl -w "\nHTTP code: %{http_code}\n"
-o /dev/null丢弃响应体配合 -w 只看时间等
--connect-timeout连接超时(秒)curl --connect-timeout 5 ...
-m / --max-time总超时(秒)curl -m 10 ...

3.3 实战示例#

bash
# 测试 REST API
curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $(cat /etc/myapp/token)" \
  -d '{"action":"reload"}' \
  https://api.example.com/v1/admin/config

# 只测响应时间
curl -s -o /dev/null -w \
  "DNS: %{time_namelookup}s | Connect: %{time_connect}s | TTFB: %{time_starttransfer}s | Total: %{time_total}s\n" \
  https://example.com

# 测试健康检查接口
curl -f -s https://api.example.com/health && echo "OK" || echo "FAIL"
# -f 表示 HTTP 状态码 >=400 时返回失败(退出码 22)

# 循环监控
while true; do
  curl -s -o /dev/null -w "%{http_code} %{time_total}s $(date)\n" \
    https://api.example.com/health
  sleep 5
done

4. 端口与连接#

4.1 ss — 查看 Socket(现代工具,替代 netstat)#

bash
ss -tlnp                     # 列出所有 TCP 监听端口
# t=TCP, l=LISTEN, n=不解析域名, p=显示进程名

ss -tlnp | grep 8080         # 查看 8080 端口是哪个进程在监听

ss -an | grep ESTAB           # 看所有已建立的连接
ss -an | wc -l                # 连接总数统计

ss -s                         # 汇总统计

# 常用组合
ss -tlnp                      # TCP 监听端口及进程(最常用)
ss -ulnp                      # UDP 监听端口
ss -tan                       # 所有 TCP 连接(含 ESTAB/TIME_WAIT 等)
ss -tan state established     # 只看已建立连接
ss -tan state time-wait       # 只看 TIME_WAIT 连接

# 重要状态
# LISTEN      — 正在监听
# ESTAB       — 已建立连接(正常)
# TIME_WAIT   — 主动关闭方等待(大量出现可能需要调内核参数)
# CLOSE_WAIT  — 对方已关闭,本地还没关闭(可能是应用 bug)

4.2 对比 netstat(已弃用)#

netstat 属于 net-tools已停止维护,现代发行版最小化安装默认不带。 上生产别再依赖它,一律用 ss(更快、支持更细的状态过滤)。

bash
# 迁移对照:
netstat -tlnp            →    ss -tlnp
netstat -an | grep ESTAB →    ss -tan state established
netstat -s               →    ss -s
netstat -rn              →    ip route            # 路由表
netstat -i               →    ip -s link          # 网卡收发统计

5. 接口与路由#

5.1 ip 命令(替代 ifconfig/route)#

bash
# 查看网络接口
ip addr                         # 所有接口的 IP 地址(同 ip a)
ip addr show eth0               # 只看 eth0

# 查看链路状态
ip link                         # 所有接口的链路状态
ip link show eth0               # eth0 状态
# UP/LOWER_UP = 正常,DOWN = 没激活或被拔线

# 路由表
ip route                        # 查看路由表
ip route get 8.8.8.8            # 查到这个 IP 走哪条路由
ip route add 10.0.0.0/8 via 192.168.1.1  # 加静态路由(临时)
ip route del 10.0.0.0/8                   # 删除路由

# 查看 ARP 表
ip neigh                        # 查看邻居(ARP 表)

5.2 关键解读#

bash
ip addr
# 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ...
#    inet 192.168.1.100/24 brd 192.168.1.255 scope global eth0
#                   ^^ /24 = 子网掩码 255.255.255.0

ip route
# default via 192.168.1.1 dev eth0     ← 默认网关
# 10.0.0.0/8 via 10.0.1.1 dev eth1    ← 到 10 网段走 eth1
# 192.168.1.0/24 dev eth0 proto kernel ← 本地直连

6. DNS 诊断#

6.1 dig — 详细查询#

bash
dig example.com                           # 详细解析
dig +short example.com                    # 只显示结果
dig +short example.com A                  # A 记录
dig +short example.com MX                 # 邮件记录
dig -x 8.8.8.8                            # 反向解析(IP → 域名)

# 指定 DNS 服务器查询
dig @8.8.8.8 example.com                  # 用 Google DNS 查询
dig @1.1.1.1 example.com                  # 用 Cloudflare DNS

# 查看解析全过程
dig +trace example.com                     # 从根域名服务器追踪

6.2 dig 输出解读#

bash
dig example.com
# ;; ANSWER SECTION:
# example.com.    300  IN  A  93.184.216.34
#                  ^^^ TTL 缓存时间(秒)
#                            ^ 记录类型

# ;; Query time: 36 msec    ← DNS 响应时间
# ;; SERVER: 8.8.8.8#53     ← 实际使用的 DNS 服务器

6.3 resolvectl / nslookup#

现代 systemd 系统(跑 systemd-resolved)优先用 resolvectl(旧名 systemd-resolve):

bash
resolvectl query example.com       # 查询(走系统实际的解析链路,含本地缓存/分链路 DNS)
resolvectl status                  # 查看每块网卡生效的 DNS 服务器、搜索域
resolvectl statistics              # 缓存命中/查询统计
resolvectl flush-caches            # 清 DNS 缓存(改了记录不生效时先清这个)

nslookup(属于 bind-utils/dnsutils,较老)仅作应急/对照,能用但不推荐深挖:

bash
nslookup example.com              # 简单查询
nslookup example.com 8.8.8.8      # 指定 DNS 服务器

注意:dig/nslookup 直接向 DNS 服务器发查询,不走 nsswitch.conf//etc/hostsresolvectl querypingcurl 才走系统真实解析链路。所以"dig 能解析但程序连不上" 往往是 hosts 文件或 resolved 缓存作祟——见下。

6.4 DNS 解析顺序与配置文件#

程序解析主机名时,先看 /etc/nsswitch.conf 决定查询顺序,再按顺序查各数据源:

bash
grep '^hosts:' /etc/nsswitch.conf
# hosts: files dns
#        ^^^^^ 先查 /etc/hosts(files),再查 DNS
# 若为  files resolve [!UNAVAIL=return] dns  → 中间经 systemd-resolved

cat /etc/hosts                     # 静态映射,优先级高于 DNS(排查"某域名被劫持到内网 IP"先看它)

cat /etc/resolv.conf
# nameserver 8.8.8.8
# nameserver 114.114.114.114
# search example.com              ← 自动补全域名后缀
# 用了 systemd-resolved 时,这里通常是指向 127.0.0.53 的软链,真实 DNS 看 resolvectl status

7. 抓包:tcpdump(简介)#

bash
# 基本抓包
tcpdump -i eth0                   # 抓 eth0 的所有包
tcpdump -i any port 80            # 抓所有网卡的 80 端口流量
tcpdump -i eth0 host 10.0.1.100   # 抓与指定 IP 的通信

# 实用过滤
tcpdump -i any port 443 -w capture.pcap    # 保存到文件(Wireshark 分析)
tcpdump -i any -A port 80                  # 显示 ASCII 内容
tcpdump -i any -n 'tcp[tcpflags] & tcp-syn != 0'   # 只看 SYN 包(连接请求)

# 限制抓包数量
tcpdump -i any -c 100 -w sample.pcap       # 只抓 100 个包

8. 实战#

实战 1:端口初诊三板斧#

bash
# 1. 端口在监听吗?
ss -tlnp | grep 8080
# 没输出:服务没启动或监听了其他端口

# 2. 端口能连上吗?
nc -zv localhost 8080
# Connection refused: 端口没监听
# Connection timed out: 防火墙拦截
# succeeded: 通了

# 3. 端口能正常响应吗?
curl -v http://localhost:8080/health

实战 2:带认证的 API 调试#

bash
# 保存 Token 到变量
TOKEN=$(curl -s -X POST https://auth.example.com/login \
  -H "Content-Type: application/json" \
  -d '{"user":"admin","pass":"secret"}' | jq -r '.token')

# 用 Token 调业务接口
curl -H "Authorization: Bearer $TOKEN" \
  https://api.example.com/v1/health

# 检查响应
# 200 OK → 正常
# 401 Unauthorized → Token 过期/无效
# 502 Bad Gateway → 上游服务挂了

实战 3:K8s 内部 DNS 查询#

bash
# 在 Pod 内部查 K8s 服务 DNS
dig +short kubernetes.default.svc.cluster.local
# 返回 ClusterIP

# 查特定服务的 DNS
dig +short myapp-svc.my-namespace.svc.cluster.local

# 查 CoreDNS 的 Pod IP
kubectl get svc -n kube-system kube-dns -o jsonpath='{.spec.clusterIP}'

# 从 Pod 内测试 DNS
kubectl exec -it myapp-pod -- nslookup myapp-svc
kubectl exec -it myapp-pod -- curl http://myapp-svc:8080/health

9. 排障顺序(网络版)#

text
1. ping         — 网络层通不通?
2. traceroute/mtr — 卡在哪一跳?有没有丢包?
3. dig/resolvectl — DNS 能解析吗?(dig 直查 DNS,resolvectl 走系统真实链路)
4. nc           — 端口通不通?
5. curl         — HTTP 层正常吗?(状态码 200/502/503?)
6. ss           — 端口在监听吗?连接在 ESTAB 状态吗?
7. tcpdump      — 抓包看数据到底去哪了

10. 小结#

知识点一句话记忆
ping测试网络层可达性(云环境可能禁 ICMP)
ncnc -zv host port 测端口通断
curlHTTP 调试标配,-X 方法,-H 头,-d 数据,-v 详细
ss-tlnp 看监听端口,-tan state 看连接状态
ip addr/route看 IP 和路由表(取代已弃用的 ifconfig/route)
mtrtraceroute+ping 二合一,看每跳持续丢包率
dig / resolvectldig +short 直查 DNS;resolvectl query/status 走系统真实解析链路
tcpdump-i any port 80 -w file.pcap 抓包分析

上一章:十、终端复用 tmux 下一章:十二、存储与磁盘管理