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 1
同楼上所说,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 ),我没有尝试过,楼主有需要可以参考一下。 |