Releases: Kylin010/tcpfit
Release list
v0.5.6
主要修复
测速偶发偏低会把整形值压到实际带宽的三分之一
一台 40 Mbps 的香港机器跑向导,近端 iperf3 三次里有一次掉到 13 Mbps。旧版本直接采信这一次读数,扫描区间被整个钉死在 25 以下,最终持久整形到 12 Mbit,国际接收只剩约 10 Mbps。
现在:不限速单流结果低于自动探测带宽的 70% 时,会在同一个对端追加两次测试,三次取送达量最高的那一组。取的是整组结果 —— 发送量、接收量、重传、丢包必须来自同一次测试,不会互相串。
三次都低也不会中断、不会换对端,继续按原有逻辑找拐点。首轮就达到 70% 的机器不增加任何运行时间。
对照(标称 40 Mbps,单流一次读到 13.0 / 34.5% 丢包,真实水平 37.4):
旧版本 采信 13.0 -> 扫描 12..25 档 -> 没找到可用拐点
本版本 补测 37.4 / 37.0 -> 取 37.4 -> 丢包 0.0000%
-> 判定无限速器, 一档都没扫, 不下整形
一键调优跑完不再自动回主菜单
调优要跑十几分钟,结果页面是唯一要看的东西。之前跑完停在「按任意键返回」,回菜单会清屏,而清屏指令连滚动回滚缓冲一起清掉 —— 往上翻也找不回结果。
现在一键调优跑完直接退出,结果留在屏幕上。要继续操作重新运行 tcpfit 即可。
「按任意键返回」不再被误触发
调优期间随手按的键会留在终端缓冲里,跑完的瞬间就把提示符吃掉,结果一眼没看见就回了菜单。现在会先清掉这些残留按键,只有真正按键才返回。
退出时也会一并清掉 —— 否则这些残留会被上层 shell 当成命令执行。
更新
tcpfit update
或在菜单中选择 8。更新后重新运行一次 tcpfit。
首次安装
bash <(curl -fsSL https://raw.githubusercontent.com/Kylin010/tcpfit/main/tcpfit.sh)
v0.5.5
主要修复
多队列网卡(10G / 多核大机器)的整形与恢复
10G 机器开机后的默认结构是 mq + 每个硬件队列一个 fq。这类网卡上:
- 之前
tc qdisc del dev eth0 root会直接失败(Cannot delete qdisc with handle of zero.),扫描和整形都装不上 - 取消整形(
shape --off)会把mq压成单个 fq,8 个硬件队列退化成一把锁 - 恢复时不再把多队列网卡压成单 root fq,而是保留
mq只替换它自己的叶子
已在真实 8 队列 10G 网卡上验证:扫描、整形、取消整形、保存/恢复四条路径全部正常,clsact(eBPF)不受影响。
小带宽机器:很浅的限速点不再被当成线路底噪吞掉
真实限速器的第一层损失可以只有 0.18%。旧逻辑会把这种浅损失当成"链路本身的噪声",于是错过真正的拐点,最后给出偏高的整形值。
300M 机器实测(4 轮换序,每档 15 秒冷却):
316M 0.0003% 319M 0.1911% ← 真正的拐点在这里
317M 0.0003% 320M 0.4352%
318M 0.0006% 322M 1.0125%
现在遇到首档就丢包时,会向下测控制点来区分「真拐点」和「路径底噪」,最多三次;宁可不给整形值,也不把仍在丢包区的值推荐给你。
低带宽机器升级后会清掉旧版本的 initcwnd
100M 以下的机器保留内核默认的初始拥塞窗口。之前版本设置的 initcwnd 32 会被主动清除(包括开机自动写回的 hook)。
三台 10-20M 实机的对照:initcwnd 32 会导致首秒暴冲后被限速器打穿,之后每秒吞吐都掉一档,重传是默认值的 3-5 倍。
只清除 tcpfit 自己设过的;用户手工设的不动。
其他
- 扫描第一档前增加 15 秒冷却。不限速探测会把限速器的令牌桶抽干,之前 3 秒不够回,导致第一档带着假丢包,进而污染整个扫描的判断基线
- HTB 令牌桶按速率推算。2G/7G 机器接收吞吐提升 0.5~2.3%,1G 以下无差别
- 缓冲区上限增加 2MiB 余量
- 大带宽扫描保护:单流结果可疑时补测 8 流,避免误扫超出上限的区间
更新
tcpfit update
或在菜单中选择更新。更新后需要重新运行一次 tcpfit 才会用上新版本。
首次安装:
bash <(curl -fsSL https://raw.githubusercontent.com/Kylin010/tcpfit/main/tcpfit.sh)
v0.5.4
主要修复:向导误报「本机没有 IPv4」导致流程中断
现象
跑向导时屏幕出现:
本机没有 IPv4, 测速走 IPv6
但机器明明有 IPv4,也没有 IPv6。随后走到「对端 IP」那一步直接退出:
公共测速服务器暂时都不可用, 稍后再试
测速服务器是好的,是脚本自己把协议族选错了。
什么样的机器会中
1 核 VPS + 有第二块网卡(最常见是用 Docker 装的面板留下的 docker0)。
两台客户机实测中招率 96% 和 99%;2 核约 1%(偶发,重跑一次就好,但现象一模一样,最难排查);4 核以上基本不会。
和发行版无关 —— Debian 11 / 12、Ubuntu 都复现;在同一台机器上换 iproute2 5.9 / 5.15 / 6.1 三个版本,也都复现。
根因
脚本顶部是 set -uo pipefail,而 have_ipv4 写成 ip … | grep -q 'inet '。
grep -q 一匹配就退出并关掉管道,写端 ip 还没写完就吃 SIGPIPE 被杀(退出码 141),pipefail 把 141 当成整条管道的返回值——「匹配到了」被读成「没匹配到」。
只有匹配成功时才会触发,所以表现为「机器真的有 IPv4 → 报没有 IPv4」。
此外旧版判不出 v4 就无条件切 IPv6,从头到尾没检查过机器有没有 IPv6。
改动
- 全脚本 14 处
| grep -q清零,改用命令替换 +case(26 个用例差分测试确认行为等价) have_ipv4/have_ipv6增加ip route get兜底 —— 默认路由不一定叫default,机器上跑 VPN / 透明代理时常被拆成0.0.0.0/1+128.0.0.0/1或挪进策略路由表- 切 IPv6 前必须先确认 IPv6 可用;两边都判不出来时保持 IPv4 并明确说明
小带宽机器(100 Mbps 以下)现在能正常调优了
三台 10-20 Mbps 的机器上,旧版 9 次扫描全部失败。四个原因:
probe_bandwidth把结果取整到 50 的档位,10 Mbps 直接归零 → 向导打印Measured ~0 Mbps后退出- 扫描步长硬下限 20,而小机器的扫描区间可能只有十几宽 → 只能采到 2 个点,找不到限速点
- 扫描区间用 iperf3 发送端数字推算,丢包链路上它远高于实际送达量 → 起点直接落在丢包区
- 安全余量对 100M 以下一律退 5 —— 15 Mbps 的线会被限到 10,白丢三分之一
现已分别修正:取整粒度跟档位走、步长按区间宽度推、区间改用实测送达量、余量按比例分档(≤30M 退 1、31-60M 退 2)。
其他修复
- 整形值为整千时验证误判 ——
tc会把1000显示成1Gbit,旧的解析剥不掉单位,导致跳过达成率判断。速率解析已统一成一个公共函数,11 个档位实测通过 - 机器没装
ping时甩锅测速服务器 —— 现在直接说明缺什么、怎么装;向导也会单独检查并询问安装(此前只在安装 iperf3 的分支里问,装了 iperf3 却没 ping 的机器永远问不到) - 重复跑向导时的整形残留 —— 这次没测到限速器时会主动清掉上次的限速;结果页和
verify改为读取网卡实际状态,不再出现「屏幕写未设置、网卡上还挂着旧值」 - 扫描过程中的 qdisc 残留 —— 修复扫描结束后 HTB 仍留在网卡上、屏幕却打印
qdisc restored的问题
更新方式
tcpfit update
或在菜单中选择更新。更新后需要重新运行一次 tcpfit 才会用上新版本。
首次安装:
bash <(curl -fsSL https://raw.githubusercontent.com/Kylin010/tcpfit/main/tcpfit.sh)
v0.5.3
RTT 不再探测,改用固定值
以前算缓冲区要先 ping 五个国内 DNS 测「到中国的延迟」。这一步现在去掉了,直接用 150ms。
为什么去掉:
一、测出来的值经常是错的。 那五个目标里,腾讯、百度、CNNIC 三个是 anycast —— 会命中离你最近的节点。实测一台香港机器:这三个报 1-2ms,而真正的国内线路是 138-145ms,差 70 倍。
算小了之后缓冲区掉到 4MB 下限,而 4MB 正好是 Linux 的出厂值 —— 等于调了个寂寞,脚本还会打印一份看起来完全正常的推导过程。实测一台 2G 口的机器因此被摁在 100-220 Mbps。
二、有些机器根本测不了。 精简系统镜像不带 ping,有些机房挡 ICMP。这两种情况都会让脚本停在「无法确定 RTT,请用 --rtt 指定」—— 而向导里根本没地方填这个参数。
三、「到中国的延迟」本来就不是一个数。 同一台机器同一时刻实测:移动 55ms、联通 93ms、电信 138ms、上海电信 145ms,差 2.6 倍,晚高峰还要再拉开。测出来的只是这个分布里随机的一个点。
为什么是 150
缓冲区取 2 倍 BDP,所以填 150 能全速覆盖到 300ms 以内的路径。大陆用户的场景全在里面:
| 线路 | 延迟 | 覆盖 |
|---|---|---|
| 香港/新加坡优化线 | 40-70ms | ✓ |
| 香港普通线 | 145ms | ✓ |
| 美西 | 160-180ms | ✓ |
| 欧洲 / 美东 | 230-250ms | ✓ |
| 晚高峰拥塞 | 300ms | ✓ |
再往上没有收益:小内存机器会先被内存上限接住(512MB 封顶 16MB),填 150 还是 300 结果一样;大机器上则要多付代价 —— 实测缓冲区超配到 215 倍时,吞吐反而掉 22%。
知道自己真实延迟的,可以自己填
tcpfit tune --role proxy --bw 500 --rtt 250比如你的机器在欧洲、用户在国内,实测 250ms,填进去比默认更准。这个参数以前没有校验(填错会掉进那条误导性报错),现在会明确提示。
顺带
tune 从此不再需要 ping 命令。
升级
菜单 8,或者:
tcpfit update安装
bash <(curl -fsSL https://raw.githubusercontent.com/Kylin010/tcpfit/main/tcpfit.sh)校验
6c86b31c3d937736bb4d919b04b732013cbb2da958d97841b34cd663fd2a6b35 tcpfit.sh
8a521bcc2f89c336fba239d7b722cede8638ac9df06b28eb8be1536a22fd5085 install.sh
v0.5.2
必修:选 IPv6 会崩在「无法确定 RTT」
如果你在开头那一问选了 v6,接着看到:
[+] Measured ~1150 Mbps
[x] 无法确定 RTT, 请用 --rtt 指定
这是 v0.5.0 引入的问题,跟你的机器无关,本版修好了。
原因:算缓冲区要用「到国内的延迟」,而这个延迟不该跟着测速协议族走 —— 你选 v6 只是为了测对端,业务流量可能还走 v4。v0.5.0 错误地把它绑在一起,导致选 v6 之后延迟探测必然失败。
临时绕过(不想升级的话):那一问选 v4(直接回车就是)。
纯 IPv6 机器现在能找到网卡了
只有 IPv6 的机器之前会停在「找不到默认路由网卡」—— 这个从 v0.4.5 及更早就存在,一直没跑起来过。
手填 IPv6 对端地址不再被拆错
之前填 2001:db8::1 会被按最后一个冒号拆成「主机 2001:db8: + 端口 1」,然后拿着错的地址继续跑,一句提示都没有。
现在这六种写法都能正确识别:
1.2.3.4 example.com
1.2.3.4:5202 example.com:5202
2001:db8::1 [2001:db8::1]:5202
端口填错会当场重问,不再静默接受。
纯 IPv4 机器不再看到「检测不到 IPv4」
之前这句是无条件打印的说明文字,但纯 IPv4 机器(绝大多数)只看得到这一行,容易误以为脚本没认出自己的 IPv4。现在纯 v4 机器不再显示这句。
升级
菜单 8,或者:
tcpfit update安装
bash <(curl -fsSL https://raw.githubusercontent.com/Kylin010/tcpfit/main/tcpfit.sh)校验
3aa22fad6e0d954a63d292c9cd1368b67d7c7c2c0ee95b7f0368781e8b6912fc tcpfit.sh
8a521bcc2f89c336fba239d7b722cede8638ac9df06b28eb8be1536a22fd5085 install.sh
v0.5.1
重要:如果你更新到 v0.5.0 后发现问题依旧,不是修复没用
更新完请退出 tcpfit 再重新进一次。
v0.5.0 及之前的版本有个问题:菜单里按 8 更新,新版本确实写进磁盘了,但当前这个进程内存里跑的还是旧代码。而更新完的提示写着「想让新版参数生效,重跑一次调优」,用户很自然就在同一个菜单里按 1 —— 跑的仍然是旧版本,于是「更新了但 bug 还在」。
已经更新过的:直接退出、重新运行 tcpfit 就好,不用重新下载。
本版修复
更新后自动用新版本重启
菜单里更新完会自己换成新版本重开;命令行 tcpfit update 则明确提示当前进程仍是旧代码、需要重新运行。
更新时不再原地覆盖正在运行的脚本
之前是直接覆写 /usr/local/bin/tcpfit,而那正是当时正在执行的文件。改成先写临时文件再原子替换,正在运行的进程不受影响。
升级
菜单 8,或者:
tcpfit update安装
bash <(curl -fsSL https://raw.githubusercontent.com/Kylin010/tcpfit/main/tcpfit.sh)校验
a1960b8042b667571575b7bf374485b2c2420f04501a32f999b73339a4724085 tcpfit.sh
8a521bcc2f89c336fba239d7b722cede8638ac9df06b28eb8be1536a22fd5085 install.sh
v0.5.0
修复:部分机房封了 5201,脚本会找不到任何测速对端
有机房为防止有人用 iperf3 刷流量,封掉了出站 5201(iperf3 的默认端口)。在这种机器上,脚本会把全部 18 个节点报成 port closed,最后提示「公共测速服务器暂时都不可用,稍后再试」—— 但服务器好好的,换个端口就能用。
现在选对端时会自动轮换 5201 → 5202 → 5203 → 5200,找到能用的就继续,界面上会显示 5201→5202 告诉你端口变了。第一个节点探出可用端口后,其余节点直接复用,不会拖慢。
如果你之前遇到「所有节点都 port closed」,升级即可。
顺带补上 Clouvider 节点的 5200 —— 他们开的是 5200-5209 而不是 5201-5210,之前那两个节点有一个实例一直没被用到。
新增:IPv4 / IPv6 协议族选择
- 默认走 IPv4
- 检测不到 IPv4 时自动走 IPv6
- 双栈机器会在开头问一句,回车 = v4
tcpfit sweep支持-4/-6指定
同一个对端在两个协议族下延迟可能差很多(实测见过 v4 133ms / v6 308ms)。现在 ping 和 iperf3 锁定同一个协议族,不会出现「按 v6 的延迟挑节点、却用 v4 测速」这种情况。
升级
菜单 8,或者:
tcpfit update安装
bash <(curl -fsSL https://raw.githubusercontent.com/Kylin010/tcpfit/main/tcpfit.sh)校验
b28752b7efad9e7ae3615f7c8c190a809733568ede5b05cdf39e49621a4f72c4 tcpfit.sh
8a521bcc2f89c336fba239d7b722cede8638ac9df06b28eb8be1536a22fd5085 install.sh
v0.4.5
升级
tcpfit update改动
调优结尾的 swap 提示改成输入大小
原先是 y/n 固定建 2G, 现在可以指定:
▸ swap
本机 961 MB 内存且没有 swap. 跑代理时 TCP 缓冲区可能撑爆内存,
代理进程被系统杀掉.
输入 1-20 的数字(单位 GB), 推荐 1-4;回车 = 2;输入 0 = 不创建.
swap 大小 GB [2]:
非法输入会循环重问, 不再退出脚本
原先把输入直接丢给 harden, 非法值触发它的 die, 整个脚本跟着退出 —— 连 "调优完成" 都打不出来. 这正是 v0.4.3 上 "按 y 之后直接结束" 的成因.
现在 abc、99 这类输入只会提示重输.
| 输入 | 结果 |
|---|---|
| 回车 | 建 2G |
4 |
建 4G |
2G |
建 2G |
0 |
跳过 |
abc / 99 |
提示重输 |
继承 v0.4.4
harden --swap 2G 被误判为非法参数的问题(v0.4.2 引入).
v0.4.4
升级
tcpfit update修复
调优结尾的「创建 2G swap?」按 y 之后直接退出
小内存机(≤1G)且没有 swap 时, 一键调优结尾会问要不要加 swap. 按 y 之后脚本直接结束, swap 没被创建, 连 "调优完成" 都没打出来.
原因: v0.4.2 为了修「--swap 2M 会建成 2GB」把参数校验改成只收纯数字, 但向导和文档里写的都是 --swap 2G, 带单位的写法被一并挡掉, 触发 die 让整个脚本退出.
现在 2 和 2G 都收, 仍然拒绝 2M 这类会引发歧义的写法:
--swap 2G ✓
--swap 2g ✓
--swap 2 ✓
--swap 2M ✗ 拒绝(fallocate 建 2MB 而失败回退的 dd 建 2GB, 差 1000 倍)
--swap 0 ✗
--swap 21 ✗
顺带把参数校验挪到存快照之前 —— 打错参数不该留下状态文件.
受影响的还有
- 脚本自带用法说明里的
tcpfit harden --swap 2G - 基础调优结尾给小内存机的建议
tcpfit harden --swap 2G
这两条在 v0.4.2 – v0.4.3 上直接执行也会失败.
v0.4.3
升级
tcpfit update改动
手填测速对端时当场校验可达性
原先填错 IP 或端口要等到执行阶段才发现, 那时前面三个问题都白填了, 而且 sysctl 已经改过.
对端 IP / 域名(回车=公共节点): 192.0.2.99
检查 192.0.2.99:5201 … 连不上
常见原因: 对端没在跑 iperf3 -s / 端口填错 / 防火墙挡了 / IP 打错
回车可以改用公共节点.
对端 IP / 域名(回车=公共节点): 10.0.0.5
检查 10.0.0.5:5201 … 可达
连不上就当场重填, 也可以回车改用公共节点. 支持 IP:端口 写法.
继承 v0.4.0 – v0.4.2
- sweep 失败时不再应用上一次的限速值
- 细扫不再丢掉粗扫已找到的拐点
- 扫描区间终点必测, 高丢包时上界按丢包率放宽
- verify 的重传判定改用丢包率
- 锁被占时列出持有者并可一键结束, 且只杀记录的 PID
- Alpine / BusyBox 兼容