写点什么

nginx 中同一端口不同 tls 版本与加密套件

  • 2025-12-04
    北京
  • 本文字数:1522 字

    阅读完需:约 5 分钟

本文分享自天翼云开发者社区《nginx中同一端口不同tls版本与加密套件》.作者:z****n


1.问题描述需要在 nginx 中使用 2 个域名同时监听 443 端口,域名 a 只允许使用 tls1.2,域名 b 允许 tls1.2,tls1.3。 实际运行发现原生 nginx 无法实现


nginx.conf 配置如下

worker_processes  1;error_log  logs/error.log  debug;events {    worker_connections  1024;}
http { include mime.types; default_type application/octet-stream; server { listen 443 ssl; server_name www.a.com; ssl_protocols TLSv1.2; ssl_certificate ssl/a.crt; ssl_certificate_key ssl/a.key; location / { return 200 ok; }}
server { listen 443 ssl; server_name www.b.com; ssl_protocols TLSv1.2 TLSv1.3; ssl_certificate ssl/b.crt; ssl_certificate_key ssl/b.key; location / { return 200 ok; } }}
复制代码


1.使用 tls1.2 连接 www.a.com 可以实现 openssl s_client -connect 127.0.0.1:443 -servername www.a.com -tls1_2


2.使用 tls1.2 连接 www.b.com 可以实现 openssl s_client -connect 127.0.0.1:443 -servername www.b.com -tls1_2


3.使用 tls1.3 连接 www.b.com 不可以实现 openssl s_client -connect 127.0.0.1:443 -servername www.b.com -tls1_3


2.原理 tls 握手原理中,在客户端发起的 client_hello 到服务端时,会告知服务端客户端支持的 tls 版本,加密套件。接着服务器响应 serve_hello 告知客户端,服务器选择的 serve_hello。所以 tls 版本在握手的 client_hello 和 serve_hello 阶段必须协商完成,


然而原生的 nginx 并没有介入 openssl 的 client_hello 的阶段,即 openssl 在握手过程中会使用 nginx 的默认 default server (默认第一个 server 块) 的 ssl_protocols 指令配置。


所以要根据不同的 sni 制定不同的 tls 版本就需要在 openssl 提供的 client_hello 阶段中根据不同的 sni 判断是否使用不同的 tls 协议版本。


3.第三方模块使用 github 上模块 https://github.com/zengjinji/ngx_http_ssl_client_hello_module


修改 nginx.conf 配置,新增 ssl_client_hello on;指令

worker_processes  1;error_log  logs/error.log  debug;events {    worker_connections  1024;}
http {include mime.types;default_type application/octet-stream;
#第三方模块新增指令ssl_client_hello on;
server { listen 443 ssl; server_name www.a.com; ssl_protocols TLSv1.2; ssl_certificate ssl/a.crt; ssl_certificate_key ssl/a.key; location / { return 200 ok; }}
server { listen 443 ssl; server_name www.b.com; ssl_protocols TLSv1.2 TLSv1.3; ssl_certificate ssl/b.crt; ssl_certificate_key ssl/b.key; location / { return 200 ok; } }}
复制代码


再次尝试用 tls1.3 连接 www.b.com 可以实现 openssl s_client -connect 127.0.0.1:443 -servername www.b.com -tls1_3



使用 tls1.2 连接 www.b.com 可以实现 openssl s_client -connect 127.0.0.1:443 -servername www.b.com -tls1_2


使用 tls1.3 连接 www.a.com 不可以实现 openssl s_client -connect 127.0.0.1:443 -servername www.a.com -tls1_3


使用 tls1.2 连接 www.a.com 可以实现 openssl s_client -connect 127.0.0.1:443 -servername www.a.com -tls1_2


此外,也可以使用 openresty 的 1.21.4.1 版本,1.21.4.1 版本增加了 ssl_client_hello_by_lua_block ,原理一样也是在 openssl 的 client_hello 阶段中根据不同的 sni 区分使用不同的协议

用户头像

还未添加个人签名 2022-02-22 加入

天翼云是中国电信倾力打造的云服务品牌,致力于成为领先的云计算服务提供商。提供云主机、CDN、云电脑、大数据及AI等全线产品和场景化解决方案。

评论

发布
暂无评论
nginx中同一端口不同tls版本与加密套件_中间件_天翼云开发者社区_InfoQ写作社区