基于主机名的 Nginx TCP 转发问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
pydiff
V2EX    程序员

基于主机名的 Nginx TCP 转发问题

  •  
  •   pydiff 2021-02-20 17:50:19 +08:00 4404 次点击
    这是一个创建于 1695 天前的主题,其中的信息可能已经有所发展或是发生改变。

    nginx 可以通过不同的主机名相同端口号来区分不同的 http 服务,今天想利用 nginx 来转发 tcp(非 http)的端口,找遍了百度都是引用了 sf 上的一个帖子的设置方法:地址:https://stackoverflow.com/questions/34741571/nginx-tcp-forwarding-based-on-hostname

    stream { map $ssl_preread_server_name $name { vpn1.app.com vpn1_backend; vpn2.app.com vpn2_backend; https.app.com https_backend; default https_default_backend; } upstream vpn1_backend { server 10.0.0.3:443; } upstream vpn2_backend { server 10.0.0.4:443; } upstream https_backend { server 10.0.0.5:443; } upstream https_default_backend { server 127.0.0.1:443; } server { listen 10.0.0.1:443; proxy_pass $name; ssl_preread on; } } 

    然而我对着设置了却报这个错,

    2021/02/20 09:31:32 [error] 23#23: *22 connect() failed (111: Connection refused) while connecting to upstream, client: 1.1.1.1, server: 192.168.0.5:9443, upstream: "127.0.0.1:9443", bytes from/to client:0/0, bytes from/to upstream:0/0 

    实在找不到解决方法了想过来问问各位大佬

    现在我已经用 8443 端口在跑着 web 服务了,还想通过改下主机名来代理不同的服务,如 mysql.test.com 代理 mysql 的 3306,redis.test.com 代理 redis 的 6379, 另外如果将上面的 upstream 配置中 443 改成 8443 则报错

    nginx: [emerg] bind() to 192.168.0.5:8443 failed (98: Address already in use) 

    想懂的大佬指点下

    20 条回复    2021-02-22 09:39:59 +08:00
    fucUup
        1
    fucUup  
       2021-02-20 18:00:38 +08:00
    大哥你标题写错了吧, tcp 转发应该是 https

    tcp 哪有域名的呀大哥

    全文都在讲 https sni 嗅探
    villivateur
        2
    villivateur  
       2021-02-20 18:03:45 +08:00 via Android
    域名是 http 里面的概念,tcp 不存在域名一说
    ysc3839
        3
    ysc3839  
       2021-02-20 18:03:51 +08:00
    你贴的这段配置前面有一段话

    This allows Nginx to read the TLS Client Hello and decide based on the SNI extension which backend to use.
    pydiff
        4
    pydiff  
    OP
       2021-02-20 18:04:58 +08:00
    @fucUup 可能我的表达有误,我的需求就是 mysql.test.com:8443 代理 mysql 的 3306,redis.test.com:8443 代理 redis 的 6379,能搞定这个就行了
    FingerLiu
        5
    FingerLiu  
       2021-02-20 18:09:42 +08:00
    你这个只能按分配不同的端口来区分,不能通过域名,为 tcp 连接没有域名的概念
    delpo
        6
    delpo  
       2021-02-20 18:21:21 +08:00 via Android   1
    同楼上所说,stream 转发的是 tcp 链接,所以你的需求是不能通过这个方法完成的。
    但是如果你开启了 tls,就可以通过 pread server name 来进行区分,这个指令只能区分 client hello 的域名
    noe132
        7
    noe132  
       2021-02-20 18:42:02 +08:00 via Android
    tcp 没有域名。你连接前域名已经被 dns 解析成 ip 后才建立的 tcp 链接。tcp 是根据 ip+端口区分链接的。
    delpo
        8
    delpo  
       2021-02-20 18:42:28 +08:00
    pread --> preread
    Qetesh
        9
    Qetesh  
       2021-02-20 18:47:22 +08:00 via iPhone
    haproxy 轻松四层负载
    snoopyxdy1
        10
    snoopyxdy1  
       2021-02-20 18:54:30 +08:00
    @pydiff 也可以实现,配置 2 台 nginx 服务器,然后将域名 mysql.test.comredis.test.com 分别指向这 2 台 nginx 服务器的 ip 地址即可
    iseki
        11
    iseki  
       2021-02-20 18:55:04 +08:00
    做不到的吧,这个功能是 TLS SNI proxy,得是带有 SNI 的 TLS 链接才起作用
    pydiff
        12
    pydiff  
    OP
       2021-02-20 20:11:54 +08:00
    @FingerLiu
    @delpo
    @noe132 好的,学习了,多谢大佬指点
    pydiff
        13
    pydiff  
    OP
       2021-02-20 20:12:16 +08:00
    @Qetesh 没用过,改天有空时试试
    also24
        14
    also24  
       2021-02-20 20:18:46 +08:00 via Android
    原理上的错误前面很多人说了,不多赘述。

    你这个原始需求也有点奇怪啊,为什么要把 mysql 和 redis 跑在 80 端口呢?

    直接:
    mysql.test.com:3306
    also24
        15
    also24  
       2021-02-20 20:20:27 +08:00 via Android
    直接:

    mysql 点 test 点 com:3306
    redis 点 test 点 com:6379

    这样使用不好么

    (前面没打完不小心按到了回复)
    pydiff
        16
    pydiff  
    OP
       2021-02-20 20:21:30 +08:00
    @also24 因为不想映射太多端口号出来呀,想着用多个主机名来区分,还容易记
    also24
        17
    also24  
       2021-02-20 20:27:15 +08:00
    @pydiff #16
    emmmm 反正前面已经很多人科普了,你的思路在原理上是不可行的,还是按常规操作来吧。
    (其实到也不是完全不可行,自己做一套解析协议的分发,也许可以做到)
    pydiff
        18
    pydiff  
    OP
       2021-02-20 20:31:51 +08:00
    @also24 #17
    这个还是算了,菜鸡一个,哪会这种东西
    xinyifly
        19
    xinyifly  
       2021-02-21 18:22:08 +08:00
    我也作过这个尝试,如果我没理解错的话,我再详细解释一下 @noe132 的答案:

    1. mysql 客户端收到 mysql.test.com:8443 的连接配置
    2. mysql 通过操作系统的 DNS 功能查询到 mysql.test.com 的 ip 为 69.172.200.109
    3. mysql 向 69.172.200.109:8443 发起连接

    对于 redis 也是一样的。

    所以你可以看到,对于提供 TCP 服务(非 HTTP )的服务器,是收不到域名(或主机名)信息的。

    总结:对于目前大部分基于 TCP 而非 HTTP 的服务而言,想通过域名或主机名区分流量是不可能的,因为客户端并未发送域名(或主机名)信息。

    其它思路:Linux 内核提供了多个服务复用同一个端口的功能,也有通过嗅探连接类型作转发的代理服务(比如 sslh ),我没有尝试过,楼主有需要可以参考一下。
    pydiff
        20
    pydiff  
    OP
       2021-02-22 09:39:59 +08:00
    @xinyifly #19
    好的,谢谢解答哈
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1037 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 33ms UTC 18:04 PVG 02:04 LAX 11:04 JFK 14:04
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86