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)
想懂的大佬指点下
![]() | 1 fucUup 2021-02-20 18:00:38 +08:00 大哥你标题写错了吧, tcp 转发应该是 https tcp 哪有域名的呀大哥 全文都在讲 https sni 嗅探 |
![]() | 2 villivateur 2021-02-20 18:03:45 +08:00 via Android 域名是 http 里面的概念,tcp 不存在域名一说 |
![]() | 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. |
![]() | 4 pydiff OP @fucUup 可能我的表达有误,我的需求就是 mysql.test.com:8443 代理 mysql 的 3306,redis.test.com:8443 代理 redis 的 6379,能搞定这个就行了 |
5 FingerLiu 2021-02-20 18:09:42 +08:00 你这个只能按分配不同的端口来区分,不能通过域名,为 tcp 连接没有域名的概念 |
6 delpo 2021-02-20 18:21:21 +08:00 via Android ![]() 同楼上所说,stream 转发的是 tcp 链接,所以你的需求是不能通过这个方法完成的。 但是如果你开启了 tls,就可以通过 pread server name 来进行区分,这个指令只能区分 client hello 的域名 |
![]() | 7 noe132 2021-02-20 18:42:02 +08:00 via Android tcp 没有域名。你连接前域名已经被 dns 解析成 ip 后才建立的 tcp 链接。tcp 是根据 ip+端口区分链接的。 |
8 delpo 2021-02-20 18:42:28 +08:00 pread --> preread |
![]() | 9 Qetesh 2021-02-20 18:47:22 +08:00 via iPhone haproxy 轻松四层负载 |
10 snoopyxdy1 2021-02-20 18:54:30 +08:00 |
11 iseki 2021-02-20 18:55:04 +08:00 做不到的吧,这个功能是 TLS SNI proxy,得是带有 SNI 的 TLS 链接才起作用 |
![]() | 14 also24 2021-02-20 20:18:46 +08:00 via Android |
![]() | 15 also24 2021-02-20 20:20:27 +08:00 via Android 直接: mysql 点 test 点 com:3306 redis 点 test 点 com:6379 这样使用不好么 (前面没打完不小心按到了回复) |
![]() | 17 also24 2021-02-20 20:27:15 +08:00 |
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 ),我没有尝试过,楼主有需要可以参考一下。 |