V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
beyondstars
V2EX  ›  宽带症候群

一个有趣的 nginx module

  •  1
     
  •   beyondstars · 13 天前 · 1369 次点击

    目的

    介绍一种利用通过合理配置 nginx 实现的动态 TCP 连接重定向方式。

    在配合 DNS 的情况下,这种功能可以用于解决这些问题:1 )为一些不便显式配置代理的应用程式配置无感的透明代理; 4 )端口复用,但仅限于在 client 支持 TLS 和 SNI extension 的情况下可用。

    概述

    nginx 支持转发 TCP 连接,也就是说它可用监听一个 socket, 当有 client 向这个 socket 发起连接请求时,它向一个配置好的 destination 发起连接,并且在 client 和 destination 之间接力传递数据,充当一个中间人角色。client 虽然直接连接到 nginx 的 socket ,但效果和直连 destination 是一样的。

    例如,下列配置

    stream {
      server {
        listen 3399;
        proxy_pass 1.2.3.4:3389;
      }
    }
    

    让 nginx 把 *:3399 收到的 TCP 连接转发至 destination 1.2.3.4:3389, 这里 destination 是静态的,硬编码的,写死的。

    现在,我们希望 TCP 转发的 destination 可以动态地决定,例如从报文中嗅探出来,可不可以做到呢?

    在使用了 TLS 的条件下,理论上是可以的,因为我们知道 TLS 协议支持一个叫做 Server Name Indication (SNI) 的 extension ,类型为 ClientHello 的 TLS 握手报文中包含明文的 server name 。

    于是有了 ngx_stream_ssl_preread_module 这个 nginx module:

    stream {
      ssl_preread on;
      resolver 114.114.114.114;
      server {
        listen 443;
        proxy_pass $ssl_preread_server_name:443;
      }
    }
    

    这里的转发工作是在传输层进行的,因此不会出现客户端 ssl 证书报错的情况。

    对于非 tls 的情形,例如 http ,ngx_http_core_module 提供了一个从 HTTP 请求头嗅探出来的 $host 变量来帮助实现应用层的动态目的地重定向。

    其他事项

    省略了 DNS 配置部分,以及 client ,resolver 和转发器 (nginx) 这三个角色完全是解耦的。

    9 条回复    2024-04-22 12:38:01 +08:00
    hvsy
        1
    hvsy  
       13 天前   ❤️ 1
    感谢分享.这个有时候还是很有用的.
    beyondstars
        2
    beyondstars  
    OP
       13 天前
    额至于说端口复用,其实还有一个叫做 `$ssl_preread_alpn_protocols` 的变量,应该可以用 `map` directive 来动态确定目的端口号。
    xiaoz
        3
    xiaoz  
       13 天前 via Android   ❤️ 1
    有个 SNIPROXY 好像就是专门干这个的:https://github.com/dlundquist/sniproxy
    est
        4
    est  
       13 天前   ❤️ 1
    听说你们很喜欢玩 SNI 反代?

    /t/341913
    deorth
        5
    deorth  
       11 天前 via Android
    我还以为你写了个 module ,就这
    beyondstars
        6
    beyondstars  
    OP
       11 天前
    @deorth 我还以为你能回复啥惊世骇俗的名言警句,点进你主页一看全是些没营养的。
    beyondstars
        7
    beyondstars  
    OP
       11 天前   ❤️ 1
    @est 哦 抱歉 这个之前确实没看到,不过那个贴确实也太久远了。
    beyondstars
        8
    beyondstars  
    OP
       11 天前
    至于说什么 SNI 反代只是应用之一,个人感觉它有趣的点主要是提供了一种(可能不是新的)思路实现一种动态的连接转发,或许还可以配合其他 nginx module 在这个点做 TLS termination, 实现真正的端口复用(没有尝试过)。
    deorth
        9
    deorth  
       11 天前 via Android
    @beyondstars 不做饭的人就不能说饭店的饭不好吃了吗
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2252 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 07:38 · PVG 15:38 · LAX 00:38 · JFK 03:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.