分享一个在 NAT1 下将端口打开到公网上的方法

2022-08-09 20:38:13 +08:00
 delpo

前言

最近在机缘巧合之下入了几个 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 需要修改三个设置:

  1. Connection -> Peer connection protocol 改为 TCP 。因为 tcp 和 udp 在 nat 防火墙上映射得到的端口是不一样的,所以想同时映射 udp 的话需要再执行一次本教程。
  2. Connection -> Proxy Server 设置 http 代理为 mitmproxy 的监听端口。注意这里不要勾选 Use proxy for peer connections ,因为我们只需要中间人 tracker 请求。
  3. Advanced -> Validate HTTPS tracker certificate 取消勾选。因为解密 https 需要中间人证书,这里直接忽略校验证书,省去了配置 mitmproxy 自签名证书的步骤。这样就可以在 mitmproxy 中抓取到 tracker 请求了。

5 通过 mitmproxy 自定义脚本修改 tracker 请求中的 port 参数。官网有一个示例,将参数换为 port ,参数的值替换为第三步中得到的 external port 54321 即可。

6 大功告成

结果

我从以下三方面验证了内网的 12345 端口已经打开在了公网上:

  1. 通过另外设备(手机)或者站长工具里的tcp ping,可以 ping 通 54321 号端口。
  2. pt 站的个人信息页面里会显示客户端的 ip 以及端口,可以确认端口变为了 external port 54321 ,同时连接性为绿色。
  3. qbittorrent 中,在种子的 peers 选项卡里,可以看到很多 peers 的 Flags 一栏中有 I 标志,意味着是由其他 peers 主动连接的。

问题

  1. ipv6 。将 ipv4 的 external port 修改以后,在 pt 站的个人信息里,ipv6 的 external port 也改变了,导致 ipv6 无法接受入站连接。经过初步调研发现,似乎是 bt 标准对 ipv4&v6 双栈情况下的支持问题,即使 tracker 请求是 ipv4 发出的,qbittorrent 也会在参数上附加 ipv6=xxx 。尝试过将 v6 请求不经过 mitm 修改,也无法解决问题。其实个人也不推荐这么做,如果你的 v4 和 v6 端口不一样,可能会被管理员怀疑使用魔改客户端导致封号。一个变通的方法是,在本地使用 ip6tables 转发 ipv6 的 54321 端口到 12345 。
  2. nat 映射断开,事实上,虽然使用 watch 命令每秒发送一次数据包维持映射,但是在我实际测试中,还是有两次映射改变的情况,其中一次是因为宽带重拨,另一次我没有捕捉到原因。每次映射改变,都需要在 mitmproxy 脚本里更改 external port ,可以说是很不自动化。
  3. 这种方法只适用于通过 tracker 连接 peers 的情况,DHT 下似乎用不了?不过问题不大,毕竟是为了 pt 折腾的。

总结

可以看出,通过(很麻烦的)折腾,是可以达到将 BT 客户端的 nat1 端口映射到公网的目的的。这主要归功于 nat1 的特性,所以显然 nat234 都不能使用。这个方法应该只在 PT 的情况下比较实用,毕竟如果是打洞的话,有一台有公网 ip 的 vps 就已经可以完成打洞了。这次试验结果来看还是很成功的,发现了一种将 nat1 主机的某个端口打开到公网的方法,但是使用上述方法显然不能完成自动化,大部分操作都需要手动配置。所以如果可以开发一款 C/S 软件,自动化的打开 nat 映射,服务端抓包,获取外部端口,结果发送到客户端,可以极大地简化上述操作,并且在 nat 映射发生改变的情况下自动的更改外部端口。

5033 次点击
所在节点    宽带症候群
31 条回复
q197
2022-08-11 20:55:31 +08:00
@ChangeTheWorld 应该是 tracker 程序的问题,正常 nat1 无公网 ip 完全不影响 bt 互联
delpo
2022-08-11 22:02:04 +08:00
@q197 其实即便 tacker 记录的是 external port ,两个 nat1 的 peers 也很难连上,主要就是因为 nat 的映射时间太短,而 tracker 汇报的间隔很长,所以只有两个 peers 同时在 nat 映射打开的时候连接对方才行,这个概率真的很随缘。不过如果真是这种情况,只需要一个 peer 主动一直打开映射就一定能被其他 peer 连上,可以说能简化很多。
delpo
2022-08-12 09:51:58 +08:00
@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
lanlandezei
2022-08-13 21:08:25 +08:00
大佬有没有能直接运行的二进制执行文件,DOCKR 感觉比较麻烦
delpo
2022-08-13 22:47:03 +08:00
@lanlandezei 有需要可以自行编译

https://github.com/Alozxy/trav
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 的代理。
delpo
2022-08-15 10:37:34 +08:00
@lanlandezei 程序里有自动创建 iptables 规则的,你可以在 nat 表里找到
还有,interval 不用设置太高,半个小时更新一次都没问题,毕竟用的公共服务器
subing
2022-08-15 18:09:51 +08:00
老哥要是长期玩 pt 还是建议有公网方便,电信 /联通总有一家会给的
thegodofoxeris
2023-02-04 01:41:18 +08:00
james19820515
199 天前
nat3 才是全锥吧?
delpo
197 天前

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/871773

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX