Nginx支持SNI证书,已经ssl_server_name的使用

news2024/10/5 18:29:48

整理了一些网上的资料,这里记录一下,供大家参考

什么是SNI?

    传统的应用场景中,一台服务器对应一个IP地址,一个域名,使用一张包含了域名信息的证书。随着云计算技术的普及,在云中的虚拟机有了一个IP,对应多个域名,使用多张证书的应用场景,SNI技术应运而生。SNI(Server Name Indication),即实现了一个服务器使用多个域名证书的TLS扩展,支持用户配置多个域名证书。

SNI请求特点

    HTTP请求的Host字段在请求的Header中。发起HTTPS请求时,在TLS握手阶段,还无法进行HTTP数据的解析,此时TLS协议的Client Hello字段新增了一个Server Name字段,请求的客户端可以通过这个字段填充请求的Host信息,而服务端在TLS握手阶段就可以选择请求处理的证书,实现SNI的功能。

 各种工具对SNI的支持各种工具对SNI的支持icon-default.png?t=N7T8https://en.wikipedia.org/wiki/Server_Name_Indication

(1)主流的浏览器  可以理解为客户端工具

(2)curl和wget之类的命令行工具  可以理解为客户端工具

curl和nginx关于SNI一些细节

 已知的问题:curl和jdk'版本过低(客户端不支持SNI)','导致'ssl握手的'SNI'问题

 (3)库和编程语言 可以理解为客户端工具

 (4)web服务器 可以理解为服务端

  • 默认SNI是'开启的'

Nginx支持的配置

    Nginx支持SNI,允许在同一个TLS服务端口下,配置不同的域名,用户通过请求不同的证书域名,可返回相应的upstream响应结果。

    本示例配置了一个证书域名为“lwl.test.com”的单向认证代理服务,一个证书域名为“lwl.default.com”的双向认证代理服务,使用相同的443端口,具体配置如下:

# Settings for a TLS enabled server.
    upstream lwl.test.com {
        server 192.168.58.196;
    }

    upstream default {
        server 192.168.58.195;
    }

  server {
        listen       443 ssl;
        listen       [::]:443 ssl;
        server_name  lwl.test.com;
        root         /usr/share/nginx/html;

        ssl_certificate /etc/nginx/ssl_sni/server/lwl.test.com/server.crt;
        ssl_certificate_key /etc/nginx/ssl_sni/server/lwl.test.com/server.key;

        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Cookie $http_cookie;
            proxy_pass http://lwl.test.com;
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

   server {
        listen       443 ssl;
        listen       [::]:443 ssl;
        server_name  lwl.default.com;
        root         /usr/share/nginx/html;

        ssl_certificate /etc/nginx/ssl_sni/server/lwl.default.com/server.crt;
        ssl_certificate_key /etc/nginx/ssl_sni/server/lwl.default.com/server.key;
        ssl_client_certificate /etc/nginx/ssl_sni/private/ca.crt;
        ssl_verify_client on;

        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Cookie $http_cookie;
            proxy_pass http://default;
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

单向认证测试

    基于以上配置,使用域名为“lwl.test.com”的证书进行单向认证的HTTPS访问,请求如下:
# curl https://lwl.test.com:443 --cacert /etc/nginx/ssl_sni/private/ca.crt

返回的响应为:


同时对当前的HTTPS请求进行抓包,可以看到,请求TLS握手阶段Client Hello请求中,包含了Server Name为lwl.test.com的字段:

双向认证测试

    基于以上配置,使用域名为“lwl.default.com”的证书进行双向认证的HTTPS访问,请求如下:   

# curl --cert /etc/nginx/ssl_sni/users/client.crt:123456 --key /etc/nginx/ssl_sni/users/client.key 'https://lwl.default.com:443' --cacert /etc/nginx/ssl_sni/private/ca.crt

返回的响应为:

同时对当前的HTTPS请求进行抓包,可以看到,请求TLS握手阶段Client Hello请求中,包含了Server Name为lwl.default.com的字段:  

至此验证了Nginx可同时支持多个TLS证书的功能。

多证书配置

    为支持多个SNI证书,一种Nginx配置文件形式为,每个证书配置单独一个server段,此处以两个单向认证证书,一个双向认证证书为例,配置如下:

# Settings for a TLS enabled server.
    upstream lwl.test.com {
        server 192.168.58.196;
    }

    upstream lwl.test1.com {
        server 192.168.58.194:8081;
    }

    upstream default {
        server 192.168.58.195;
    }

  server {
        listen       443 ssl;
        listen       [::]:443 ssl;
        server_name  lwl.test.com;
        root         /usr/share/nginx/html;

        ssl_certificate /etc/nginx/ssl_sni/server/lwl.test.com/server.crt;
        ssl_certificate_key /etc/nginx/ssl_sni/server/lwl.test.com/server.key;

        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Cookie $http_cookie;
            proxy_pass http://lwl.test.com;
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

   server {
        listen       443 ssl;
        listen       [::]:443 ssl;
        server_name  lwl.test1.com;
        root         /usr/share/nginx/html;

        ssl_certificate /etc/nginx/ssl_sni/server/lwl.test1.com/server.crt;
        ssl_certificate_key /etc/nginx/ssl_sni/server/lwl.test1.com/server.key;

        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Cookie $http_cookie;
            proxy_pass http://lwl.test1.com;
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

   server {
        listen       443 ssl;
        listen       [::]:443 ssl;
        server_name  lwl.default.com;
        root         /usr/share/nginx/html;

        ssl_certificate /etc/nginx/ssl_sni/server/lwl.default.com/server.crt;
        ssl_certificate_key /etc/nginx/ssl_sni/server/lwl.default.com/server.key;
        ssl_client_certificate /etc/nginx/ssl_sni/private/ca.crt;
        ssl_verify_client on;

        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Cookie $http_cookie;
            proxy_pass http://default;
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
可以看到,随着加载证书个数的增加,Nginx配置篇幅增长较大,不利于配置维护。

优化的配置方式

    启用了sni的nginx,如下变量会被赋值

$ssl_server_name

默认SNI是'开启的'

检查'nginx server端'是否支持SNI扩展协议:'nginx -V'

      在1.7.0版本开始,Nginx支持通过$ssl_server_name 变量获取TLS中的Server Name,我们可以据此结合map映射指令,提升配置的重用度,一种优化后的配置方式如下:

例子1:

# Settings for a TLS enabled server.
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout  10m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    map $ssl_server_name $ssl_string {
        lwl.test.com lwl.test.com;
        lwl.test1.com lwl.test1.com;
        default lwl.default.com;
    }

    upstream lwl.test.com {
        server 192.168.58.196;
    }

    upstream lwl.test1.com {
        server 192.168.58.194:8081;
    }

    upstream lwl.default.com {
        server 192.168.58.195;
    }

  server {
        listen       443 ssl;
        listen       [::]:443 ssl;
        server_name  $ssl_string;
        root         /usr/share/nginx/html;

        ssl_certificate /etc/nginx/ssl_sni/server/$ssl_string/server.crt;
        ssl_certificate_key /etc/nginx/ssl_sni/server/$ssl_string/server.key;

        include /etc/nginx/default.d/*.conf;

        location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Cookie $http_cookie;
            proxy_pass http://$ssl_string;
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

例子2:

stream {
       upstream test {
               server 127.0.0.1:50001;
       }

       map $ssl_server_name $sni_string {
               test1.www.local test1;
               test2.www.local test2;
               test3.www.local test3;
               default test1;
       }

       map $ssl_server_name $sni_string445 {
               test1.www.local test4451;
               test2.www.local test4452;
               test3.www.local test4453;
               default test4451;
       }


       server {
               listen 444 ssl;
               ssl_certificate /data/sni/sni_${sni_string}.cer;
               ssl_certificate_key /data/sni/sni_${sni_string}.key;
               proxy_pass test;
       }
       server {
               listen 445 ssl;
               ssl_certificate /data/sni445/sni_${sni_string445}.cer;
               ssl_certificate_key /data/sni445/sni_${sni_string445}.key;
               proxy_pass test;
       }

}

注意,如果希望map命令支持host的最长匹配与正则,需要再添加hostnames关键字。

Module ngx_http_map_module

map命令的本质,可以理解为通过旧的变量定义出了一个新的变量。

 模拟tcp客户端的方法:

openssl s_client -connect t9:5000 -CAfile ~/Keys/https/root/root.cer -servername test2.www.local

[openssl][nginx] 使用openssl模拟ssl/tls客户端测试nginx stream

模拟http客户端的方法:

curl --cacert ~/Keys/https/root/root.cer -vvvv  https://test1.tls.local/
curl --cacert ~/Keys/https/root/root.cer -vvvv  https://test2.tls.local/
curl --cacert ~/Keys/https/root/root.cer -vvvv  https://test3.tls.local/
curl --cacert ~/Keys/https/root/root.cer -vvvv  https://test3.www.local/

结束语

    本文通过结合Nginx的 $ssl_server_name 变量与map指令,提供了一种支持多个SNI证书配置的实现方式,提高了配置维护的重用度。


参考

https://www.nginx.org.cn/article/detail/12416
https://www.cnblogs.com/hugetong/p/11727275.htmlhttps://blog.csdn.net/wzj_110/article/details/110149984

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1069531.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自定义无边框窗口

效果: 可拖动拉伸 ui:设计如下 样式表:在ui CustomDialog 里设置的 #widget_title{background: #E6F1EB;border-top-left-radius: 20px;border-top-right-radius: 20px;}#widget_client{background-color: rgb(255, 255, 255);border-bottom…

游乐园票务小程序商城的作用是什么

游乐园是众多儿童喜欢的场所,尤其大城市,场所多且规模大,成年人也会前往,对园方来说自然是好的,然而在实际经营中,也会面临一些痛点。 通过【雨科】平台制作游乐园商城,电脑手机端小程序端打造品…

小说推文和短剧推广的收益模式

先说授权方式,可以使用”巨量推文“进行授权 申请授权后怎么获取收益呢 小说推文分为cpa拉新和cps推广的形式 cpa拉新的价格大概未4-10多块钱一个固定价格,cps则按充值比例进行分成,cps的充值分成比例大概60%-90%左右 短剧推广也是一样分…

低功耗对于IOT来说是必备技术吗?

万物互联的时代,现代人已普遍接受电视、音箱等电器设备具备智能化能力,也是在这个趋势下,我们身边越来越多的 iot 设备联网和交互成为刚需。 但 iot 设备也面临到一些非常显著的痛点,例如iot设备的内存、处理器等核心元件无法与手…

【单元测试】如何使用 JUnit5 框架?

JUnit5 单元测试框架使用教程 一、Junit5 是什么? Junit5是一个用于在Java平台上进行单元测试的框架。JUnit 5 框架主要由三部分组成:JUnit Platform、JUnit Jupiter 和 JUnit Vintage。 JUnit Platform:定义了测试引擎的 API,是…

python代码封装二进制文件并使用C#调用方案

思路 首先使用Cython库将python代码生成二进制文件pyd,然后使用C#中的pythonnet的Nuget包来进行调用,python代码中可以使用第三方类库。 Cython使用 Cython的安装 在命令行中使用如下语句即可安装Cython pip install cythonpyd文件格式 Cython用于…

服务器中勒索病毒怎么解决?勒索病毒解密,数据恢复

服务器中勒索病毒是一件低频、高概率的事情。而且一旦用户的服务器中招以后,想要处理无论是经济成本还是时间成本都非常的高。也会对企业的生产经营造成很大的影响。所以绝大多数企业主都很关心服务器中勒索病毒后怎么解决。针对这个问题,云天数据恢复中…

ArcGIS API for JavaScript部署开发

官方快速上手教程:https://developers.arcgis.com/javascript/latest/ 官方 API 参考文档:https://developers.arcgis.com/javascript/latest/api-reference 文章目录 0.前言1.引入ArcGIS API for JavaScript部署开发1.1在线引入(via CDN&…

任务工单发送失败重试方案设计

需求背景: 该系统为一个工单系统,其中任务工单为该系统中的一个模块;任务工单它是需要周期性调度的一种任务类型;可以按照用户配置的时间周期定时性触发的。由于任务需要发送到对应的工作人员上,所以这里需要先对员工进…

学习Origin

最近,在学习Origin软件,网上资源还是很多的。我简单地记录了Origin的一些知识点,来督促自己的学习。 了解一下Origin的作用。 Origin入门教程(一):一文学会Origin (sousepad.com) 该文讲述了Origin的一些基…

从城市吉祥物进化到虚拟人IP需要哪些步骤?

在2023年成都全国科普日主场活动中,推出了全国首个科普数字形象大使“科普熊猫”,科普熊猫作为成都科普吉祥物,是如何进化为虚拟人IP,通过动作捕捉、AR等技术,活灵活现地出现在大众眼前的? 以广州虚拟动力虚…

性能测试工具概念指的是什么

性能测试工具是一类用于模拟多种负载情况下应用程序行为的软件。它们可用于测量应用程序的响应时间、吞吐量、资源利用率和稳定性。本文将介绍性能测试工具常见几种类型有哪些! 性能测试工具通常分为以下几种类型: 1、负载测试工具: 这些工具用于模拟多个…

SQL多表设计--一对多(外键)

-- 完成部门和员工的-- 选择当前db03 这个数据库use db03;-- 查看当前选中的数据库select database();-- 创建员工表create table tb_emp (id int unsigned primary key auto_increment comment ID,username varchar(20) not null unique comment 用户名,password varchar(32)…

【网路安全 --- pikachu靶场安装】超详细的pikachu靶场安装教程(提供靶场代码及工具)

一,资源下载 所用到的工具是: VMware16.0 虚拟机 windows server 2003 phpstudy 2018 pikachu 靶场代码 notepadd 文本编辑器 360zip VMware 虚拟机 参照以下博客安装,如果已安装则忽略 【网络安全 --- 工具安装】VMware 16.0 详细安装过…

滚雪球学Java(42):探索对象的奥秘:解析Java中的Object类

🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!&#xf…

如何编写性能测试用例?

前言 写测试用例,是测试绕不开的工作内容,不管是功能、自动化,还是性能。先来回顾一下功能测试用例主要包含的要素:测试用例编号、测试标题、所属模块、测试需求项编号、案例状态、预置条件、优先级、测试输入、操作步骤、预期输…

智慧茶园:茶厂茶园监管可视化视频管理系统解决方案

一、方案背景 我国是茶叶生产大国,茶叶销量全世界第一。随着经济社会的发展和人民生活水平的提高,对健康、天然的茶叶产品的消费需求量也在逐步提高。茶叶的种植、生产和制作过程工序复杂,伴随着人力成本的上升,传统茶厂的运营及…

Scala第十九章节

Scala第十九章节 scala总目录 文档资料下载 章节目标 了解Actor的相关概述掌握Actor发送和接收消息掌握WordCount案例 1. Actor介绍 Scala中的Actor并发编程模型可以用来开发比Java线程效率更高的并发程序。我们学习Scala Actor的目的主要是为后续学习Akka做准备。 1.1 Ja…

递归和分治算法(2)--合并排序和快速排序

目录 一、合并排序相关题 1、合并排序 2、逆序对 二、快速排序相关题 1、快速排序 目录 一、合并排序相关题 1、合并排序 2、逆序对 二、快速排序相关题 1、快速排序 2、中位数选取 三、循环赛日程表 一、合并排序相关题 1、合并排序 合并排序的原理:…

一文读懂|zRAM 内存压缩机制

内存是计算机系统最重要的资源之一,当操作系统内存不足时,进程申请内存将会失败,从而导致其运行异常或者崩溃。 Linux 内核提供 swap 机制来解决内存不足的情况,其原理是: 当系统内存不足时,内核会将进程不…