ping 不通但网站能打开?tcping 与 ICMP ping 的区别和正确用法
ping 不通但网站能打开,最常见的原因是对方或中间网络过滤了 ICMP,而网页走的是 TCP 443,两者互不相干。想知道某个服务“到底通不通、有多远”,应该用 tcping 这类工具直接对业务端口发起 TCP 握手,或者用 curl -w 把 DNS、TCP、TLS 各段时间拆开看。tcping 比 ping 更接近真实访问,但也有两个容易读错的地方:RST 和本机代理。
ping 不通为什么网站还能打开?
ping 发的是 ICMP Echo Request,等对方回一个 Echo Reply。它不经过任何端口,也不经过 Web 服务器,回应它的是对方操作系统的网络栈,或者更早的某个设备。
ICMP 在下面几种情况下会“失真”:
- 被直接过滤:不少云服务器的安全组默认不放行入站 ICMP,部分 API 入口和 CDN 节点也不回应 ping。这时 ping 100% 超时,但 443 端口完全正常。
- 被限速或降低优先级:路由器对发给自己的 ICMP、以及 TTL 超时报文的生成,通常交给控制面处理并限速;有的网络还会对经过的 ICMP 整体限速。于是 ping 显示的延迟偏高、偶尔丢包,而同一路径上的 TCP 流量并没有受影响。这也是 traceroute 中间跳出现星号或延迟突增的常见原因,读法见 traceroute 和 mtr 结果怎么看。
- 走了不同的路径:有的网络对 ICMP 和 TCP 做不同的策略路由,代理软件一般也只接管 TCP(和部分 UDP),ICMP 仍然从本地出口直接发出。开着代理 ping 一个海外域名,测到的是“本地直连”的路径,而浏览器访问走的是代理,两者没有可比性。
所以 ping 的结论只能是“ICMP 这条路的情况”。它通了,不代表 443 能用;它不通,也不代表服务挂了。
tcping 测的到底是什么?
tcping 对指定的 IP 和端口发起一次 TCP 连接:发出 SYN,等对方回 SYN-ACK,记下这个往返用了多久,然后关闭连接。它测的是 TCP 三次握手的第一个往返,不发 HTTP 请求,也不做 TLS 握手。
和 ping 相比,它有两点更贴近真实访问:
- 用的是业务协议和业务端口,能被 ICMP 过滤规则影响的情况少了一大类。
- 能顺便回答“端口开没开”:收到 SYN-ACK 说明有程序在监听。
RST 也算“有响应”:最容易看错的地方
TCP 握手有三种结果:
| 对方回应 | 含义 | 常见工具的表现 |
|---|---|---|
| SYN-ACK | 端口开放,有服务在监听 | 显示 open / 连接成功,给出耗时 |
| RST | 主机可达,但端口没有服务,或被防火墙主动拒绝 | 部分工具显示 closed,也有工具照样给出一个耗时 |
| 无回应 | 被防火墙静默丢弃,或路由不通 | 超时(timeout / filtered) |
问题出在第二行。RST 也是一个完整的往返,有些工具(尤其是发原始 SYN 包的工具,比如 hping3)会把它的耗时照常打印出来,只在标志位里写着 RA。只看数字的话,会误以为“端口通,延迟 40 ms”。读 tcping 结果时,先确认状态是 open,再看耗时。
本机代理会“替”对方完成握手
开启 TUN 模式或透明代理时,很多代理客户端会在本机直接接受 TCP 连接,再转发出去。此时 tcping 任何海外地址都可能显示 1 ms 左右、端口全开,测到的只是你和本机代理之间的握手。CDN 也有类似情况:TCP 在离你最近的边缘节点就终止了,tcping 测到的是你到边缘的距离,不是到源站。
判断方法很简单:同一个目标,关掉代理测一次、开着代理测一次;或者 tcping 一个肯定不存在服务的地址和端口,如果也“秒通”,说明握手被本地接管了。
三种测量方式放在一起对比
| ICMP ping | tcping(TCP 握手) | HTTPS 首次连接(curl / 浏览器) | |
|---|---|---|---|
| 协议与端口 | ICMP,无端口 | TCP,指定端口 | TCP 443 + TLS + HTTP |
| 测到的时间 | 1 个 ICMP 往返 | 1 个 TCP 往返 | DNS + TCP 握手 + TLS 握手(+ 首字节) |
| 能发现端口不通 | 不能 | 能 | 能 |
| 能发现证书、SNI、TLS 层问题 | 不能 | 不能 | 能 |
| 是否经过代理 | 通常不经过 | 取决于代理模式 | 和真实应用一致 |
| 适合回答的问题 | 主机在网络层是否可达(前提是不过滤 ICMP) | 业务端口开没开、TCP 往返多少 | 真实请求在连接阶段要花多久、卡在哪一段 |
越往右越接近应用实际遇到的情况,代价是测量更重、受更多因素影响。排查时建议从右往左用:先用 curl 看哪一段慢,再用 tcping 确认 TCP 层,最后才看 ping 和 traceroute。
各系统怎么测端口和握手延迟?
下面以 api.openai.com:443 为例。示例输出只用来说明格式,数字不是实测值。
Windows:tcping.exe 与 PowerShell
Windows 没有自带 tcping,常见的是一个单文件的 tcping.exe,下载后放进任意在 PATH 里的目录即可。请从项目的原始发布页下载,下载后核对数字签名或哈希。
tcping -n 5 api.openai.com 443
输出大致是每行一次探测,带 Port is open 和 time=xx.xxxms,最后给出最小、最大、平均值。如果显示 No response,就是超时。
不想装软件的话,PowerShell 自带的命令可以判断端口是否开放:
Test-NetConnection api.openai.com -Port 443
看 TcpTestSucceeded : True 即可。它不适合用来测延迟,结果里的 PingReplyDetails 是 ICMP 的数据,不是 TCP 握手时间。
macOS 与 Linux:nc 和 nping
nc(netcat)系统一般自带:
nc -vz -w 3 api.openai.com 443
succeeded / open 表示握手成功,Connection refused 对应 RST,超时说明没有回应。nc 不打印耗时,需要的话套一层 time:
time nc -z -w 3 api.openai.com 443
这样测到的时间包含 DNS 解析,想排除 DNS 就直接写 IP。
需要连续测、看抖动时,可以用 nmap 附带的 nping,它的 --tcp-connect 模式走系统的正常 connect,不需要 root:
nping --tcp-connect -p 443 -c 10 api.openai.com
最后一行会给出 Max rtt / Min rtt / Avg rtt。Linux 发行版仓库里也有叫 tcping 的包,不同发行版的实现不一样,参数以 tcping -h 为准。
通用:curl -w 拆分每一段时间
这是测 API 最推荐的一条命令,三个系统都能用(Windows 10 1803 及之后的版本自带 curl,PowerShell 里要写 curl.exe,并把 -o /dev/null 换成 -o NUL):
curl -o /dev/null -s -w "DNS: %{time_namelookup}s\nTCP: %{time_connect}s\nTLS: %{time_appconnect}s\n首字节: %{time_starttransfer}s\n总计: %{time_total}s\n" https://api.openai.com/v1/models
这几个值都是从开始计时的累计时间,要相减才是每一段:
time_connect - time_namelookup:TCP 握手,和 tcping 测的是同一个东西。time_appconnect - time_connect:TLS 握手。time_starttransfer - time_appconnect:请求发出到收到第一个字节,包含服务端处理。不带密钥访问/v1/models通常直接返回 401,这一段基本就是“网络往返 + 网关处理”,不涉及模型推理。
如果 curl 走了代理(设置了 https_proxy 等环境变量),time_connect 测到的是连代理的时间。想区分,就用 --noproxy '*' 再跑一次对比。连接阶段之后的延迟怎么继续拆,见 AI API 延迟拆解:连接建立、网关往返与首 token 时间。
为什么测 AI API 应该测 443,而不是 ping 域名?
多数 AI API 的入口在 CDN 或云负载均衡后面,对 ping 的处理各不相同:有的回应,有的不回应,有的由边缘节点代答。ping 一个 API 域名得到的结果,既不能说明 443 可用,也不能拿来横向比较各家快慢。
实际调用要经过的是:DNS 解析 → TCP 443 握手 → TLS 握手 → HTTP 请求。任何一段出问题,ping 都看不出来。比较典型的几种:
- DNS 解析到了错误的地址:ping 可能通(只是 ping 错了对象),请求却失败。是否被污染或劫持,可以按 DNS 污染和 DNS 劫持的三步判断来查。
- TCP 443 被重置或丢弃:ping 正常,tcping 显示 closed 或超时。
- TLS 握手失败或特别慢:ping 和 tcping 都正常,只有 curl 的 TLS 段异常或报错。
所以排查 Claude Code、Codex 这类工具连不上时,应该按层次逐一检查,而不是 ping 一下就下结论。完整的分层清单见 Claude Code 连接超时和报错怎么排查。
一份可以照做的检查顺序
- 运行上面的
curl -w命令,看在哪一段出错或变慢。 - DNS 段慢或报解析错误:换一个解析器对比
dig/nslookup结果。 - TCP 段超时:用 tcping 或
nc -vz测 443,开关代理各测一次,确认是不是被本机代理接管。 - TLS 段报错:检查系统时间、代理证书、是否有中间设备在做 HTTPS 解密。
- 连接都正常但请求失败:看 HTTP 状态码,再去 API 状态页 确认上游有没有事件。
- 最后才用 ping 和 mtr 看路径,判断是不是中间某段网络有问题。
日常需要定期做的项目,可以对照 开发者网络自检清单(2026 版)。
cdnping 首页的“首次连接”和“往返”分别对应什么?
cdnping 的在线测速在浏览器里测 15 个 AI 模型 API 和 9 个公共前端 CDN,给出两个数字,和前面三种测量可以这样对上:
| cdnping 指标 | 包含什么 | 对应的命令行测量 |
|---|---|---|
| 首次连接 | DNS 解析 + TCP 握手 + TLS 握手,以及第一次请求 | 大致相当于 curl 的 time_starttransfer |
| 往返 | 连接复用后再发 3 次请求,取中位数 | 去掉建连开销后的单次请求往返,接近 tcping 的 TCP 往返加上服务端入口处理时间 |
两个数字差得多,说明大部分时间花在建连上:DNS 慢、RTT 大导致 TCP 和 TLS 握手被放大,或者 TLS 握手本身有问题。这种情况下,客户端开启连接复用(keep-alive、HTTP/2)收益最大。两个数字都高,说明你和入口之间的往返本身就远,复用连接也省不掉。
浏览器测速走的是浏览器的网络栈,开着代理就会经过代理,所以它反映的是“你的浏览器实际访问这些 API 的情况”,这一点和 tcping 在 TUN 模式下只测到本机不同。测量细节见 数据方法。如果想确认自己的出口 IP、是否走了代理、浏览器往返和出口 TCP 往返是否对得上,可以用 IP 与环境检测,其中延迟特征一项正是拿浏览器往返和 Cloudflare 测得的出口 TCP 往返做对比,原理见 网站如何用延迟判断你在用代理。
一份边缘探测数据怎么读
cdnping 的 API 状态页 从 Cloudflare 边缘每 5 分钟探测一次各官方 API 入口。下面取自 2026-10-17 的首批快照:探测节点是 DEN(美国丹佛),窗口为 UTC 08:40–10:05,所有入口合计 242 次探测。cdnping 从这一天才开始采集,数据只覆盖这一个多小时,不是长期统计。数据以 CC BY 4.0 发布。
| 入口 | 中位数(ms) | P95(ms) |
|---|---|---|
| api.anthropic.com | 73 | 84 |
| api.openai.com | 96 | 194 |
| api.deepseek.com | 353 | 414 |
| dashscope.aliyuncs.com | 615 | 1152 |
这些数字主要反映丹佛到各入口的网络距离,海外入口和国内入口的差距来自地理位置,不说明哪家服务更快。中位数和 P95 的差距可以多看一眼:同样的探测,有的入口 P95 接近中位数,有的接近两倍,后者意味着偶发的慢请求更多。你在自己的网络里用 tcping 或 curl 测,排序和数值都可能完全不同,结论要以本地实测为准。