Duke Yin's Technology database

使用Gost桥接外部服务

最近遇到一个问题:

  • 性能更好
  • 只有 IPV6公网
  • 跑了一个服务,通过1234/udp端口对外提供服务
  • 网络较为稳定
  • 假设域名为 domainv6.com
  • 性能差
  • 有IPV4公网,有解析IPV6域名的能力
  • 因为性能瓶颈,跑不动服务器A的服务。
  • 网络较为稳定
  • 假设域名为 domainv4.com

服务器A服务器B位于不同地理位置。

虽然现在IPV6已经比较普遍了,但是大部分的家庭宽带,企业内部宽带都默认关闭了解析IPV6的能力,直接将服务器A的纯IPV6域名domainv6.com提供给客户,将导致大部分客户因为IPV6解析能力无法连接服务。

不论是给服务器A购买IPV4公网,还是给服务器B增加CPU内存,成本都较高。

考虑解决

内网穿透

最初想的是在服务器A部署一个穿透工具,然后客户端就相当于跟服务器A在局域网了,也就不存在IPV6连不上的问题。

这种类似的东西有很多,例如Zerotie,frp

但是!让客户安装个额外的客户端,还每次用都得去连接VPN,穿透的效果还时好时坏,不稳定,这是不能忍的。

所以很快,这种方案Pass了。

跳板服务器转发

于是我在想,是否有一种技术,可以实现客户端访问服务器B的IPV4,服务器B收到访问后自主去访问服务器A的对应服务,并发送结果给客户端:

客户端 <-> 服务器B <-> 服务器A

这样一来客户端只需要记住服务器B的IPV4域名domainv4.com,基本是个宽带都能连上,而且服务器B充当了桥梁,不会暴露真实提供服务的服务器A,安全性也更好。

可以预见唯二的缺点是:

  • 多了一个故障节点,故障率会更大
  • 强依赖服务器B服务器A的网络状况

挑选方案

现成的有好几种成品可以实现“协议桥接”:

  • socat
  • haproxy
  • gost

socat

在桥梁服务器B上执行:

socat -T60 UDP4-LISTEN:1234,fork,reuseaddr UDP6:[domainv6.com]:1234

优点是配置简单,支持IPV6。

缺点是高并发性能一般。

haproxy

global
    maxconn 10000

defaults
    mode udp
    timeout connect 5s
    timeout client  60s
    timeout server  60s

frontend udp_in
    bind *:1234
    default_backend udp_out

backend udp_out
    server srv1 domainv6.com:1234

优点是性能好,可以负载均衡。

缺点是配置复杂。

gost

gost 支持 UDP 转发,而且对 IPv6 友好。

gost -L udp://:1234/[domainv6.com]:1234

优点:支持UDP / TCP / QUIC; 性能优于socat;部署较为简单

缺点:几乎没有

确定方案

gost方案最优,但是直接在服务器B跑系统级服务有点不好维护,所以最终确定是跑一个Gost的Docker容器负责服务转发,资源可控,且方便开关。

于是在服务器B配置Docker compose如下:

version: '3.8'
services:
  udp-1234-bridge:
    image: ginuerzh/gost:latest
    container_name: udp-1234-bridge
    network_mode: host
    restart: unless-stopped
    command: >
      -L=udp://:1234/[domainv6.com]:1234
      -L=tcp://:2345/[domainv6.com]:2345 #如果有更多转发需求,新增-L参数行
      # 输出日志,产品阶段关闭
      #-D

Docker跑起来之前,应当调整服务器A服务器B的防火墙,保证端口udp/1234是对外开放的。

总结:

gost很好,套了Docker容器的gost更可控,并且gost服务本身只是网络转发,对服务器B性能几乎不会有任何影响,使用gost节省了硬件和网络成本,如果是简单的服务、不需要身份验证、即时性要求不是毫秒级,这种方案可以说很完美。

值得注意的是,我们目前所实现的协议桥接还是具有一些风险,这些风险无论用上面哪个工具都会有,与gost无关:

  • 对于实时性要求高的服务不适用,节点多会有额外的延迟和抖动
  • UDP协议没有握手,没有认证,知道服务器B的地址就能连上,安全性较低
  • 服务器A看到的所有连接都是来自服务器B,难溯源,难根据IP设置黑白名单
  • 抗攻击能力弱,如果有人flood攻击,服务器A的服务会爆掉,两台服务器的带宽打满可能会连服务器B也爆掉
  • 多节点故障率比单节点高
  • 通信速度依赖两台服务器之间的带宽和连通情况。

注:本文的所有域名、端口和IP都不是真实的。

# #

发布评论

评论

标注 * 的为必填项。