它测什么,怎么测,为什么可信
网页测速回答「我有多快」。portbug 回答的是另一类问题:哪个端口、哪个方向、在第几跳被限住了 —— 并给出一份能拿去跟机房或运营商对质的记录。
浏览器做不到的六件事
本站首页那个测速页只能测 HTTPS/443,那不是偷懒,是沙箱的上限。下面这些必须用本地程序:
浏览器只能发起 80 / 443 的连接。8080、3389、5060、51820 一概碰不到。
WebRTC 之外发不出裸 UDP 包,RDP / 游戏 / 音视频的真实上限测不到。
需要逐秒吞吐序列与同链路对照端口,JS 计时被缓冲和 TLS 层抹平。
需要构造 TTL 递增的 SYN 包,浏览器碰不到 IP 层。
rtt / retrans / snd_cwnd / delivery_rate 是内核态数据,JS 读不到。
需要控制包长与 DF 标志位,浏览器无此能力。
四条不肯妥协的规矩
只测一个端口然后说它被限速,那是猜的。没有同节点、同时段、同方向的可用对照端口时,结论一律是「无法判定」,不管数据多难看。宁可不出结论,也不出一个错的。
时长在握手里由两端协商,各自按自己的时钟停。按字节的测试在慢链路上要跑几分钟,在快链路上只采到三个点 —— 两头都测不准。
限速只有一端知道会死锁:发送方按限额节流,接收方在等永远不会被安排发出的字节。所以限额写在握手帧里。
拐点用变点检测(对均值做 Fisher 式打分)而不是「第一个低于阈值的样本」,两段速率取中位数,还要求掉档后至少 85% 的样本维持低位。早期版本会把 TCP slow-start 的第一个尖峰报成「掉档」—— 对一份要拿去吵架的报告来说,虚报比漏报危害大得多。
「所有端口」是怎么做到的
监听 65535 个 socket 是不现实的。真正的做法是内核重定向:Linux 上用 nftables 把 1–65535 全部 REDIRECT 到一个 socket,再用 SO_ORIGINAL_DST(TCP)和 IP_ORIGDSTADDR(UDP)把原始目的端口交还给进程。
用 REDIRECT 而不是 TPROXY 是刻意的:REDIRECT 是 NAT 规则,conntrack 会把回包的源端口改回客户端瞄准的那个端口,节点不需要 IP_TRANSPARENT 那一整套。
怎么证明它真的生效了
节点在每个 ack 里回传它实际收到的端口号。客户端拿它和自己请求的端口比对,不一致就判定本次测量作废并拒绝发布 —— 捕获规则写错时,报告上的端口号会是错的,而这种报告是要拿去对质的。
一个已知缺口,写在这里而不是藏起来:capture 模式下的 UDP 端口号目前无法回证。TCP 用 SO_ORIGINAL_DST 向 conntrack 查 NAT 之前的目的地;UDP 的 IP_ORIGDSTADDR 给的是数据报到达 socket 时携带的目的地,而 REDIRECT 早已把它改写过了。所以这种情况下节点回传 0(=未验证),客户端如实标注「端口号未经节点回证」,而不是报一个错的端口号。吞吐、丢包、抖动这些数值本身不受影响。彻底解决要把 UDP 侧换成 TPROXY(不做 NAT,原始目的地得以保留)。
没有 root 或不在 Linux 上时,节点退化成显式端口段监听,并在节点列表里如实标成 range 模式,不假装支持全端口。
可以用标准 iperf3 复核
节点在每一个端口上同时接受 iperf3。portbug 自己的协议只有读源码才能审计,而 iperf3 是每个网工都已经信任、也已经装好的工具 —— 一个没人能独立复现的测量结果不算证据。
$ iperf3 -c 47.116.36.78 -p 8080 -t 5 -P 2 # 任意端口都行
能这么做是因为 iperf3 的控制流和数据流走同一个 TCP 端口,一条重定向规则就覆盖整场会话。节点看连接的前 4 个字节分流:PBUG 是我们的,其余原样转给本机 iperf3(只监听回环,不直接对外)。
看结果时注意 sender 和 receiver 往往不一样:sender 是写进 socket 的量,receiver 是真正过了链路的量。链路被限速时,前者会把后者甩开一大截 —— 这正是「一个平均数说明不了问题」的现场演示。
端口不通时,到底是谁挡的
失败有三种形态,含义完全不同,分开报比只说「不通」有用得多:
| 形态 | 含义 |
|---|---|
| RST(refused) | 主机在线但该端口没有监听,或被明确拒绝。通常不是中途丢包。 |
| 超时 | 数据包被静默丢弃,常见于中途防火墙或对端安全组。 |
| ICMP unreachable | 路径上有设备明确拒绝转发。 |
一次真实的判定长什么样
$ portbug port 8080 --to sh-01 ■ TCP/8080 下行 ▁▄███████▁▁▁▁▁▁▁▁▁▁▁ 3.1 Mbps 掉档 @1.83s · 桶 ≈ 20.1 MB ■ TCP/443 下行 ▁▄███████████████████ 94.2 Mbps 对照 · 平稳 判定 TCP/8080 存在端口级令牌桶整形,稳态 3.1 Mbps 同时段同链路的对照端口未出现掉档,可排除总带宽受限与本机瓶颈。 置信度 高 报告 https://portbug.allog.com/r/3F7A2C
报告页带编号、时间戳、方法学和原始逐秒数据的核对链接,可以直接打印成 A4 附进工单。方法学那一段从不折叠隐藏 —— 报告的可信度就来自那里。
退出码
退出码是接口的一部分,脚本和 CI 不用解析文本:
| 码 | 含义 |
|---|---|
| 0 | 达标 |
| 1 | 未达阈值 / 判定异常(整形、降级) |
| 2 | 端口不通 |
| 3 | 节点不可达 |
| 4 | 配额耗尽 |
| 5 | 用法错误 |
风控与隐私
只能测到 portbug 自己的节点。 客户端不接受任意目标 IP —— 一个能对任意地址打流量的工具就是压测/攻击工具,这条是从架构上堵死的,不是靠提示语。
客户端会采集本机出口 IP、路由与 ISP,用于生成报告;不采集与测量无关的信息。发布报告始终是显式动作(--publish,或页面上点一下),报告可设为私有。