标签归档:https

Nginx SSL配置问题汇总

0x01 SSL配置


首先生成私钥文件

openssl genrsa -des3 -out ssl.key 1024

然后他会要求你输入这个key文件的密码。不推荐输入。因为以后要给nginx使用。每次reload nginx配置时候都要你验证这个PAM密码的。
由于生成时候必须输入密码。你可以输入后 再删掉。

mv ssl.key xxx.key
openssl rsa -in xxx.key -out ssl.key
rm xxx.key

然后根据这个key文件生成证书请求文件,CSR是一个证书签名请求,是客户的服务器软件所生成的一串文本字符。服务器在向CA注册的过程中首先要在WEB服务器上生成CSR,并把这串字符提供给证书认证中心。
openssl req -new -key ssl.key -out ssl.csr
最后根据这2个文件生成crt证书文件
openssl x509 -req -days 365 -in ssl.csr -signkey ssl.key -out ssl.crt
最后使用到的文件是key和crt文件。

然后修改Nginx配置

    server {
        listen       443 ssl;
        server_name  localhost;

        ssl_certificate      ssl.crt;
        ssl_certificate_key  ssl.key;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 SSLv3;
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
            root   html;
            index  index.html index.htm;
        }
    }

首次配置需要重启nginx,reload不生效。
这里比较重要的配置是:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2 SSLv3;
ssl_ciphers HIGH:!aNULL:!MD5;

0x02 SSL证书返回错误问题排查


运维同学反馈在IE 8和XP的环境下使用https访问chinaacc.com的时候,返回了cdeledu.com的证书。先验证下:
果然是提示证书不安全,然后查看证书,果然是访问chinaacc.com的时候,返回了cdeledu.com的证书。

经过了解,原来是服务器上配置了多个域名的SSL证书,使用低版本浏览器的时候默认返回了配置的第一个证书。
在HTTP协议中,请求的域名作为主机头(Host)放在HTTP Header中,所以服务器端知道应该把请求引向哪个域名,但是早期的SSL做不到这一点,因为在SSL握手的过程中,根本不会有Host的信息,所以服务器端通常返回的是配置中的第一个可用证书。因而一些较老的环境,可能会产生多域名分别配好了证书,但返回的始终是同一个。
直到后来出现了SNI(Server Name Indication),是一项用于改善SSL/TLS的技术,在SSLv3/TLSv1中被启用。它允许客户端在发起SSL握手请求时(具体说来,是客户端发出SSL请求中的ClientHello阶段),就提交请求的Host信息,使得服务器能够切换到正确的域并返回相应的证书。
这里我们抓一下SSL握手的包,看一下ClientHello的内容
发现使用Chrome访问的,证书正常,此时ClientHello中有SNI,如下图所示:

在XP系统使用IE浏览器的时候返回证书错误,发送的ClientHello包中没有SNI,所以会返回配置的第一个证书。
然后我在Window7下使用IE8测试,返回证书是正常的。看来跟操作系统也有关系。
需要注意SNI需要客户端和服务端同时支持才行。例如查看Nginx时候支持

[root@VM_1_112_centos sbin]# ./nginx -V
nginx version: nginx/1.6.3
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-17) (GCC)
TLS SNI support enabled

TLS SNI support enabled表示支持SNI。

0x03 Nginx多SSL配置不生效问题


今天运维同事反馈XP系统IE6不能正常访问Https站点的问题。
低版本的IE默认配置是SSLv2和SSLv3。

抓包先看了下,握手失败。

然后用nmap跑了下证书支持的加密套件:

[root@server120 ]# nmap --script ssl-enum-ciphers -p 443 chinaacc.com

Starting Nmap 6.47 ( http://nmap.org ) at 2017-09-01 10:34 CST
Nmap scan report for chinaacc.com (59.151.113.79)
Host is up (0.034s latency).
PORT    STATE SERVICE
443/tcp open  https
| ssl-enum-ciphers: 
|   SSLv3: No supported ciphers found

发现站点不支持SSLv3。
然后看了下SSL配置
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
发现没有配置SSLv3
修改配置
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 SSLv3;
然后用nmap扫描了下发现还是不行,配置没有生效。

原因是如果一个反向代理Nginx上配置了多个https域名的话,默认会走第一个的SSL配置。
例如我的配置如下:

    server {
        listen       443 ssl;
        server_name  localhost;

        ssl_certificate      xx.crt;
        ssl_certificate_key  xx.key;
        ssl_protocols TLSv1;
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;
        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
            root   html;
            index  index.html index.htm;
        }
    }

    server {
        listen       443 ssl;
        server_name  192.168.192.120;

        ssl_certificate      xx.crt;
        ssl_certificate_key  xx.key;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;
        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
            root   html;
            index  index.html index.htm;
        }
    }

第一个server配置ssl_protocols TLSv1;
第二个server配置ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
然后用nmap测试一下

[root@server144 ~]# nmap --script ssl-enum-ciphers -p 443 192.168.192.120

Starting Nmap 5.51 ( http://nmap.org ) at 2017-09-01 16:35 CST
Nmap scan report for localhost (192.168.192.120)
Host is up (0.00066s latency).
PORT    STATE SERVICE
443/tcp open  https
| ssl-enum-ciphers: 
|   TLSv1.0
|     Ciphers (13)
|       TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA
|       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
|       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
|       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA
|       TLS_RSA_WITH_AES_128_CBC_SHA
|       TLS_RSA_WITH_AES_256_CBC_SHA
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
|     Compressors (1)
|_      uncompressed
MAC Address: 52:54:00:26:BE:A2 (QEMU Virtual NIC)

Nmap done: 1 IP address (1 host up) scanned in 91.34 seconds

可以看到只支持TLSv1,走的是第一个ssl_protocols的配置。

解决方案:
修改第一个SSL配置中

ssl_protocols TLSv1 TLSv1.1 TLSv1.2 SSLv3;

HTTPS握手过程

握手过程如下:

只需要验证SSL服务器身份,不需要验证SSL客户端身份时,SSL的握手过程为:

1)SSL客户端通过Client Hello消息将它支持的加密套件(加密算法、密钥交换算法、MAC算法)发送给SSL服务器。

例如第一个Cipher Suite:
密钥交换算法为非对称加密算法RSA
数据使用对称加密算法AES_128_CBC
消息完整性使用HASH算法SHA

2)SSL服务器确定本次通信采用的SSL版本和加密套件,并通过Server Hello消息通知给SSL客户端。如果SSL服务器允许SSL客户端在以后的通信中重用本次会话,则SSL服务器会为本次会话分配会话ID,并通过Server Hello消息发送给SSL客户端。协商后确认的算法如下图所示

3)SSL服务器将数字证书通过Certificate消息发送给SSL客户端,证书里面包含了网站地址,加密公钥,以及证书的颁发机构。
4)SSL服务器发送Server Hello Done消息,通知SSL客户端版本和加密套件协商结束,开始进行密钥交换。
5)SSL客户端验证SSL服务器的证书合法后,如果不合法浏览器会提示。如果合法的话,利用证书中的公钥,SSL客户端随机生成的premaster secret(后续加密数据所需要的对称密钥),并通过Client Key Exchange消息发送给SSL服务器。
6)SSL客户端发送Change Cipher Spec消息,通知SSL服务器后续报文将采用协商好的密钥和加密套件进行加密和MAC计算。
7)SSL客户端计算已交互的握手消息(除Change Cipher Spec消息外所有已交互的消息)的Hash值,利用协商好的密钥和加密套件处理Hash值(计算并添加MAC值、加密等),并通过Finished消息发送给SSL服务器。SSL服务器利用同样的方法计算已交互的握手消息的Hash值,并与Finished消息的解密结果比较,如果二者相同,且MAC值验证成功,则证明密钥和加密套件协商成功。
8)同样地,SSL服务器发送Change Cipher Spec消息,通知SSL客户端后续报文将采用协商好的密钥和加密套件进行加密和MAC计算。
9)SSL服务器计算已交互的握手消息的Hash值,利用协商好的密钥和加密套件处理Hash值(计算并添加MAC值、加密等),并通过Finished消息发送给SSL客户端。SSL客户端利用同样的方法计算已交互的握手消息的Hash值,并与Finished消息的解密结果比较,如果二者相同,且MAC值验证成功,则证明密钥和加密套件协商成功。

TLS/SSL中使用了非对称加密,对称加密以及HASH算法。
1)非对称加密
SSL客户端收到证书后,获得公钥,然后生成随机数密钥用于后续的信息加密,SSL客户端将随机数秘钥发送给SSL服务器,SSL服务器使用私钥解密,这里用到的就是非对称加密。
2)对称加密。
SSL客户端与SSL服务端使用相同的随机数秘钥加解密,使用的对称加密。
3)HASH算法
验证信息的完整性,使用的HASH算法(MD5或者SHA)。

测试服务器支持的加密套件:
Nmap:

[root@server120 ~]# nmap --script ssl-enum-ciphers -p 443 baidu.com

Starting Nmap 6.47 ( http://nmap.org ) at 2017-08-31 16:28 CST
Nmap scan report for baidu.com (123.125.114.144)
Host is up (0.0028s latency).
Other addresses for baidu.com (not scanned): 220.181.57.217 111.13.101.208
PORT    STATE SERVICE
443/tcp open  https
| ssl-enum-ciphers: 
|   SSLv3: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - strong
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - strong
|       TLS_ECDHE_RSA_WITH_RC4_128_SHA - strong
|       TLS_RSA_WITH_AES_128_CBC_SHA - strong
|       TLS_RSA_WITH_AES_256_CBC_SHA - strong
|       TLS_RSA_WITH_RC4_128_SHA - strong
|     compressors: 
|       NULL
|   TLSv1.0: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - strong
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - strong
|       TLS_ECDHE_RSA_WITH_RC4_128_SHA - strong

另外还可以访问https://www.ssllabs.com/ssltest/analyze.html

 

 

参考文章:
https://superuser.com/questions/109213/how-do-i-list-the-ssl-tls-cipher-suites-a-particular-website-offers