通过端口限速,给 Snell 限流

由于云服务商给的 VPS 速度太优秀了,看流媒体时会自动播放最高质量的内容,VPS 流量很快就会被用完,因此不得不做一下限速、让流媒体不要直接拉到画质天花板。

我部署在服务器上的代理工具是 Snell,但它并不支持通过配置文件指定网络带宽。替代方案是用 tc 来限制出网卡(egress)方向,实现对 Snell 端口的限速。

限速目标

这台 VPS 只给了每月 150G 的配额,我预期用 100G 来看流媒体,50G 日常使用。我常看的流媒体是 Apple TV,查了下 15Mbps 这个速率是刚好足够观看 4k 画质的。

流量估算

  • 15Mbps ≈ 1.875MB/s ≈ 6.59GB/小时
  • 100GB ÷ 6.59GB/小时 ≈ 15.2 小时

满打满算的情况下,100G 够看 15 小时的 Apple TV,我觉得完全没问题,我一个月可能都看不了 15 小时电视。

限速脚本

VPS 上已经有一个跑着的 snell 服务了,换个端口号单独写一个配置文件,然后再开一个服务,对这个服务所使用的端口号进行限制即可,之后在 Surge 客户端中添加为一个新的服务器。

这里我已经创建好了新的服务,端口号用 12345,服务名为 snell-stream

创建并编辑限速脚本:

nano /usr/local/bin/snell-tc.sh

写入内容:

#!/bin/bash
IFACE=eth0        # 替换成实际网卡名,用 ip a 查看
PORT=12345        # 替换成实际 snell 端口

### 清理旧规则(可选,重复执行脚本时先清空)
tc qdisc del dev $IFACE root 2>/dev/null
tc qdisc del dev $IFACE ingress 2>/dev/null
ip link del ifb0 2>/dev/null

### 下行限速:server 发出的流量 (sport = PORT,TCP/UDP 都覆盖) 限 15Mbps
tc qdisc add dev $IFACE root handle 1: htb default 30

tc class add dev $IFACE parent 1: classid 1:1 htb rate 1000mbit
tc class add dev $IFACE parent 1:1 classid 1:10 htb rate 15mbit ceil 15mbit
tc class add dev $IFACE parent 1:1 classid 1:30 htb rate 1000mbit ceil 1000mbit

tc qdisc add dev $IFACE parent 1:10 handle 10: sfq perturb 10

tc filter add dev $IFACE protocol ip parent 1: prio 1 u32 \
    match ip sport $PORT 0xffff flowid 1:10

echo "限速已生效: $IFACE 端口 $PORT 下行15Mbps (TCP+UDP)"

如果哪天需要更换成其他速率比如 10Mbps,只要改动其中的这一行:

tc class add dev $IFACE parent 1:1 classid 1:10 htb rate 10mbit ceil 10mbit

以及这一行:

echo "限速已生效: $IFACE 端口 $PORT 下行10Mbps (TCP+UDP)"

给脚本赋予执行权限:

chmod +x /usr/local/bin/snell-tc.sh

使用 systemd 进行管理

创建并编辑 service 文件:

nano /etc/systemd/system/snell-tc.service

写入内容:

[Unit]
Description=Snell port rate limit
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/snell-tc.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

启用并立即运行:

systemctl daemon-reload
systemctl enable --now snell-tc.service

之后如果修改了脚本,重启一下服务即可:

systemctl restart snell-tc.service

验证

Surge 客户端

在 Apple TV app 中播放起来,然后到 Surge 的 工具—实时统计—策略 中检查对应策略的当前速度和最高速度,网络状况好的时候当前速度和最高速度都是 1.9MB/s,但最高不会超过这个速度。

也可以直接在 工具 中开启实时浮窗,这个更直观一些。

服务器端

通过 nethogs 工具可以直观看到每个进程的实时网络速率,通过 PID 来识别 snell 进程。

首先找到已经做了限速的 snell 服务的端口号:

systemctl status snell-stream.service
● snell-stream.service - Snell Proxy Service
     Loaded: loaded (/etc/systemd/system/snell-stream.service; enabled; preset: enabled)
     Active: active (running) since Thu 2026-08-06 07:39:39 IST; 1 day 4h ago
 Invocation: 4716628ad98a4171868175db130df941
   Main PID: 11756 (snell-server)
      Tasks: 2 (limit: 506)
     Memory: 7.1M (peak: 17.8M)
        CPU: 4.785s
     CGroup: /system.slice/snell-stream.service
             └─11756 /usr/local/bin/snell-server -c /etc/snell/snell-stream.conf

然后使用 nethogs 检查进程的实时速率:

nethogs eth0

NetHogs 显示 snell-server 网络流量监控,eth0 接收流量约 1678 KB/s

可以看到这里面有两个 snell 在跑,而 PID 为 11756 的 snell 进程正是刚刚做了限制的那个,现在还没有达到 1.9 MB/s 的上限,预期不会超过上限值。

评论