小记:用 frp 让家里的 BT 下载"支棱"起来

家里的电脑在路由器 NAT 后面,做种/下载 BT 资源时,外部 peer 根本连不进来——只能靠自己主动连出去,Peers 数量始终个位数,速度自然上不去。 手头正好有一台便宜 VPS,一直想着能不能借它的公网 IP,把这个短板补上。

目录

起因

家里的电脑在路由器 NAT 后面,做种/下载 BT 资源时,外部 peer 根本连不进来——只能靠自己主动连出去,Peers 数量始终个位数,速度自然上不去。

手头正好有一台便宜 VPS,一直想着能不能借它的公网 IP,把这个短板补上。网上常见的思路是买带端口转发功能的商用 VPN(Proton VPN、PIA 之类),但既然有 VPS,不如自己搭一套更灵活、也更可控的方案——frp

GitHub 地址:https://github.com/fatedier/frp

思路:反向隧道

核心逻辑一句话说清楚:

家里电脑主动连出去,跟 VPS 建一条隧道;外部有人连 VPS 的某个端口时,VPS 把内容通过隧道"搬"回家里。

frp 干的正是这件事——不是传统意义上路由层面的端口转发,而是应用层的"转信":VPS(frps)收到数据后读出来,塞进早就建好的隧道,家里的 frpc 收到后,再原样转发给本地的 BT 软件。全程家里的路由器只知道自己"主动发起了一条连接",跟平时刷网页没有区别,不需要在路由器上开任何端口。

配置示例

服务端 frps.toml(跑在 VPS 上)

bindPort = 8888

auth.method = "token"
auth.token = "换成你自己的随机长字符串"

# 可选:控制通道加密
transport.tls.enable = true

客户端 frpc.toml(跑在家里的电脑上)

serverAddr = "你的VPS公网IP"
serverPort = 8888

auth.method = "token"
auth.token = "跟frps.toml里一样的字符串"

transport.tls.enable = true

# BT swarm里peer密集涌入时,预备的工作连接池不够用,
# 会报 "work connection pool is full, discarding"
# 按观察到的Peers+Seeds峰值来定,够用就好
transport.poolCount = 150

[[proxies]]
name = "bt-p2p"
type = "tcp"
localIP = "127.0.0.1"
localPort = 51413        # BT软件实际监听端口
remotePort = 51413        # VPS上对外暴露的端口

BT 软件里把监听端口固定为 51413,关掉随机端口选项,防火墙/安全组放行对应端口即可。

顺带一提:搭配代理走加密隧道

如果本地直连 VPS 容易被 QoS 限速,可以让 frpc 显式走本地的代理客户端出去,而不是裸连:

transport.proxyURL = "socks5://127.0.0.1:7890"

这样 frp 的控制通道会先经过本地代理再出去,混在正常加密流量里,比裸露的 frp 协议特征更不容易被单独针对。相比让代理软件用全局模式"顺手"接管所有流量,这种显式指定的方式更可控,不容易出现意外的路由问题。

观察链接信息

一开始 Peers 只有 4 个,怀疑端口没通。后来在 frpc 日志里看到密集的:

get a user connection [92.238.37.56:50923]
get a user connection [145.79.182.73:9210]
...

不同国家的真实外部 IP 主动连进来,这是端口双向打通最直接的证据——比软件自带的 Test Port 按钮更"硬核",因为是服务器视角的真实连接记录。

BT 软件里 Peers 列表 Flags 列出现 I 标记,也是同样的意思:这条连接是对方主动连进来的。不过因为经过 frp 转发,本地看到的连接来源会显示成 127.0.0.1(因为是 frpc 在本机重新发起的连接),不是真正的对方 IP,这是正常现象,不是 bug——想看真实来源,得去 VPS 上用 ss 命令查。

关于 NAT 类型检测的一点插曲

试着拿 dyebean.com 这个 NAT 类型检测站测过一次,理论上走 frp 之后,因为固定端口、任何外部地址都能连进来,应该属于最宽松的全锥形(Full Cone)NAT

但实测检测不出来——原因是这类检测站的机制通常是"让你连它指定的端口,它再反过来看能不能连你",而 frp 只映射了固定的那一个端口(比如 51413),检测站没法指定成这个端口去测,天然就测不准。这算是这套方案的一个已知局限:端口转发只解决了"你自己知道的那个端口"的可达性,不是通用意义上把整台机器变成完全公网可达——如果换个端口,一样是不通的,得单独加一条 [[proxies]] 配置才行。
img

效果

调整完之后,Peers 从个位数冲到两百多(对方主动连接进来的IP会展示为127.0.0.1,这个ip会被算为1个peer),下载速度从 几 MiB/s 起步,慢慢跑到十几 MiB/s,个别时刻甚至到过 20+ MiB/s。

过程中也顺手搞明白一个点:BT 是互惠协议,choking algorithm 会优先把带宽让给"对我大方"的 peer——上传表现差,下载速度自然也不稳定。多喂一点上传,下载反而更持续。这个"信用"只在当前种子的 swarm 里有效,公开种子换一个资源就清零重来,只有私有 tracker 才会跨种子累计成账号的分享率。
img

一点总结

配置本身不复杂,麻烦的地方在于理解每一层到底在做什么——控制连接和工作连接的区别、连接池的作用、代理和隧道谁先谁后——一旦想明白"谁在跟谁说话",排查起来就顺畅多了。