最近在机缘巧合之下入了几个 pt 大站。大站下载人数多,总的来说还是比较好混的。但是为了永久保留账号,需要刷一定的上传流量。在苦恼于硬盘空间不足无法大量保种的同时,还有一个很重要的问题就是没有公网 ip 。家里的宽带是电信内网 v4+公网 v6 ,虽然有 ipv6 地址,并且大部分 pt 都支持 v6 tracker ,但是总的来看 ipv6 无论是做种还是下载人数都是远远少于 ipv4 的。所以一直想要一个公网 ip 。给运营商要公网 ip 好几次,都被打太极给拒绝了。因为之前研究过 nat 以及打洞相关的知识,就想研究一下没有公网 ip 是否也可以把某个端口暴露在公网上。恰好家里宽带是 nat1 ,经过一番折腾,发现了一种可以在 nat1 下将某个端口暴露在公网的办法,在这里分享给大家。
1 第一步当然是打开 BT 客户端。这里以 qbittorrent 为例,假设 qbittorrent 的 BT 监听端口,即 local port 为 12345
2 将 local port 和 nat 防火墙对应的 external port 之间的映射打开。由于 qbittorrent 已经监听了 12345 端口。所以无法通过创建一个新 socket 进行发包。当然,你可以重新编译 qbittorrent ,加上 SO_REUSEPORT 标志,但是这里为了快速实验,使用基于 raw socket 的 sendip 工具进行网络包创建,命令如下:
watch -n 1 sendip -p ipv4 -is <LOCAL_ADDR> -id <YOUR_VPS_ADDR> -p tcp -ts 12345 -td <ARBITRARILY_PORT> <YOUR_VPS_ADDR>
这里使用 watch 命令每秒执行一次 sendip 命令,是因为我这里的 CGN nat 在未建立连接的情况下超时时间非常短,只有 5 秒。作为对比,linux 下 iptables 的 conntrack 模块在 NEW 状态下会持续 180 秒。所以需要每秒发一次包保持连接。注意,这个命令在之后需要一直运行以保持 nat 映射,即使已经端口映射成功。
命令中-td 表示的目标端口可以随意指定
3 在 vps 上抓包获取 external port 。使用 tcpdump 抓取上一步中发送的网络包,从而获取到 local port 12345 对应的 external port ,这里假设为 54321 。
4 本地部署 mitmproxy ,抓取 qbittorrent 的 tracker 请求。这里 qbittorrent 需要修改三个设置:
5 通过 mitmproxy 自定义脚本修改 tracker 请求中的 port 参数。官网有一个示例,将参数换为 port ,参数的值替换为第三步中得到的 external port 54321 即可。
6 大功告成
我从以下三方面验证了内网的 12345 端口已经打开在了公网上:
可以看出,通过(很麻烦的)折腾,是可以达到将 BT 客户端的 nat1 端口映射到公网的目的的。这主要归功于 nat1 的特性,所以显然 nat234 都不能使用。这个方法应该只在 PT 的情况下比较实用,毕竟如果是打洞的话,有一台有公网 ip 的 vps 就已经可以完成打洞了。这次试验结果来看还是很成功的,发现了一种将 nat1 主机的某个端口打开到公网的方法,但是使用上述方法显然不能完成自动化,大部分操作都需要手动配置。所以如果可以开发一款 C/S 软件,自动化的打开 nat 映射,服务端抓包,获取外部端口,结果发送到客户端,可以极大地简化上述操作,并且在 nat 映射发生改变的情况下自动的更改外部端口。
为了简化流程,方便自动化,我改进了之前的流程
相比原流程,新流程使用的工具更简单,更方便自动化布署。如果之后有时间我会写成脚本发布。
刚看了一下STUN协议标准,发现STUN竟然支持使用TCP连接,而公共的STUN服务器可是有很多的。感觉此贴可以终结了。
用go写了一个小工具,可以保持nat映射,以及将外部端口输出到文件,包装成docker镜像了,欢迎大家使用
1
br2049 2022-08-09 21:05:59 +08:00
感谢 思路很清晰
|
2
terrancesiu 2022-08-09 22:13:33 +08:00 via iPhone
很厉害,学到了
|
3
LnTrx 2022-08-09 22:32:11 +08:00
很好的想法。过程中涉及很多方面技能的综合运用,或有用于教学的潜力。
|
4
ScotGu 2022-08-09 22:52:40 +08:00
谢谢,然后拿起电话继续拨打一万号要公网 IP 。
|
5
v2tudnew 2022-08-09 22:53:48 +08:00
如果有软件自动化还是不错的。
|
6
isad 2022-08-09 23:36:56 +08:00 1
我也这样设想过,但没有实施,因为我发现 DHT 直接就会用你的公网端口,只需要下载个热门种子“启动”一下就好了
|
7
hello365 2022-08-10 09:10:40 +08:00
请教一下,如果 qb 勾选了 Use proxy for peer connections 是不是 pt 站显示的就是 vps 的 ip 了?如果本地 debian 和 vps 通过 tinc 、wireguard 这类的组网软件组成一个局域网,然后 vps iptables 转发到 qb 是不是也可行?只是所有流量都是通过 vps 进来的链路更长了。
|
8
FrankAdler 2022-08-10 10:15:49 +08:00 via iPhone
牛逼啊,移动 nat1 有救了,虽然我有公网用不上
|
9
delpo OP @isad DHT 我测试了一下,qbittorrent 会使用设置中的监听端口,通过 udp 发送 dht 查询消息. 但是具体到连接 peers 进行下载的时候,除非你把 peers 传输协议设置为仅μtp, 否则还是会优先使用 tcp 进行连接. 由于 tcp 和 udp 的 nat 映射不一样, 所以连接性依然不是很理想. 即使设置为仅μtp, 也同样只能在 nat1 下接受入站连接.
不过话说回来,既然使用 DHT,就意味着在下载公网的种子,其实只要有速度,连接性好不好也不是很重要了,毕竟公网种子不强制要求上传. |
10
delpo OP @hello365 我这个实践里,vps 仅用于获取本地客户端在 nat 防火墙外的 external port, 而不是用来架代理的. mitmproxy 是和客户端一样搭建在本地的,所以源 ip 依然是你本地的 ip.
至于你说的,相当于通过 vps 代理下载. 相关教程很多就不赘述了 |
11
FrankAdler 2022-08-10 10:30:43 +08:00 via iPhone
自动化的话,这套 cs 软件就是在提供打洞的基础上代理并修改 tracker 的流量,看起来是可行的🤔,可能 mitmproxy 需要在 c 端再实现一个才能自动化
|
12
delpo OP @hello365 你勾选 Use proxy for peer connections 相当于是把 BT 协议和 μtp 协议代理到 mitmproxy 里, 大概 mitmproxy 处理不了这两个协议汇报错吧.
|
13
isad 2022-08-10 10:47:46 +08:00
@delpo 你搞错了吧,DHT 是别的主机交换信息后来找你连接,至于为什么都是 μtp ,是因为 qb 就只支持 udp 打洞。
我没有用过公网 ip ,分享率依然有一点几 |
14
delpo OP @isad 不好意思,我写错了,应该是: 除非"你"把 peers 传输协议设置为仅μtp --> 除非"别人"把 peers 传输协议设置为仅μtp
因为大部份 BT 客户端默认情况都是基于 TCP 的 BT 协议优先,这个是没有问题的 |
15
ChangeTheWorld 2022-08-10 13:58:53 +08:00
这 NAT 都把人逼成啥样了,各种骚操作都出来了,IPv6 任重而道远啊
|
16
lanlandezei 2022-08-10 14:27:54 +08:00
收藏了 过程太复杂了操作不来,期待大佬做个自动化软件
|
17
mxuan 2022-08-11 01:40:21 +08:00
mark 一下,很有价值,很想尝试一下。
|
18
hello365 2022-08-11 08:52:45 +08:00
嗯,感谢解答,另外还有个疑问,sendip 里面指定-td 我理解的是将在 cgn nat 上申请的从 local 公网端口到 vps 的链接,是这样吗?如果是这样怎么保证这个-td 参数值是否可用呢?会不会已经在 cgn nat 上被占用了。
|
19
delpo OP @hello365 -td 是你 tcp 包的目的端口,也就是你 vps 上的端口,你说的那个是 nat 防火墙上的 external port,这个是 nat 防火墙自动分配的
|
20
mxuan 2022-08-11 09:25:23 +08:00
cgnat 是 nat3 ,用 stun 试了下,没法提供对应端口。心酸。。
|
21
q197 2022-08-11 20:55:31 +08:00 via Android
@ChangeTheWorld 应该是 tracker 程序的问题,正常 nat1 无公网 ip 完全不影响 bt 互联
|
22
delpo OP @q197 其实即便 tacker 记录的是 external port ,两个 nat1 的 peers 也很难连上,主要就是因为 nat 的映射时间太短,而 tracker 汇报的间隔很长,所以只有两个 peers 同时在 nat 映射打开的时候连接对方才行,这个概率真的很随缘。不过如果真是这种情况,只需要一个 peer 主动一直打开映射就一定能被其他 peer 连上,可以说能简化很多。
|
23
delpo OP @q197 更进一步研究抓包发现,在 TCP 协议下,无论是连接 peers 还是连接 tracker ,使用的本地端口都是 socket 随机指定的,而不是设置里的监听端口,在这种情况下 nat 外的端口也是不固定的,所以两个 peers 自动打洞成功的概率可以忽略不计。
但是作为对比,UDP 协议下,无论是μtp 还是 udp tracker ,使用的本地端口都是设置里的监听端口,这种情况下才有可能实现上一楼中说的情况,但是这要求必须是μtp + udp tracker ,实际使用中 udp tracker 其实是很少的。 但是如果下载的不是私有种子,那么就和之前说的一样,可以使用 DHT 或者 PEX 协议接受μtp 入站连接,[BEP_0055]( https://www.bittorrent.org/beps/bep_0055.html)也规定了一部分打洞扩展。 以上实验皆基于 qbittorrent |
24
lanlandezei 2022-08-13 21:08:25 +08:00
大佬有没有能直接运行的二进制执行文件,DOCKR 感觉比较麻烦
|
25
delpo OP |
26
lanlandezei 2022-08-15 08:27:13 +08:00
我应该已经执行到最后一步了,PT 站个人信息那里,BT 客户端有显示 trav 执行的端口了。现在就是差最后一步 DNAT 不知道怎么写。(用 iptables 的 DNAT 模块进行本地端口转发,从而将 extra port 的入站流量全部转发到 local port 上)。
我的运行环境 移动宽带 NAT1 debian11 apt 直接安装的 qbittorrent mitmdump -p 8888 -s http-modify-query-string.py trav -i 8 -l 12345 qb 连接 mitmdump 的代理。 |
27
delpo OP @lanlandezei 程序里有自动创建 iptables 规则的,你可以在 nat 表里找到
还有,interval 不用设置太高,半个小时更新一次都没问题,毕竟用的公共服务器 |
28
subing 2022-08-15 18:09:51 +08:00
老哥要是长期玩 pt 还是建议有公网方便,电信 /联通总有一家会给的
|
29
thegodofoxeris 2023-02-04 01:41:18 +08:00 via Android
老哥,你这个对我来说十分复杂,我完全看不懂,但我以其他的方式获取了公网端口,这是我写的教程
https://www.cometbbs.com/t/%E5%9F%BA%E4%BA%8Estun%E7%A9%BF%E9%80%8F%E5%B7%A5%E5%85%B7lucky%EF%BC%8C%E4%BD%BFbt%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%BB%BF%E7%81%AF%E3%80%81%E5%BC%80%E6%94%BEtcp%E7%AB%AF%E5%8F%A3%E7%9A%84%E5%8A%9E%E6%B3%95%EF%BC%88%E8%BF%9B%E5%8C%96%E7%89%88%EF%BC%89/82042 |
30
james19820515 171 天前
nat3 才是全锥吧?
|
31
delpo OP |