美文网首页
记一次nginx https的坑

记一次nginx https的坑

作者: 奶茶不要奶不要茶 | 来源:发表于2022-10-28 19:46 被阅读0次
image.png

服务器部署了nginx,nginx配置了多个不同域名的server,分别是www.example.comstatic.example.com,还有一个 server_name _ 的默认server。
然后使用curl测试https的时候,发现在访问www.example.com域名时,nginx响应的ssl证书竟然是默认server的,这显然是不正确的,之后经过抓包发现了问题。
原因是nginx默认开启了SNI,如果客户端在ssl握手阶段未携带server_name就会去找默认server,然后使用默认server的ssl证书来响应,nginx没有可以匹配成功的server,只能去找默认server了。下面通过实战还原问题现象。

服务器nginx配置共两个server:默认server(server_name _)和www.example.com

server {
        listen       443 ssl default_server;
        listen       [::]:443 ssl default_server;
        server_name  _;

        ssl_certificate "/etc/nginx/ssl/default_server_rsa.crt";
        ssl_certificate_key "/etc/nginx/ssl/default_server_rsa.key";
        ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
        ssl_ecdh_curve X25519:P-256;
        ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:HIGH:!NULL:!aNULL:!MD5:!3DES:!DES:!ADH:!RC4:!DH:!DHE:!EXP;

        location / {
        }
}

server {
        listen       443 ssl;
        listen       [::]:443 ssl;
        server_name  example.com www.example.com;

        ssl_certificate "/etc/nginx/ssl/www_server_rsa.crt";
        ssl_certificate_key "/etc/nginx/ssl/www_server_rsa.key";
        ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
        ssl_ecdh_curve X25519:P-256;
        ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:HIGH:!NULL:!aNULL:!MD5:!3DES:!DES:!ADH:!RC4:!DH:!DHE:!EXP;

        location / {
        }
}

首先看一下两个server的ssl证书内容,可以使用openssl命令查看,留意Subject参数。
default_server_rsa.crt的CN是Default Server,www_server_rsa.crt的CN是example.com

root@k8s-master1:/etc/nginx/ssl# openssl x509 -text -noout -in default_server_rsa.crt 
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            5b:75:14:0a:a5:f8:97:da:3b:eb:8d:09:e1:84:e5:67:cb:94:e2:42
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = CN, O = People's Republic of China, CN = Default CA
        Validity
            Not Before: Oct 29 07:22:33 2022 GMT
            Not After : Oct 26 07:22:33 2032 GMT
        Subject: C = CN, O = People's Republic of China, CN = Default Server
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:ee:aa:43:3b:44:08:f5:7e:62:35:f3:35:ac:ba:
                    ...
                    16:41:6e:ba:06:9f:9e:d9:03:d1:27:42:33:28:af:
                    9c:91
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            X509v3 Key Usage: 
                Digital Signature, Non Repudiation, Key Encipherment
    Signature Algorithm: sha256WithRSAEncryption
         27:07:ad:67:18:e2:4d:9c:48:14:c8:eb:f5:6c:2b:a1:7a:95:
         ...
         77:48:03:3c:e6:cc:1d:d2:e5:31:32:bf:4d:6e:a3:df:e3:89:
         d7:e5:4e:cb
root@k8s-master1:/etc/nginx/ssl# 
root@k8s-master1:/etc/nginx/ssl# openssl x509 -text -noout -in www_server_rsa.crt 
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            2c:a4:0b:32:9d:ed:2c:e4:98:a3:44:79:dd:c8:8a:a1:5a:16:e0:12
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = CN, O = People's Republic of China, CN = China CA
        Validity
            Not Before: Oct 28 17:12:27 2022 GMT
            Not After : Oct 25 17:12:27 2032 GMT
        Subject: C = CN, O = People's Republic of China, CN = example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:bc:7f:3e:ac:aa:ab:c6:02:74:22:fd:6c:61:43:
                    ...
                    02:38:16:66:69:9c:22:22:ac:96:f3:35:48:61:49:
                    7c:25
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Alternative Name: 
                DNS:example.com, DNS:www.example.com
            X509v3 Basic Constraints: 
                CA:FALSE
            X509v3 Key Usage: 
                Digital Signature, Non Repudiation, Key Encipherment
    Signature Algorithm: sha256WithRSAEncryption
         3c:a9:80:3d:b0:7f:f7:c9:e7:eb:1c:06:bb:52:5b:57:cc:15:
         ...
         96:5c:b4:0c:a5:99:30:26:98:6b:ea:16:c2:bb:88:88:a8:20:
         9f:19:a5:d0
root@k8s-master1:/etc/nginx/ssl# 

异常问题可以使用curl复现,发起两个请求,然后看一下有什么区别。

[root@centos ~]# curl -skvo /dev/null https://www.example.com -H "Host: www.example.com" --resolve www.example.com:443:192.168.3.47
* Added www.example.com:443:192.168.3.47 to DNS cache
* About to connect() to www.example.com port 443 (#0)
*   Trying 192.168.3.47...
* Connected to www.example.com (192.168.3.47) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
*   subject: CN=example.com,O=People's Republic of China,C=CN
*   start date: Oct 28 17:12:27 2022 GMT
*   expire date: Oct 25 17:12:27 2032 GMT
*   common name: example.com
*   issuer: CN=China CA,O=People's Republic of China,C=CN
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Accept: */*
> Host: www.example.com
> 
< HTTP/1.1 200 OK
< Server: nginx
< Date: Sat, 29 Oct 2022 11:09:33 GMT
< Content-Type: text/html
< Content-Length: 612
< Last-Modified: Tue, 21 Apr 2020 14:09:01 GMT
< Connection: keep-alive
< ETag: "5e9efe7d-264"
< Accept-Ranges: bytes
< 
{ [data not shown]
* Connection #0 to host www.example.com left intact
[root@centos ~]# 
[root@centos ~]# 
[root@centos ~]# curl -skvo /dev/null https://192.168.3.47 -H "Host: www.example.com" --resolve www.example.com:443:192.168.3.47
* Added www.example.com:443:192.168.3.47 to DNS cache
* About to connect() to 192.168.3.47 port 443 (#0)
*   Trying 192.168.3.47...
* Connected to 192.168.3.47 (192.168.3.47) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
*   subject: CN=Default Server,O=People's Republic of China,C=CN
*   start date: Oct 29 07:22:33 2022 GMT
*   expire date: Oct 26 07:22:33 2032 GMT
*   common name: Default Server
*   issuer: CN=Default CA,O=People's Republic of China,C=CN
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Accept: */*
> Host: www.example.com
> 
< HTTP/1.1 200 OK
< Server: nginx
< Date: Sat, 29 Oct 2022 11:09:40 GMT
< Content-Type: text/html
< Content-Length: 612
< Last-Modified: Tue, 21 Apr 2020 14:09:01 GMT
< Connection: keep-alive
< ETag: "5e9efe7d-264"
< Accept-Ranges: bytes
< 
{ [data not shown]
* Connection #0 to host 192.168.3.47 left intact
[root@centos ~]# 

第一个请求响应的ssl证书是正确的,第二个请求响应的ssl证书是错的。注意看两个请求ssl握手期间的subject内容,第一个请求中的CN是example.com,这是正确的ssl证书,第二个请求中的CN是Default Server,这个是错的,也说明了访问www.example.com,nginx使用了默认server的ssl证书来响应。
从curl的返回看不出有什么异常,那么就只能通过抓包了。

image.png image.png

通过抓包分析,发现第一个请求在ssl握手时客户端有携带server_name参数,而第二个请求则是未携带server_name参数,然后nginx就响应默认server的证书。

对于这种情况,客户端在发起请求时必须指定ssl的server_name参数,否则得到的证书就有可能是错误的,例如ssl双向认证也可能有异常。一般支持SNI功能的客户端都是可以配置server_name的。

问题解决之后,不禁感慨。怪不得在调试业务时老是出现问题,通过抓包才发现原来是这东西惹的祸。

另外如果用curl访问https请求,推荐用这条命令。

curl -skvo /dev/null https://www.example.com -H "Host: www.example.com" --resolve www.example.com:443:192.168.3.47

相关文章

  • 记一次nginx https的坑

    服务器部署了nginx,nginx配置了多个不同域名的server,分别是www.example.com[http...

  • 【Nginx】

    记录一下Nginx配置的坑 官网https://nginx.org/en/download.html[https:...

  • 记一次nginx配置https

    nginx版本1.14.0,openssl版本1.0.2nginx -vopenssl version 拿到的证书...

  • 砸壳采坑

    记一次砸壳的采坑之路 <<<<<----0919https://github.com/KJCracks/Clutc...

  • nginx 源码安装 mac

    nginx源码安装,添加with-http_ssl_module, mac采坑记 首先,下载源码,解压,进ngin...

  • nginx采坑记

    采坑系列2-nginx 最近因为工作,需要配置nginx,初期nginx都运行的非常的顺利,在终端输入命令 ngi...

  • 简单|就好

    记一次蜀山之行…………【坑】

  • http和https在nginx中的坑

    首先需要知道的是通讯协议一共分为7个层次。 而http和https都在应用层中,https和http之间差的就是一...

  • 小程序wx.request失败,无法发出请求解决办法

    记一次小程序踩坑,时间18年3月24.小程序发出的网络请求需要满足HTTPS协议,在我配置好HTTPS并且保证TL...

  • nginx - https

    1、http 重定向 [图片上传失败...(image-ca2188-1534050760876)] 2、一台主机...

网友评论

      本文标题:记一次nginx https的坑

      本文链接:https://www.haomeiwen.com/subject/cifctdtx.html