外观
网络与端口
排查顺序固定:本机监听 → 本机连通 → 网段连通 → 域名解析 → 应用层。跳过前面几步直接看应用,是最常见的浪费时间。
一、看本机地址
bash
ip addr show
ip -4 addr | grep inet
ip routetext
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
inet 127.0.0.1/8 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP
inet 10.0.0.31/24 brd 10.0.0.255 scope global eth0
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
default via 10.0.0.1 dev eth0 proto static
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.31ip 已取代 ifconfig / route。CentOS 7 起默认不装 net-tools。
二、看端口监听
bash
ss -lntp
ss -lntp 'sport = :8080'
ss -lntp | grep -E ':(80|443|8080)\b'text
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1204,fd=3))
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=29112,fd=6))
LISTEN 0 4096 127.0.0.1:8080 0.0.0.0:* users:(("java",pid=28441,fd=42))| 参数 | 含义 |
|---|---|
-l | 只看监听 |
-n | 不解析端口名和 IP |
-t / -u | TCP / UDP |
-p | 显示进程(需要 root) |
-a | 所有状态 |
-s | 汇总统计 |
Local Address 决定谁能连:
| 地址 | 含义 |
|---|---|
0.0.0.0:8080 | 所有网卡,外部可连 |
127.0.0.1:8080 | 只有本机 |
10.0.0.31:8080 | 只有这块网卡 |
上面例子里 8080 绑在 127.0.0.1,外部一定连不上,不管防火墙和安全组怎么配。
连接状态统计
bash
ss -stext
Total: 412
TCP: 389 (estab 128, closed 210, orphaned 0, timewait 204)
UDP: 12timewait 204 偏多说明短连接频繁。大量 CLOSE_WAIT 则是应用没关连接(代码里没 close()):
bash
ss -tan state close-wait | head
ss -tan state time-wait | wc -l三、连通性
bash
ping -c 4 10.0.0.32
mtr -n --report 10.0.0.32
tracepath 8.8.8.8text
PING 10.0.0.32 (10.0.0.32) 56(84) bytes of data.
64 bytes from 10.0.0.32: icmp_seq=1 ttl=64 time=0.214 ms
64 bytes from 10.0.0.32: icmp_seq=2 ttl=64 time=0.189 ms
--- 10.0.0.32 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 0.189/0.204/0.231/0.017 msping 不通不代表端口不通
云厂商安全组常默认禁 ICMP 但放通 TCP。ping 不通时用端口探测确认:
bash
nc -vz 10.0.0.32 8080
timeout 3 bash -c '</dev/tcp/10.0.0.32/8080' && echo openmtr 比 traceroute 好:一次跑完并统计丢包率,能看出是某一段链路的问题。
四、探测端口
bash
nc -vz 10.0.0.32 6379
nc -vz -w 2 10.0.0.32 3306text
Connection to 10.0.0.32 6379 port [tcp/*] succeeded!失败:
text
nc: connect to 10.0.0.32 port 3306 (tcp) failed: Connection refused| 报错 | 含义 |
|---|---|
Connection refused | 到达了主机,但端口没监听(或被 REJECT) |
Connection timed out | 包被丢(防火墙 DROP、安全组、路由) |
No route to host | 路由不通 |
Network is unreachable | 本机没有到该网段的路由 |
三种报错的排查方向完全不同:refused 查服务,timeout 查防火墙/安全组。
五、HTTP 调试
bash
curl -I http://10.0.0.31:8080/health
curl -v http://10.0.0.31:8080/api/orders
curl -s -o /dev/null -w '%{http_code} %{time_total}s\n' http://10.0.0.31:8080/text
HTTP/1.1 200 OK
Server: nginx/1.27.2
Date: Tue, 27 Oct 2026 21:40:12 GMT
Content-Type: application/json
Content-Length: 27
* Trying 10.0.0.31:8080...
* Connected to 10.0.0.31 (10.0.0.31) port 8080
> GET /api/orders HTTP/1.1
> Host: 10.0.0.31:8080
> User-Agent: curl/8.7.1
< HTTP/1.1 200 OK常用参数:
bash
# 带 header
curl -H 'Content-Type: application/json' -H 'Authorization: Bearer xxx' \
-d '{"id":1}' http://10.0.0.31:8080/api/orders
# POST JSON(-d 默认表单,所以要显式指定 Content-Type)
curl -X POST -H 'Content-Type: application/json' -d @body.json http://...
# 只看耗时分解
curl -w '\ndns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n' \
-o /dev/null -s https://example.com
# 忽略证书(自签环境)
curl -k https://10.0.0.31:8443/
# 指定解析(绕过 DNS 验证某台机器)
curl --resolve app.example.com:443:10.0.0.31 https://app.example.com/
# 跟随重定向、限制时间
curl -L --max-time 10 http://example.com-w 的耗时分解是排查"慢"的利器:dns 大是 DNS 慢,connect 大是网络RTT,ttfb 大是服务端处理慢。
六、DNS
bash
dig +short app.example.com
dig @8.8.8.8 app.example.com A
nslookup app.example.com
getent hosts app.example.comtext
10.0.0.31
;; ANSWER SECTION:
app.example.com. 300 IN A 10.0.0.31bash
cat /etc/resolv.conf
cat /etc/hoststext
nameserver 10.0.0.2
nameserver 223.5.5.5
search internal.local解析顺序由 /etc/nsswitch.conf 的 hosts: 行决定,通常是 files dns——先 /etc/hosts,再 DNS。
改 hosts 只影响本机
/etc/hosts 是最快的临时方案,但只对这台机器生效,且容器不一定继承(取决于是否挂载)。容器里要加解析用:
bash
docker run --add-host app.example.com:10.0.0.31 ...七、防火墙
firewalld(CentOS / Rocky)
bash
systemctl status firewalld
firewall-cmd --list-ports
firewall-cmd --add-port=8080/tcp --permanent
firewall-cmd --reload
firewall-cmd --list-alltext
public (active)
target: default
interfaces: eth0
ports: 22/tcp 80/tcp 443/tcp 8080/tcpufw(Ubuntu)
bash
ufw status verbose
ufw allow 8080/tcp
ufw delete allow 8080/tcpiptables 直接看
bash
iptables -L INPUT -n --line-numbers
iptables -t nat -L -n | head -20text
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
2 DROP all -- 0.0.0.0/0 0.0.0.0/0三层都要放通
云上访问不通,依次确认:云安全组 → 系统防火墙(firewalld/ufw)→ 服务监听地址。三层缺一层都连不上,而只有前两层能在服务器内部查到(安全组要去控制台看)。
八、抓包
bash
tcpdump -i eth0 -nn port 8080 -c 20
tcpdump -i any -nn 'host 10.0.0.32 and port 3306' -w /tmp/db.pcap
tcpdump -i eth0 -nn -A 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'text
21:42:01.114221 IP 10.0.0.31.51244 > 10.0.0.32.8080: Flags [S], seq 184320123, win 64240
21:42:01.114388 IP 10.0.0.32.8080 > 10.0.0.31.51244: Flags [S.], seq 983211, ack 184320124
21:42:01.114402 IP 10.0.0.31.51244 > 10.0.0.32.8080: Flags [.], ack 1读法:
- 只有
[S]没有[S.]→ 对方没响应(防火墙 DROP 或服务没监听)。 - 有
[S.]但客户端回了[R]→ 端口没监听(REJECT)。 [R]重置 → 可能是中间设备或连接被复用冲突。
九、踩过的坑
| 现象 | 根因 | 处置 |
|---|---|---|
| 本机 curl 通、外部不通 | 监听在 127.0.0.1 | 改 0.0.0.0 或反代 |
| 完全连不上、无报错 | 安全组 / 防火墙 DROP | 三层依次确认 |
Connection refused | 端口没监听 | ss -lntp 查服务 |
| ping 不通但端口通 | ICMP 被禁 | 正常,用 nc 验证 |
大量 CLOSE_WAIT | 应用没关连接 | 查代码里的 close() |
大量 TIME_WAIT | 短连接频繁 | 连接池、tcp_tw_reuse |
| DNS 偶尔慢 | resolv.conf 第一个 ns 不可用 | options timeout:1 attempts:2 |
| 容器里连不上宿主机 | 宿主机服务只监听 127.0.0.1 | 改监听,或 --add-host host.docker.internal:host-gateway |
| 改了防火墙规则不生效 | 忘了 --reload / --permanent | 两条一起用 |