
需求:
对外只能开放一个端口,要实现https服务,还要能通过ssh访问Linux服务器
分析:
可以使用Nginx的四层代理(stream 模块) 与 TLS 预读(ssl_preread) 功能
注意:HTTP协议无法通过stream模块的SNI识别,因为stream模块只能识别TLS握手包中的协议信息。
具体操作:
Nginx 编译时要包含以下模块才可以:
--with-stream
--with-stream_ssl_preread_module
验证命令:
/data/server/nginx/sbin/nginx -V 2>&1 | grep -o 'with-stream\|with-stream_ssl_preread_module'
#有输出即支持
参考资料:
Nginx 单端口兼容 HTTP 与 HTTPS:基于 stream 模块与 ssl_preread 的智能分流方案
准备就绪:
SSH 服务运行在 22 端口(默认)
HTTPS 服务运行在 另一个端口,例如28443
对外只开放9290端口
1、修改nginx配置文件
cp /data/server/nginx/conf/nginx.conf /data/server/nginx/conf/nginx.conf.bak
1.1在nginx主配置文件引入stream模块

mkdir -p /data/server/nginx/conf/stream #创建目录
vi /data/server/nginx/conf/nginx.conf #stream块必须在顶层,和 http 是平级的,不能嵌套在 http 内
stream{
log_format stream_log '$remote_addr [$time_local] -> $upstream_addr ($ssl_preread_protocol)'; #引入日志记录
include /data/server/nginx/conf/stream/*.conf;
}
:wq! #保存退出
1.2创建stream规则
cd /data/server/nginx/conf/stream

vi 9290.conf #规则名字自己定义
# 定义后端服务
upstream ssh_backend {
server 127.0.0.1:22;
}
upstream web_backend {
server 127.0.0.1:28443;
}
# 根据SSL协议进行流量分发
map $ssl_preread_protocol $backend_name {
default ssh_backend; # 非TLS流量(SSH)
"TLSv1.2" web_backend; # TLSv1.2流量(HTTPS)
"TLSv1.3" web_backend; # TLSv1.3流量(HTTPS)
~TLSv1 web_backend; # 其他TLS版本
}
# 复用端口服务器配置
server {
listen 9290 ; # 对外暴露的端口
listen [::]:9290 ;
proxy_pass $backend_name;
ssl_preread on; # 启用SSL预读
proxy_connect_timeout 5s;
proxy_timeout 5s;
access_log /data/server/nginx/logs/stream-access-9290.log stream_log; #日志文件
}
:wq! #保存退出
最后重启nginx服务
2、测试服务
通过9290端口可以ssh登录服务器


通过9290端口可以https访问web服务

至此,使用Nginx实现HTTPS和SSH共用同一个端口访问各自服务完成。

②190706903
③203744115
