
做运维和开发的这些年我最常被问到的一句话就是“网又断了/网页打不开了”。这四个字背后可能是网线松了可能是路由器抽风可能是 DNS 服务器没了响应也可能是某个服务根本没起来。如果上来就重启路由、重装驱动那基本是在碰运气。我写这篇文章是想把一套我自己一直在用的网络故障排查思路彻底捋清楚从 DNS 解析开始一路查到 TCP 连接层面一步步定位问题到底出在哪一层、哪一跳顺便把这些年踩过的坑和总结的命令挨个列出来。无论你是刚入门的小白还是被各种疑难杂症折磨的运维、开发、网工这套思路都能直接用。1. 排查总纲先把“玄学”踢出局1.1 分层排查为什么“重启大法”不是好办法网络故障排查最忌讳的就是一上来就凭感觉乱试。今天重启路由器、明天换个 DNS、后天把防火墙全关了偶尔碰对了问题就消失了但根本原因没找到下次换个场景还会再犯。我习惯把整个网络链路想象成一次寄快递的过程应用层是“写收件人信息”TCP 是“快递员确认你签收”IP 是“快递面单上的地址”网线、Wi-Fi 信号这些则是“运货的卡车和公路”。任何一个环节出了问题包裹都到不了手上。但不同环节出了问题的表现是完全不一样的。所以排障的第一原则是先分层再定位。从物理层到应用层一层层往上确认物理链路通不通、网络层能不能路由、DNS 能不能解析、TCP 能不能握手、应用层请求有没有响应。每一层都有对应的工具和命令按顺序查基本不会跑偏。1.2 从症状反推“嫌疑层”不同故障现象其实早就暗示了问题大概率在哪个层。我整理了这么一张判断表现象大概率嫌疑层排查方向完全断网所有设备都不通物理层/链路层光猫、路由器、网线、交换机能上内网上不了外网网络层/出口网关、路由、运营商链路能上微信打不开网页应用层/DNS浏览器代理、DNS 解析、HTTP 服务能 ping 通 IP但连不上端口传输层防火墙规则、服务监听状态网页能开但图片/接口时不时失败传输层/链路层丢包、重传、MTU 分片这里有个经典例子能上微信、QQ但浏览器打不开网页。很多人第一反应是网络断了其实不是。这类即时通讯软件用的是长连接服务器 IP 早就写在配置里基本不需要每次重新解析域名。而浏览器访问网站每一次都要先做 DNS 解析域名再发起 TCP 连接。网页打不开微信却好好的通常问题就出在 DNS 解析这一环或者浏览器的代理设置上。1.3 记录现场排障第一步永远是留证据我见过太多人上来就改配置改完更坏了然后一脸茫然“刚才是什么样来着”。所以我的排障铁律第一条动手之前先记录现场。需要记的信息不复杂故障开始时间、影响范围只有自己还是全办公室、具体现象能上什么、不能上什么、有没有报错提示、最近改过什么配置。这五条记下来很多问题其实已经能猜出一半了。比如“只有我这台电脑打不开网页”那交换机、路由、光猫基本可以先排除问题大概率在这台机器的 DNS 或浏览器配置里。而“整层楼都上不了网”那就不用纠结本机了直接往网络出口方向查。2. 第一站DNS 解析到底卡在哪一环2.1 别小看这个“翻译官”URL 是一个给人看的名字而网络通信用的是 IP 地址。DNS 要做的事就是把人能记住的域名翻译成机器能懂的 IP。这个翻译过程看着简单实际链条非常长浏览器缓存 → 系统 hosts 文件 → 系统解析器 → 本地 DNS 服务器可能是路由器下发的也可能是自建的→ 根服务器 → 顶级域服务器 → 权威服务器。这条链路上任何一个环节出了问题表现都是“域名解析不了”或“解析超时”。区别在于有些是本地问题有些是远端问题排查方法完全不同。最典型的本地问题就是 hosts 文件被改坏或者浏览器缓存里存了一条脏记录。我曾遇到过一台电脑访问某个内部系统总是跳到别的 IP折腾了半天最后发现是 hosts 文件里残留了一条旧的内网映射。把那条删掉问题立刻消失。所以排查 DNS 的第一件事永远是先看 hosts再看缓存最后才怀疑上游。2.2 手动验证nslookup 与 dig 的正确用法光看浏览器报错“找不到服务器”是不够的。我们得手动解析一次才能确认问题到底在不在 DNS。在 Windows 和 Linux 上最通用的命令是 nslookupnslookup www.example.com如果能看到返回的 IP 地址说明 DNS 基本正常。如果报 “** server cant find ...”说明域名解析失败。这时候再用dig追一下详细过程Linux/macOS 自带Windows 可以装个工具或用 Git Bashdig www.example.com short # 只要结果 dig www.example.com trace # 看完整递归查询路径 dig 223.5.5.5 www.example.com # 指定某个 DNS 服务器查trace特别有用它能显示查询从根服务器一步步走向权威服务器的全过程。如果卡在某一步不动了那就是那一层出了问题。如果指定阿里 DNS223.5.5.5能正常解析但用本机默认 DNS 不行那问题就在本地 DNS 配置上。如果指定哪个 DNS 都不行而别的机器正常那就该查本机的网络层和防火墙了。2.3 系统配置 DNS 的坑Linux 改完重启就还原、虚拟机只能手动配置很多人都被这个问题坑过在 Linux 里直接编辑/etc/resolv.conf改了 DNS看着生效了结果一重启网络或者一重启系统配置又变回去了。这个真不是手误而是现代 Linux 发行版普遍用 systemd-resolved 或 NetworkManager 接管了 DNS 配置。在 Ubuntu 22.04 这类系统上/etc/resolv.conf往往是指向 systemd-resolved 的一个软链接手动改了也只是临时生效。正确的持久化配置方式是nmcli con mod Wired ipv4.dns 223.5.5.5 119.29.29.29 # NetworkManager 管理时用 nmcli con mod Wired ipv4.ignore-auto-dns yes nmcli con up Wired如果是用 netplan 的服务器系统则修改/etc/netplan/xx-netcfg.yaml在对应网卡的nameservers下配置 DNS 列表然后执行netplan apply。改完之后用resolvectl status确认当前生效的 DNS别再看那个软链接了。Windows 虚拟机也有个常见的怪毛病自动获取的 DNS 总是不太稳定表现为宿主机上网没问题虚拟机里浏览器经常打不开网页但手动把 DNS 填上 223.5.5.5 或者 119.29.29.29 就一切正常。这通常是虚拟化 NAT 网络在 DHCP 下发 DNS 时的兼容性问题。遇到这种情况别犹豫直接在虚拟机网卡属性里把 DNS 改成手动指定。2.4 企业域环境DC 的网卡 DNS 千万别乱配自家搭过 AD 域的朋友应该都有体会域环境里 DNS 和 AD 是深度耦合的。客户端找域控制器、找组策略、各种 SRV 记录解析全部依赖 DNS。所以在有 3 台 DC 域控制器的环境里DC 网卡的 DNS 配置是个特别讲究的活。原则是主 DNS 指向另一台 DC辅助 DNS 指向第三台 DC绝不写本机回环地址127.0.0.1也不写公网 DNS。比如 DC-A、DC-B、DC-C 三台DC-A 的网卡 DNS 填 DC-B 的 IP 作为首选DC-C 作为备用。之所以不写本机回环是因为如果本机 DNS 服务异常或者开机顺序不对自己解析自己的时候容易进入环路反而造成服务启动失败。很多人图省事给 DC 配了公网 DNS短期好像也能用但时间一长就会发现域内客户端登录变慢、组策略不生效、各种莫名奇妙的问题。原因就是 AD 的 DNS 区域没有被正确复制和解析。这个属于典型的企业环境“配置一时爽排查火葬场”案例最好一开始就按规范来。3. 第二站TCP 连接建立不起来到底是谁在拒绝3.1 三次握手的本质一次带应答的呼叫DNS 解析出 IP 之后下一步就是建立 TCP 连接。TCP 的可靠性建立在“三次握手”上客户端发 SYN表示“我要连接你”服务器回 SYN-ACK表示“收到我同意”客户端再回 ACK表示“确认收到开始传数据”。用打电话来类比最贴切拨号SYN→ 对方接听并且说“喂”SYN-ACK→ 你回一句“你好我是某某”ACK→ 然后才开始正式说话。三次握手缺任何一次数据都传不了。在排查问题的时候我们真正关心的是握手停在了哪一步。这个信息能直接告诉我们是客户端发不出去还是服务器不回还是回包在中途丢了。光靠现象连接超时很难分辨需要抓包辅助。3.2 “连接超时”和“连接被拒绝”完全是两码事很多人分不清这两个报错其实它们的排查方向天差地别Connection timed out连接超时SYN 发出去了等半天没人应答。可能的原因包括远端防火墙直接丢弃了数据包、服务器宕机、中间链路丢包、IP 本身不可达。Connection refused连接被拒绝对端收到了请求并且明确回了一个 RST 包告诉“我这里没有这个服务在监听”。这个反而是个“好消息”至少链路是通的问题在服务本身。用一个例子说明你用浏览器访问某台服务器的 8080 端口立即报“拒绝连接”那基本是服务没起来或者端口监听地址不对。反过来如果在“正在连接”那里卡了十几秒甚至一分钟才超时那大概率是防火墙把包悄悄丢弃了。所以排障时记住一句话超时先查链路和防火墙拒绝先查服务本身。3.3 用一条命令判断端口通不通判断端口通不通我常用telnet或者nctelnet 192.168.1.10 8080 nc -vz 192.168.1.10 8080如果连接成功窗口会进入一个黑屏等待输入的状态或者 nc 输出“succeeded”。如果连接不上nc 会明确告诉你 timeout 还是 refused。不过要注意端口通并不代表业务就正常。端口通只能说明 TCP 握手完成之后可能立刻被服务端断开也可能是服务端返回了 500 错误。所以更稳的方法是用curl -v看完整的请求过程curl -v http://192.168.1.10:8080/-v会打印出每一步DNS 解析用了多久、TCP 连接用多久、TLS 握手、发送请求、接收响应。curl 的输出本身就是一份很好的排障日志。如果端口不通到服务器本机再确认一下服务有没有监听ss -lntp | grep 8080这个命令会列出所有处于 LISTEN 状态的 TCP 端口以及对应的进程。如果这里看不到 8080说明服务根本没起来或者监听的地址不对。如果看到了那就是防火墙或中间链路的问题。3.4 SYN 一直发不出去半连接队列与防火墙的降维打击还有一种比较难缠的情况客户端显示 TCP 连接一直处于 SYN_SENT 状态也就是 SYN 发出去了没有任何回应。这通常意味着两种可能要么请求在半路被防火墙 drop 掉要么服务器端的半连接队列被塞满了根本来不及处理新到的连接。半连接队列是内核里一个专门保存“握手进行中”连接的地方如果客户端一直发 SYN 但不完成握手也就是 SYN Flood 攻击这个队列就会被打满正常用户的连接请求只能排队等超时。检查方法是在服务器上执行ss -s看syn retrans相关的统计或者用netstat -s看SYNs to LISTEN sockets dropped这个字段。如果数字一直在涨基本可以判断是半连接队列溢出。遇到这个问题除了做 SYN 防御和限速之外还需要检查应用层的 backlog 参数是否设置得太小。Linux 上还涉及net.ipv4.tcp_max_syn_backlog和net.core.somaxconn这两个内核参数。排查这类问题最好结合抓包看看是“根本没有 SYN-ACK 回来”还是“SYN-ACK 被客户端当成无效包丢弃了”。4. 第三站连接的“路况”——重传、MSS 与黑洞问题4.1 TCP 握手成功但数据传不过去MTU 分片黑洞握手成功只代表通信链路是通的真正传数据的时候还可能出幺蛾子。最经典的场景就是能 telnet 通 80 端口但用 curl 发一个 GET 请求就卡住不动了。这种问题十有八九跟 MTU最大传输单元有关。大致的原理是以太网标准 MTU 是 1500 字节如果一个数据包超过这个大小沿途就要拆分成多个小片段。但如果中间某个设备的防火墙不允许携带分片标志的大包通过或者丢弃了 ICMP 差错报文发送方就永远不知道自己发的包太大了只能一直重传表现为“连接能通但反应极慢”。排查方法也很简单用 ping 手动测最大包大小。Windows 下ping -f -l 1472 192.168.1.10Linux 下ping -M do -s 1472 192.168.1.101472 加上 28 字节的 ICMP 包头刚好是 1500。如果这个包能通但加大到 1473 就不通或者出现分片那基本可以断定中间存在 MTU 限制。解决办法一般是对路由器设置 MSS Clamp让 TCP 握手时协商的报文段长度MSS自动减小或者把某些接口的 MTU 调成 1400 左右。4.2 TCP 重传与重复 ACK慢不能全怪“网速”很多人觉得网页打开慢就是带宽不够其实很多情况下是丢包导致的 TCP 重传在拖后腿。TCP 有个机制发出一个数据段之后如果在一定时间内没收到确认就认为是丢了于是重新发一次。如果网络丢包率稍微高一点比如 2%TCP 的有效吞吐量会下降得极其夸张因为重传占用了大量带宽和等待时间。抓包的时候重传包长这样同样的序列号反复出现或者连续收到多个相同 ACK 号的数据包Dup ACK。如果你发现一个简单的 HTTP 请求在 tcpdump 里看到大片的重传就不用去怀疑宽带套餐了该去查网线、交换机端口、Wi-Fi 信号质量以及有没有链路拥塞。这里有个容易被忽视的细节TCP 处理的是“丢包”问题而 UDP 处理的是“丢包就丢了”的问题。两者的排查思路完全不一样。DNS 查询走 UDP如果 UDP 包被丢弃客户端只会觉得“超时了、慢”而 HTTP 走 TCP一旦丢包你会看到明显的重传和体验卡顿。所以排查直播、语音这类 UDP 应用的问题ping 丢包率才是最直接的证据。4.3 TIME_WAIT 与“地址已在使用”的恩恩怨怨开发环境的另一个高频问题是程序里建 TCP 连接经常报Address already in use。这背后是 TIME_WAIT 状态在作祟。TCP 连接在主动关闭之后发起关闭的一方会进入 TIME_WAIT 状态默认要等 2 个 MSL报文最大生存时间Linux 上一般约 60 秒。之所以要等是为了确保最后一个 ACK 不会被网络延迟导致旧连接的数据包残留到新连接上。问题在于如果你的客户端用固定端口高频建连、断开、再建连很快就发现端口被 TIME_WAIT 的连接占着新连接起不来。Java 的 HttpClient、自写的 C asio 客户端、以及一些 Nginx 反向代理的高并发场景里都容易撞上。解决方法有几种在服务端允许SO_REUSEADDR地址重用在客户端主动调用connect()前设置复用端口选项或者干脆让系统把 TIME_WAIT 缩短一些。但要提醒一句SO_REUSEADDR不是万能灵药它的语义在不同系统上略有差异只适合在明确理解行为后使用。生产环境更建议通过连接池来复用连接而不是让每个请求都新建一个 TCP。4.4 高并发下的连接数上限不只是改一个参数那么简单说到 Nginx 反向代理 TCP 最大连接数、以及各种高并发 TCP server 的优化很容易让人误以为只要把 worker 开多就行。实际上真正限制连接数的是文件描述符fd上限、内存大小、以及内核 TCP 缓冲区。每建一个 TCP 连接服务器就要占用一个 fd、一部分内核缓冲区内存。一台只有 2GB 内存的小服务器如果跑着大量保持空闲的 TCP 连接可能几十万并发就已经把自己耗尽。排查的时候用ss -s看当前连接状态分布用ss -lnt看监听队列溢出情况。这里面还有一个值得提的场景用 asio 这类库写 TCP server很多人习惯每来一个连接就起一个线程连接一多就崩。正确的做法是 io_context 配合多线程事件循环加上异步读写控制并发量。这类问题表面上是“代码写得不好”本质上还是没有真正理解 TCP 连接是资源这件事它不只是网络层面的问题更是系统资源层面的问题。5. 工具箱从命令行到抓包三板斧拿下5.1 高频命令速查平时排障我大部分时间用下面这些命令就够了命令用途关键参数ping测连通性与丢包-c 次数、-M do 禁止分片nslookup / dig解析域名、查 DNS 链路服务器、trace、shorttelnet / nc验证 TCP 端口连通性-vz 端口扫描模式curl -v完整打 HTTP 请求过程-v、-w 打印耗时ss -lntp查看本机监听端口-l 监听、-t TCP、-p 进程traceroute / tracert看路由经过哪几跳-n 不反查域名tcpdump / wireshark抓包和分析-i 网卡、-nn 不解析、tcp port 80ip route get查指定 IP 走哪条路由一条指令直接出结果这几个组合起来能覆盖从物理层到应用层 80% 以上的排查场景。5.2 tcpdump 抓一次握手过程怀疑 TCP 层有妖就直接抓包看现场。tcpdump 是 Linux 上最常用的抓包工具tcpdump -i eth0 -nn host 192.168.1.10 and tcp port 8080这个命令会抓取和 192.168.1.10:8080 相关的所有 TCP 包。一次完整的成功握手你会看到类似这样的三行Flags [S] - SYN Flags [S.] - SYN-ACK Flags [.] - ACK如果只有第一行Flags [S]后面什么都没有说明 SYN 发出去了但没有回应问题大概率在服务器端或者中间防火墙。如果看到了[S]和[S.]但没有[.]说明握手卡在最后一步可能是客户端本地防火墙或者网络转换设备丢包。如果连接完成了但传输很慢抓包的重灾区是看[P.]之后有没有出现大量重传。在 Wireshark 里打开保存的 pcap 文件可以通过“分析”→“专家信息”快速看到重传和乱序的数量。Wireshark 里过滤重传也很简单直接在过滤栏输入tcp.analysis.retransmission立刻就能把所有重传包筛选出来。5.3 DNS 查询为什么超时也靠抓包说话DNS 走的是 UDP 53 端口抓包命令类似tcpdump -i eth0 -nn udp port 53你会发现 DNS 查询如果超时通常会发好几遍请求每次间隔几秒。如果 nslookup 显示“connection timed out; no servers could be reached”而抓包看不到任何发出去的 DNS 包那问题出在本地网络栈或者防火墙配置连查都没查出去。如果能看到请求包但不见响应那就是上游 DNS 服务器的问题或者链路丢包。掌握抓包技能之后排障会变得非常直观。很多看似玄学的问题看一眼包就全明白了。这也是我一直跟经验尚浅的同事强调的一点别猜抓包。猜一百次不如看一次真实流量。6. 实战复盘一次“网页打不开”的完整定位过程6.1 现象与第一轮判断有次同事找我说“我们这有台电脑微信能上网页打不开特别慢浏览器转圈转半天然后报错”。我过去之后没有直接重装浏览器或者修复网络而是先按老规矩记录现场时间当天上午 10 点左右开始范围只有这一台电脑隔壁工位正常现象微信正常网页打不开ping 外网 IP 是通的变化前一天同事装过某个安全软件我先把“全办公室断网”这种大范围故障排除了因为它只影响一台机器。既然 ping 外网 IP 都通说明物理链路、IP 配置、路由这些都是通的。微信又是长连接应用对 DNS 依赖不大。那么“网页打不开”的嫌疑高度集中在 DNS 解析和浏览器代理这两个环节。6.2 从 DNS 查到 TCP 的完整过程首先打开命令行执行nslookup www.example.com结果等了十几秒返回一个解析失败的错误。接着用nslookup www.example.com 223.5.5.5强制指定阿里 DNS结果秒回正常 IP。这一步基本就实锤了问题出在这台电脑正在使用的 DNS 配置上。然后ipconfig /all看了一眼发现这台机器的 DNS 确实不是 DHCP 自动下发的而是被人手动改成了一个内网地址。而这个内网地址现在根本 ping 不通。大概判断是之前装的那个安全软件把 DNS 改到了它的本地服务上该服务又没有正常启动。之后我顺手查了一下 TCP 层有没有别的问题telnet 223.5.5.5 53通不通通说明到 DNS 服务器的链路没问题。这里就没再继续深挖 TCP因为问题已经定位到了“DNS 指向了一个死地址”。修改 DNS 为 223.5.5.5 和 119.29.29.29 之后再用nslookup验证解析正常刷新浏览器缓存网页秒开。6.3 修复与验证一次只改一个变量这个案例里最关键的一步不是最后改 DNS而是“先强制指定正常 DNS 对比验证”。这一步把故障从“整条网络链路都不明不白”压缩到了“单纯 DNS 配置错误”。修复完成之后还有一步收尾刷新系统 DNS 缓存。Windows 执行ipconfig /flushdnsLinux 执行resolvectl flush-caches。我在验证阶段有个习惯改一个变量测一次效果不要同时动两个东西。比如这个案例里如果一边改 DNS 一边把浏览器代理也关掉虽然网页很可能也开了但永远不知道真正的根源是什么下次同类问题还是会踩坑。7. 常见问题速查表与我的几条排障铁律7.1 现象 → 排查点速查表最后再整理一个速查表适合直接打印出来贴在工位上现象第一步查什么常用命令网页打不开微信正常DNS、浏览器代理nslookup、curl -v完全上不了网物理链路、网关ping 网关、traceroute能 Ping 通但连不上服务防火墙、服务监听ss -lntp、telnet、nc连接一直超时中间防火墙丢包、远端宕机tcpdump、traceroute连接秒拒绝服务没起来、监听地址不对ss -lntp、journalctl网页打开极慢MTU、TCP 重传、Wi-Fi 信号ping -M do、Wireshark程序报地址已在使用TIME_WAIT、端口占用ss -tan state time-wait虚拟机上网只能手动 DNSNAT 的 DHCP 下发 DNS 异常网卡属性手动指定企业域内客户端联不上 DCDC 网卡 DNS 是否指向其他 DCnslookup -typeSRV _ldap._tcpDNS 被恶意域名查询刷爆日志溯源、DNS 过滤、主机加固dig 日志、防火墙域名策略在企业网络里我还遇到过恶意域名引发的黑产扫描某个内网主机被植入了恶意脚本反复对外发起针对特定域名的解析请求搞得内部 DNS 日志里全是异常记录。排查时先在 DNS 层面对该域名做阻断过滤再顺着日志找到发起查询的内网主机清理脚本、加固补丁最后在 WAF/IDS 侧补充了对应的检测规则这才算闭环。这类问题的核心依然是先看清楚流量从哪里来再决定在哪一层阻断而不是拍脑袋封一堆 IP。7.2 我的几条排障心得第一次动手前先记录现场故障现象比猜测值钱一百倍。出去的几条“铁律”都是这些年用血泪换来的永远先说现象再说猜测。尤其是多人协作排障的时候描述现象要客观不要一上来就“我觉得是防火墙的问题”。一次只改一个变量。同时改两个配置出了问题你根本分不清是哪个改坏的。怀疑谁就抓谁的包。网络问题如果靠配置对比查不出来直接 tcpdump 抓两台机器之间的流量几十秒就能把“犯罪嫌疑人”锁定。不要迷信玄学先从物理层查起。所谓网速慢、时不时断线很多时候就是一根劣质网线、一个松动的水晶头、一个信道拥堵的路由器造成的。能猜到的结论也要用命令验证一遍。哪怕你觉得“肯定是 DNS 问题”也要亲手跑一次 nslookup把输出放出来给人看也算给自己留一份记录。这套从 DNS 到 TCP 的排查思路我在不同场景里反复用过从家用路由器到企业数据中心底层逻辑都一样确认现象、分层定位、抓包求证、小步修复。遇到网络问题时别慌按这个顺序走大部分问题都能在半小时内找到答案。