Nginx Stream 模块实现 443 端口复用与流量分发

nginx
最近有一些需求需要普通的的 TCP/UDP 与 HTTP 流量共用 443 端口

笔者使用的 Nginx 作为 WEB 服务,其中的 stream 模块可以很好的实现这个功能

首先要检查 Nginx 是否含有 stream 模块:

1
nginx -V

输出中需要含有如下内容:

1
--with-stream=dynamic

通常来说,最近几年的 nginx 都是涵盖了 stream 模块的,在此就不加以赘述。

本文使用 nginx 进行 443 端口的复用是基于 sni 识别的,443 则被 stream 模块独占了,首先需要将原有的已监听443端口的站点的端口改为其他端口,如 8443 :

1
2
listen 8443 ssl; 
listen [::]:8443 ssl;

接着对 nginx.conf 进行编辑,通常是在 /etc/nginx/nginx.conf , 直接在 http 前加入 stream 字段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
stream {
map $ssl_preread_server_name $backend {
123.shiyunhong.com tcp__backend;
shiyunhong.com http_backend;
www.shiyunhong.com http_backend;
default http_backend;
}

# 定义 TCP 的上游服务器
upstream tcp__backend {
server 127.0.0.1:666; # 假设 TCP 正在监听 666 端口
}
# 定义 http 模块的上游服务器
upstream http_backend {
server 127.0.0.1:8443; # 你的 ssl 端口
}

# 监听 443 端口,启用 ssl_preread 来获取 SNI
server {
listen 443 so_keepalive=on;
listen [::]:443 so_keepalive=on;
ssl_preread on;
proxy_pass $backend;
}
}

http{
# 原有内容...
}

这样即可实现 123 走 TCP 服务,@ 与 www 以及默认的站点都通过 443 走 http 服务

对于强制 https 跳转与平常设置也是没有区别的,只是后续新建的站点 https 端口均不能使用 443:

1
2
3
4
location / {
proxy_redirect off;
return 301 https://yourdomain:443$request_uri;
}

参考链接:https://nginx.org/en/docs/stream/ngx_stream_core_module.html