最近在机缘巧合之下入了几个 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 映射发生改变的情况下自动的更改外部端口。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.