一个客户端零配置的端口转发工具

日期 : 2022-06-04 09:11:23作者 : 熊人

主要想要解决的需求是有时想把一个端口暴露在公网,但又不想完全公开,只想开放给认证过的客户端,通过转发到客户端的本地端口来访问。

frp 的 STCP 模式能解决这个问题,实现方式是端口提供者 A 、公网服务器 B 、访问者 C 三个机器都进行配置。这样做忽略了一点,就是 A 和 B 可能都是我自己,但用户 C 可能是个完全不懂技术的人,我要花时间教给 C 怎么去配置。

VPN 也可以解决这个需求,也还是会有上述配置问题。一些新型 VPN 如 tailscale 主打零配置,但前提是公网服务器由他来提供。

于是就自己写了一个简单的工具,实现了类似 ssh 隧道的端口转发功能,加密和认证用的是 noise 协议,握手采用跟 wireguard 一样提前交换密钥的形式。特色就是客户端无需配置,服务端的配置也只需要执行命令,不用复制粘贴密钥。

关于零配置我的实现非常暴力:在二进制程序的数据段预留一部分空间,当需要新的客户端时,服务端程序复制一份空白的客户端,修改二进制文件把生成的配置存进去,得到一个认证过的客户端。把这个认证过的客户端发给对方,使用时直接无参数运行。

工作原理

远端 1 <-> 客户端 <-> 服务端 <-> 远端 2
  1. 服务端绑定公网 IP 的一个端口.
  2. 远端可以是其他的公网端口(google.com:443), 本地端口(127.0.0.1:port), 或者动态端口(socks5).
  3. 客户端可以工作于以下任一模式:
    • ssh -L 模式:通过服务端访问远端 2 的静态端口。
    • ssh -D 模式:通过服务端内置的 socks5 服务访问动态的远端 2 。
    • ssh -R 模式:将远端 1(固定端口或内建 socks5)暴露给服务端并注册一个 service id 。
    • ssh -R visitor 模式:只有在此模式下具有相同 service id 的客户端才能访问暴露的端口。
  4. 客户端与服务端通过 Noise_IK_25519_ChaChaPoly_BLAKE2s 协议握手.
  5. 随后客户端与服务端之间的流量加密传输.

使用场景举例

  1. -L 模式: 把某些软件绑定在 127.0.0.1 的 socks5 服务加密共享给局域网中的某几台机器,从而无需绑定 0.0.0.0 完全在局域网公开
  2. -D 模式:内网其中一台机器有公网端口时,作为 VPN 服务的简单替代,从外部访问内网任意一台机器
  3. -R 模式:把内网机器的端口暴露至公网服务器,并且只允许同样认证过的客户端访问

想法非常简单,作者也比较菜,肯定会有潜在的安全缺陷,不推荐在生产环境使用,作者也为可能出现的安全问题负责。

开发过程没有什么技术含量,基本都是用的现成的轮子。性能方面因为就我自己在用,目前没感觉出太大问题,没详细测过性能,有可能还不如 ssh 。

源码在:https://github.com/wlh320/portguard

感兴趣的网友欢迎一起探讨和改进。

标签 :