V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
annoygaga
V2EX  ›  程序员

非 http 协议多租户服务 proxy, SNI Proxy 靠谱么?好像用的人不多

  •  1
     
  •   annoygaga · 11 天前 · 2771 次点击

    楼主有一个对外的多租户服务,用同一个域名的不同子域名对外提供多租户服务,我们假设这个服务是 redis (虽然不是 redis ,但是问题类似)

    楼主希望不同的子域名会转发到后端不同的 Pod (在 kubernetes 上)进行服务,目前看只有 SNI Proxy 这一个办法

    从原理上看 SNI Proxy 只需要类似 letencrypt 签发证书,其他的就是 TLS 握手的 SayHello 过程拿到域名进行转发,原理非常合理,但我搜了一下貌似没什么人使用这个东西,想问问这个东西靠谱么?谁在生产环境下使用了吗?

    第 1 条附言  ·  10 天前

    发这个贴的目的其实是纯粹想问问 SNI proxy 这个方案目前有哪些人上了生产方案,从原理上看蛮合理的(当然我第一次接触这个),但寻找了一圈,发现讨论有限,特来论坛看看这个方案大家有没有踩过什么坑

    50 条回复    2025-07-24 14:56:36 +08:00
    nealnote
        1
    nealnote  
       11 天前
    根据不同的子域转发到不同的 pod 和 转到相同的 pod 解析子域区分不同的 businessId 或者商户有什么优势或者更强的需求么?
    annoygaga
        2
    annoygaga  
    OP
       11 天前 via iPhone
    @nealnote 类似 redis ,服务里面拿不到域名,本身是 tcp 连过来的
    just1
        3
    just1  
       11 天前
    sni proxy 就不需要签发证书了,是 backing endpoint 来提供
    oott123
        4
    oott123  
       11 天前 via Android
    用 nginx 或者 traefik 里的类似功能就好了,sniproxy 确实没什么人生产用
    yinmin
        5
    yinmin  
       10 天前 via iPhone
    后端服务是 tls 协议,的确可以直接使用 sni proxy 。如果后端服务是 tcp ,可以用反向代理软件包裹一层 tls ,然后使用 sni proxy 分流,client 端使用 stunnel 或者 gost 还原出 tcp 。

    sni proxy 推荐使用 nginx 的 stream 模块,可以在生产环境稳定运行,也可以动态修改 nginx 配置文件然后 nginx -reload
    strp
        6
    strp  
       10 天前
    LanCache 算不算生产。。不过 SNIProxy 已经停更了,用的人不多的话也许可以试试 cloudflared 的反代,它支持路径自定义,基于 WAF 的 ACL 和 TCP 代理。
    zzh0410
        7
    zzh0410  
       10 天前 via Android
    在 k8s 里面做一个网关根据域名分发呢
    RobinFai
        8
    RobinFai  
       10 天前
    后端是 redis 这一类的 tcp 服务的话,服务本身不一定是 tls ,所以也没法用 sni 代理过去。另外对应的客户端也没有 tls 配置(部分产品支持 tls 应该不再这个讨论范围里)。

    如果定制客户端的 http CONNECT 和 proxy protocol 的封装就行了。

    不能定制客户端的话,只能用端口映射应该是没有别的办法了。
    annoygaga
        9
    annoygaga  
    OP
       10 天前
    @just1 是的,我是这么做的,证书来自 letsencrypt
    annoygaga
        10
    annoygaga  
    OP
       10 天前
    @oott123 我感觉我自己写一个也很容易,在考虑自己写,nginx 主要是每次多租户增加,动态 load 有点烦
    annoygaga
        11
    annoygaga  
    OP
       10 天前
    @oott123 不过不是很明白为什么没人用
    annoygaga
        12
    annoygaga  
    OP
       10 天前
    @yinmin 后端是 tcp ,目前准备用 letsencrypt 抱一层,nginx 这个靠谱吗?我看自己写一个貌似也不复杂
    annoygaga
        13
    annoygaga  
    OP
       10 天前
    @strp 这个没用过呢,我看着自己实现一个 sni proxy 貌似也不复杂?看上去就是解析 tls hello ,然后维持连接即可,主要是对外提供服务,用不了 cloudflare
    annoygaga
        14
    annoygaga  
    OP
       10 天前
    @zzh0410 是打算这么做的,目前的问题在于,服务是 tcp 的,拿不到域名,只有 tls 还保留的域名
    annoygaga
        15
    annoygaga  
    OP
       10 天前
    @RobinFai 我是准备抱一层 tls ,redis 也可以包一层 tls 的,通过 tls 来搞到域名做转发
    RobinFai
        16
    RobinFai  
       10 天前
    如果是支持 tls 协议的话,是可以用 sni proxy 的。建议用 envoy 去 proxy ,省心省力,静态配置和动态配置都能支持,代理连接池啥的也都有。
    RobinFai
        17
    RobinFai  
       10 天前
    看帖子提到了 letsencrypt ,应该是不想花钱签泛域名证书。 那应该是要自己维护定时任务去续签和新签发 tls 证书,然后维护 域名和后端 ip 端口的映射关系,再把对应的关系转换成代理配置下发到代理服务。
    kur0d3s
        18
    kur0d3s  
       10 天前
    mTLS ? 印象中企业版的 server 是支持的,不知道 ce 版本用 haproxy 之类的代理终结 tls ,是否可行
    annoygaga
        19
    annoygaga  
    OP
       10 天前
    @RobinFai 是的,但我看自己写一个 sni proxy 貌似也不难?有什么坑么
    annoygaga
        20
    annoygaga  
    OP
       10 天前
    @kur0d3s sni proxy 的话应该是不终结 tls 的
    Curtion
        21
    Curtion  
       10 天前
    tcp 就只能四层上考虑,要么像 Cloudflare Tunnel 这样,要求客户端装软件。要么就只能用 TLS 中的 SNI 了,但是四层根据 SNI 转发有很多方案,例如 Traefik 和 Nginx 什么的,用得人少估计这样场景就少,大多业务都是 HTTP 的
    annoygaga
        22
    annoygaga  
    OP
       10 天前
    @Curtion 我在考虑自己写一个,看上去也不难,而且还可以加一些 metrics 监控什么的,但看上去用的人少,总怕有什么坑
    realpg
        23
    realpg  
    PRO
       10 天前
    想喷两句 又不知道从何喷起

    那就放下助人情节, 尊重他人命运吧

    连协议概念都没有的都能搞架构了吗
    annoygaga
        24
    annoygaga  
    OP
       10 天前
    @realpg 你想表达的是 sni 这玩意没有协议,所以无法构成一个合理的架构,是这个意思嘛?
    那类似的需求如何处理呢?我觉得首先是得解决问题
    realpg
        25
    realpg  
    PRO
       10 天前
    @annoygaga #24
    不是 大部分通用协议里 即使他是 tls 加密的协议 也未必是传输封装
    而你不说协议 问就是 redis 类似 根本不确定可行性 就开始研究后续了
    RobinFai
        26
    RobinFai  
       10 天前
    k8s 里面玩的话 gateway api ( envoy gateway ) + cert manager 看着刚好满足需求了
    annoygaga
        27
    annoygaga  
    OP
       10 天前
    @realpg 细节确实不方便说,但和 redis 协议类似,所以其实可以按照 redis 的情况来聊具体技术方案
    annoygaga
        28
    annoygaga  
    OP
       10 天前
    @RobinFai 是的,只是看这个功能貌似也不复杂,想着要不要自己搞一个,还方便搞一些动态 load 和 metrics 之类的
    realpg
        29
    realpg  
    PRO
       10 天前
    @annoygaga #27
    不建议你去搞这个 不是不建议搞这个事 我的意思是换个人去带这个想法
    都回帖 30 多条了 所有讨论都没有一条碰到这个方案应该第一个讨论的重点上 第二个应该讨论的也没问

    都是些没有任何架构经验的人在问再答
    你也从来没有花 10 分钟 哪怕用你说的 redis 测试一下可行性
    RobinFai
        30
    RobinFai  
       10 天前
    @realpg 所以方案是什么?
    povsister
        31
    povsister  
       10 天前 via iPhone
    @realpg #23 你喷的很对,OP 脑子里是一团浆糊。
    就让他自己写吧,放下助人情节,尊重他人命运。
    Opportunity
        32
    Opportunity  
       10 天前
    要动态操作啥的可以用 caddy + caddy-l4 插件,通过 API 控制 caddy

    https://github.com/mholt/caddy-l4
    dzdh
        33
    dzdh  
       10 天前
    自己做个 ca 证书就好了。自己签发。
    annoygaga
        34
    annoygaga  
    OP
       10 天前
    @Opportunity 是的,我看大部分 caddy/nginx 都支持这个,但好奇为什么这块讨论这么少,开这个贴其实也想看看有没有人有生产经验,看看有没有问题
    annoygaga
        35
    annoygaga  
    OP
       10 天前
    @dzdh 用 letsencrypt 应该也行,取决于客户端是不是做 ca 校验
    smileawei
        36
    smileawei  
       10 天前
    如果后端是 http 服务(从你说运行在 k8s 里推断) 那么你应该用 ingress 或者 nodeport 的方式暴露你的服务端口到你的内网;
    然后使用 nginx caddy 等反向代理工具,配置 vhost 。这些反向代理工具可以做 https 的卸载,可以根据传递过来的请求里的 sni 信息匹配对应的证书,然后卸载 ssl 。转发到对应的 k8s 的服务里。我猜测 这个是你理解的 sni proxy 吧

    不过!! sniproxy 还是一个工具本身 https://github.com/dlundquist/sniproxy 用法和反向代理类似,但是也不太一样。

    还有 我不确定你想做的是不是四层的服务(类似 redis ) 开启了 tls 后,想通过识别传递过来的 tls 的 sni 信息做不同四层后端的转发。 这个似乎 nginx 的 ssl_preread 可以实现。。不过没实际配置过。
    jqknono
        37
    jqknono  
       10 天前
    赠送一个 letsencrypt 的坑.

    - 每个注册域名每周最多 50 个证书
    - 每个账户每三小时最多 300 次请求
    - 每份证书最多 100 个域名
    - 每周最多 5 张重复证书
    - 续期证书不受限制

    原链接: https://letsencrypt.org/docs/rate-limits/

    如果你坚持要用 letsencrypt, 那每周只能卖 50 个用户. 如果共享证书, 则最多可以卖 5000 个, 但不同用户间的服务会产生关联. 删服务时不能删证书, 因为别人还在用, 需要从一个证书里移除一个域名, 但这会算一次重复证书, 而一周只能重复 5 次.

    理论上简单, 涉及到细节非常让人掉头发.

    https://adguardprivate.com 就是使用 tls sni 做的转发, 我可以证明实际是可以做出来工作的.

    letsencrypt 只算一个小坑, k8s 及其组件, 以及网络问题上的坑会比较多.

    总之你的想法理论上成立, 实际上也可以做出来, 只是实施起来会有很多细节需要注意.
    annoygaga
        38
    annoygaga  
    OP
       10 天前
    @smileawei 后端不是 http ,这就是最烦的问题,就是个类似 redis 的自定义协议的 tcp 服务,所以正常情况下是拿不到域名的,我才动了 sni 的心思
    本质上我其实就像你说的,需要一个四层服务的转发,但约束条件是,ip 是固定的
    只从逻辑看貌似很合理,我其实想问问谁用过(毕竟搜到的资料貌似很少的样子)
    annoygaga
        39
    annoygaga  
    OP
       10 天前
    @jqknono 非常感谢
    是的,letsencrypt 限制蛮多的,但貌似也没什么可以选的
    k8s 那块又是其他的问题了,不过确实各种坑很多,我也在测试和调研方案,同时也不是很敢用用的人少的方案,毕竟也考虑维护成本
    RobinFai
        40
    RobinFai  
       10 天前
    "类似 redis 的自定义协议的 tcp 服务" 问题出现在这里,到底这里是 tcp 服务,还是 tls over tcp 。
    其实服务本身是用不用 tls 无所谓,主要是 client 能不能发起 tls 请求携带 sni 信息才是这套方案能不能执行的关键。
    dzdh
        41
    dzdh  
       9 天前
    @annoygaga #39 所以还是自定义 ca 是最靠谱的
    annoygaga
        42
    annoygaga  
    OP
       9 天前
    @RobinFai 对外服务,所以是 tls over tcp
    目前看只有 tls 会携带相关的域名信息
    annoygaga
        43
    annoygaga  
    OP
       9 天前
    @dzdh 主要是之前经验,有些客户端会对没信任的 ca 直接报错,这就很尴尬
    dzdh
        44
    dzdh  
       9 天前
    @annoygaga #42

    mysql 、redis 之类的服务。本身就是自定义 ca 不会验证 ca 可信的,甚至需要自己指定 ca 证书。
    https://redis.io/docs/latest/operate/oss_and_stack/management/security/encryption/
    realpg
        45
    realpg  
    PRO
       9 天前
    @RobinFai #40
    你终于说到第一个应该问的问题的一半点子上了...
    这是这么多楼第 0.5 个有价值的问题...

    OP 第一时间不去查看他的 client library 的源代码如何实现的连接
    甚至不愿意花 10 分钟用 nginx 先模拟测试一下他的客户端库到底是大致是怎么实现的
    wangmn
        46
    wangmn  
       9 天前
    我之前这么干的 *.a.com 直接解析到一固定前端 nginx 服务,后端通过不同的域来区分租户。*.a.com 就一个通配符证书。
    annoygaga
        47
    annoygaga  
    OP
       9 天前
    @dzdh 我之前的经历是一些客户端是社区贡献的,估计是类似这种版本的坑了
    annoygaga
        48
    annoygaga  
    OP
       9 天前
    @wangmn 是的,是这个方案,之后有遇到什么坑嘛?
    wangmn
        49
    wangmn  
       9 天前
    @annoygaga 不用 ng 动态加租户,直接解析通配符到前端页面。后来没遇到坑
    xjzshttps
        50
    xjzshttps  
       8 天前
    单纯讲 SNI proxy 是没什么大问题。
    理论上没什么问题,现实中我记得有不少 SNI Proxy 的反向代理,甚至以前杂牌宽带劫持 dns 解析到自己的 http 缓存服务器,为了处理 https 没私钥就是直接用的 SNI proxy 实现,那种流量下都没什么问题应该没事。

    但是问题是,你的服务到底是什么?
    如果他是 http/https 协议的,你的想法就是最常见的 http 前端负载均衡。
    但是如果不是 http/https 协议,那么你要修改客户端或者还要在客户端前面再加个程序等方式 去实现 tls 握手及加密。
    那么既然要修改客户端,直接改下客户端协议,前面再加个握手包提供域名可能更简单。
    除非你原始的协议并未实现加密,你还需要 tls 加密的支持。

    实际直接写代码测试就完事,
    tls 客户端 + SNI proxy 不考虑线上环境各种异常、超时、配置文件等,也就 10 多分钟到半小时就搞定。
    再写下测试代码,跑几天看看就完事。
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   896 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 21:11 · PVG 05:11 · LAX 14:11 · JFK 17:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.