Richard's Blog

Nginx配置一个端口同时处理多种协议

字数统计: 748阅读时长: 2 min
2020/05/09 Share

在工作中遇到一个问题,公司因为安全的要求,以前服务在公司内统一使用的http访问方式,现在对一些非我们部门内部的访问需要改为https。这个很简单,Nginx直接配置就完了。
但是过了一天有同事反应有些系统因为很久了,已经没人维护了,所以暂时没法立即修改,还是需要使用http进行访问,但此时已经有一些系统使用相同的端口改为了https访问。
现在就出现了可能同一时间访问的客户端可能会分别使用http和https访问同一端口,但是Nginx的server配置一个server端口只能配置一个协议,于是问题就变成了如何让Nginx使用多种协议监听同一个端口。

百度搜索关于nginx同一端口同时支持http与https的结果大多是教怎么用nginx将http协议的请求转为https的请求,没什么帮助。
谷歌搜到一篇文章Running SSL and Non-SSL Protocols over the Same Port with NGINX 1.15.2。文章中作者用nginx的$ssl_preread_protocol参数加上stream配置使得同一个端口同时能处理ssh和https的请求,与我的想法——同时处理http和https不太一样。然后再百度$ssl_preread_protocol这个参数的使用方法,发现全是对这篇文章的翻译,全都是说同一个端口能同时处理ssh和https的请求。

其实看以下配置可以看出一些信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
stream {
upstream ssh {
server 192.0.2.1:22;
}

upstream web {
server 192.0.2.2:443;
}

map $ssl_preread_protocol $upstream {
default ssh;
"TLSv1.2" web;
}

# SSH and SSL on the same port
server {
listen 443;

proxy_pass $upstream;
ssl_preread on;
}
}

  • map $ssl_preread_protocol $upstream这个配置中可以看到default ssh"TLSv1.2" web,这明显是个switch case语句,选择的是上面定义的upstream配置。
  • 每个upstream配置实际上是运行在本机的一个服务,监听着另一个端口。

这样看来可以猜测$ssl_preread_protocal变量实际就是当前请求443端口所使用的协议,通过map选择转发到另一个服务端口上。

那么我们其实可以在http配置里配置两个server,一个是http的配置,一个是https的配置,然后像上面这样通过$ssl_preread_protocal还根据不同的协议分发到不同的端口就能实现同一端口同时处理http/https请求了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
stream {
upstream web_http {
server 127.0.0.1:8000;
}

upstream web_https {
server 127.0.0.1:8001;
}

map $ssl_preread_protocol $upstream {
default web_http;
"TLSv1.2" web_https;
"TLSv1.3" web_https;
}

# SSH and SSL on the same port
server {
listen 8080;

proxy_pass $upstream;
ssl_preread on;
}
}

这样配置并运行后,使用http访问8080端口的请求会被转发到监听8000端口的服务上,https会被转发到8001端口的服务上,这样就实现了使用nginx在同一个端口处理不同的请求协议。

CATALOG