早期的SSLv2根据经典的公钥基础设施PKI(Public Key Infrastructure)设计,它默认认为:一台服务器(或者说一个IP)只会提供一个服务,所以在SSL握手时,服务器端可以确信客户端申请的是哪张证书。

但是让人万万没有想到的是,虚拟主机大力发展起来了,这就造成了一个IP会对应多个域名的情况。解决办法有一些,例如申请泛域名证书,对所有*.yourdomain.com的域名都可以认证,但如果你还有一个yourdomain.net的域名,那就不行了。

在HTTP协议中,请求的域名作为主机头(Host)放在HTTP Header中,所以服务器端知道应该把请求引向哪个域名,但是早期的SSL做不到这一点,因为在SSL握手的过程中,根本不会有Host的信息,所以服务器端通常返回的是配置中的第一个可用证书。因而一些较老的环境,可能会产生多域名分别配好了证书,但返回的始终是同一个。

根据HTTPS的工作原理,浏览器在访问一个HTTPS站点时,先与服务器建立SSL连接,建立连接的第一步就是请求服务器的证书。而服务器在发送证书的时候,是不知道浏览器访问的是哪个域名的,所以不能根据不同域名发送不同的证书。

既然问题的原因是在SSL握手时缺少主机头信息,那么补上就是了。

SNI(Server Name Indication)是为了解决一个服务器使用多个域名和证书的SSL/TLS扩展。定义在RFC 4366。是一项用于改善SSL/TLS的技术,在SSLv3/TLSv1中被启用。它允许客户端在发起SSL握手请求时(具体说来,是客户端发出SSL请求中的ClientHello阶段),就提交请求的Host信息,使得服务器能够切换到正确的域并返回相应的证书。一句话简述它的工作原理就是,在连接到服务器建立SSL链接之前先发送要访问站点的域名(Hostname),这样服务器根据这个域名返回一个合适的证书。目前,大多数操作系统和浏览器都已经很好地支持SNI扩展,OpenSSL 0.9.8已经内置这一功能,据说新版的nginx也支持SNI。

要使用SNI,需要客户端和服务器端同时满足条件,幸好对于现代浏览器来说,大部分都支持SSLv3/TLSv1,所以都可以享受SNI带来的便利。

用代码来演示:

server {
listen 443;
server_name www.example.com;
ssl on;
ssl_certificate www.example.com.crt;
...
} server {
listen 443;
server_name www.example.org;
ssl on;
ssl_certificate www.example.org.crt;
...
}

使用上面的配置,不论浏览器请求哪个主机,都只会收到默认主机www.example.com的证书。这是由SSL协议本身的行为引起的——先建立SSL连接,再发送HTTP请求,所以nginx建立SSL连接时不知道所请求主机的名字,因此,它只会返回默认主机的证书。

最古老的也是最稳定的解决方法就是每个HTTPS主机使用不同的IP地址:

server {
listen 192.168.1.1:;
server_name www.example.com;
ssl on;
ssl_certificate www.example.com.crt;
...
} server {
listen 192.168.1.2:;
server_name www.example.org;
ssl on;
ssl_certificate www.example.org.crt;
...
}

那么,在同一个IP上,如何配置多个HTTPS主机呢?

nginx支持TLS协议的SNI扩展。不过,SNI扩展还必须有客户端的支持,另外本地的OpenSSL必须支持它。

如果启用了SSL支持,nginx便会自动识别OpenSSL并启用SNI。是否启用SNI支持,是在编译时由当时的 ssl.h 决定的(SSL_CTRL_SET_TLSEXT_HOSTNAME),如果编译时使用的OpenSSL库支持SNI,则目标系统的OpenSSL库只要支持它就可以正常使用SNI了。

nginx在默认情况下是TLS SNI support disabled。如果需要支持,编译时需要增加:

--with-http_ssl_module \
--with-openssl=./openssl-1.0.1e \
--with-openssl-opt="enable-tlsext"

但是我用的nginx/1.10.1,在编译时没有添加--with-open-opt="enable-tlsext",就可以支持SNI了,所以最新版本默认是开启的?

HTTPS-SSL/TSL与SNI的关系以及同IP多域名虚拟主机的SSL/TSL认证的更多相关文章

  1. RedHat7配置Nginx实现多域名虚拟主机的SSL/TLS认证(实现单IP以不同证书服务于不同域名)

    以RedHat7(64bit)平台为例 如果RedHat源没法用,可以使用EPEL源 # rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-rel ...

  2. 十八.搭建Nginx服务器、配置网页认证、基于域名的虚拟主机、ssl虚拟主机

    配置要求: client:192.168.4.10 proxy:192.168.4.5(eth0) 192.168.2.5(eth1) web1:192.168.2.100 web2:192.168. ...

  3. 高级运维(二):搭建Nginx服务器、用户认证、基于域名的虚拟主机、SSL虚拟主机、Nginx反向代理

    一.搭建Nginx服务器 目标: 在IP地址为192.168.4.5的主机上安装部署Nginx服务,并可以将Nginx服务器,要求编译时启用如下功能: 1> SSL加密功能 2> 设置Ng ...

  4. 阿里云万网虚拟主机安装配置Https(SSL)教程

    太多太多的用户咨询阿里云虚拟主机是否可以安装SSL数字证书?万网空间是否可以支持HTTPS协议访问网站?答案只有一个:目前阿里云虚拟主机都不支持安装SSL证书!但是,但是,可以曲线实现目标! 1.为了 ...

  5. [nginx][tls] nginx配置https与ssl/tls的sni的方法

    一 https的sni配置方法 http {       }       server {               listen 443 ssl;               server_nam ...

  6. [从零开始搭网站六]为域名申请免费SSL证书(https),并为Tomcat配置https域名所用的多SSL证书

    点击下面连接查看从零开始搭网站全系列 从零开始搭网站 由于国内的网络环境比较恶劣,运营商流量劫持的情况比较严重,一般表现为别人打开你的网站的时候会弹一些莫名其妙的广告...更过分的会跳转至别的网站. ...

  7. CentOS 7 下的LAMP实现以及基于https的虚拟主机

    系统环境:CentOS 7Apache 2.4php 5.4MariaDB 5.5 项目需求:创建3个虚拟主机,分别架设phpMyadmin,wordpress,Discuz其中phpMyadmin提 ...

  8. CentOS 6下Apache的https虚拟主机实践

    题目:1.建立httpd服务器,要求: 提供两个基于名称的虚拟主机: (a)www1.buybybuy.com,页面文件目录为/web/vhosts/www1:错误日志为/var/log/httpd/ ...

  9. apache虚拟主机配置HTTPS

    win+apache+php的环境下做虚拟主机的https. 1.https用的是443端口,确定防火墙已经开放443了.2.http.conf要加载以下模块: #这两个是用来存放SSLSession ...

随机推荐

  1. mine layer(2008 World Final C)

    类似于扫雷游戏,在一些格子中散布着一些地雷,具体的埋藏位置并不清楚,但知道每个格子及其周围八个格子的地雷总数.请问此时正中间那一行最多可能有多少地雷(题目假定所有的输入都是奇数行的)? 输入: 第一行 ...

  2. oracle 10gwindow7安装添加内容

    F:\软件\database\stage\prereq\db\refhost.xml <!--Microsoft Windows 7 .Windows 8--> <OPERATING ...

  3. Ubuntu系统下运行Eclipse出现找不到jre的问题的解决方法

    在Ubuntu的某些版本下,比如10.10,会出现以下奇怪问题: 1. 安装jdk 我下载的jdk是bin格式的,直接运行解压,得到一个文件夹. 这个文件夹作为jdk的安装目录,可以拷贝到任意目录. ...

  4. CRM客户关系管理系统修改(十四)

    修改的流程:

  5. Postfix之telnet测试

    1.# 2. 3.#若没安装telnet 需安装telnet 4.yum install telnet 5. 6.#telnet测试smtp连接postfix 7.telnet 127.0.0.1 2 ...

  6. 20145210 《Java程序设计》第09周学习总结

    教材学习内容总结 第十六章 整合数据库 •JDBC(Java DataBase Connectivity) •JDBC是用于执行SQL的解决方案 •JDBC全名Java DataBase Connec ...

  7. 30道四则运算<1>

    #include<iostream> using namespace std; #define random()(rand()%100) class shuzi //shuzi类的功能是产 ...

  8. Entityframework更新数据和插入数据

    public bool UpdateEmloyeeInfo(EmployeInfo employeInfo) { bool flg = false; try { using (UserManageDB ...

  9. C++学习笔记5:如何给变量及函数命名?

    1.遵循C++规定的变量及函数命名方法: 2.原则:简单,易于理解: 以下是一些例子,可以作为参考: //bad examples: int ccount;//Nobody knows what a ...

  10. insertAdjacentHTML

    /** * insertAdjacentHTML * 支持 insertAdjacentHTML()方法的浏览器有 IE.Firefox 8+.Safari.Opera 和 Chrome */ var ...