V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
wlh233
V2EX  ›  分享创造

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

  •  
  •   wlh233 ·
    wlh320 · 2022-06-01 17:27:32 +08:00 · 1798 次点击
    这是一个创建于 688 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    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

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

    6 条回复    2022-06-10 09:07:54 +08:00
    zagfai
        1
    zagfai  
       2022-06-02 00:29:20 +08:00
    好像很厉害的样子
    saltbo
        2
    saltbo  
       2022-06-02 14:17:31 +08:00
    > 但用户 C 可能是个完全不懂技术的人,我要花时间教给 C 怎么去配置。

    你虽然解决了配置的问题,但是最终还是要 C 安装一个客户端。正常来说面向最终用户不应该压根不需要安装什么东西么?

    针对需求:想把一个端口暴露在公网,但又不想完全公开,只想开放给认证过的客户端。
    其实就是你暴露的服务自身没有鉴权能力,需要代理层帮助他完成鉴权嘛。我觉得正常来说 C 只需要:注册-> 登录 -> 使用。

    frp 的 STCP 我觉得完全没必要。因为这种工具干的事都是在应用协议里面传输 TCP ,所以完全可以在应用层加上鉴权,对接 oidc 即可。
    wlh233
        3
    wlh233  
    OP
       2022-06-02 15:52:22 +08:00
    @saltbo 感谢反馈。对于反向代理的这部分,除了鉴权以外,我还希望是做到隐蔽性,也就是公网服务器 B 上不会开放新的端口,要实现这个不在 C 处安装客户端我认为是做不到的。我感觉这也是 frp 的 STCP 模式存在的意义。现在的设计是在这个前提下进行的。
    molezznet
        4
    molezznet  
       2022-06-03 01:58:31 +08:00
    nps 的客户端傻瓜 , 可以直接发送后傻瓜运行。 所有配置都由服务端设置
    wlh233
        5
    wlh233  
    OP
       2022-06-09 23:53:49 +08:00
    @molezz765 之前没听说过,去看了一下功能还挺多的。相比之下我这个比较简陋,就只有基本功能。无配置的思路是一致的,他的无配置我看是由服务端返回客户端需要的命令行参数,我是直接放在了客户端文件里,给分发带来了一些困难,好处是对于占大多数的 windows 用户来说,只需要双击运行。
    molezznet
        6
    molezznet  
       2022-06-10 09:07:54 +08:00
    @wlh233 嗯 就是看需求和实际使用的变化情况了。 有家基于这个的商业服务,其实也是为了拉低门槛, 让客户运行后自行在 web 新建端口
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2831 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 06:12 · PVG 14:12 · LAX 23:12 · JFK 02:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.