企业级Nginx实战-配置Https单向认证、双向认证

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 企业级Nginx实战-配置Https单向认证、双向认证

一、背景



继上一篇企业级nginx实战,里面有一位访客留言说要我写一篇关于验证客服端证书的留言。我们通常配置的https一般使用的证书是单向验证,也就是说客户端单向验证服务器的安全性,但是服务器端是没有对客户端的身份进行验证的。Nginx的单向和双向验证都要http_ssl_module的支持,查看方法如下:


  1. nginx安装包
>./nginx -v
nginx version: nginx/1.19.4
built by gcc 8.3.0 (Debian 8.3.0-6)
built with OpenSSL 1.1.1d  10 Sep 2019
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-1.19.4/debian/debuild-base/nginx-1.19.4=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'


  1. docker镜像版
[root@k8snode1 html]# docker exec -it nginx /bin/sh
# nginx -V
nginx version: nginx/1.19.4
built by gcc 8.3.0 (Debian 8.3.0-6)
built with OpenSSL 1.1.1d  10 Sep 2019
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-1.19.4/debian/debuild-base/nginx-1.19.4=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'
#


  1. 如不支持的解决思路:Nginx为了支持Https需要安装http_ssl_module模块。在编译时需要带上--with-http_ssl_module参数。
./configure --prefix=/usr/local/nginx --with-http_ssl_module
make && make install


二、单向验证



1. 原理解析


单向认证流程中,服务器端保存着公钥证书和私钥两个文件,整个握手过程如下:


  1. 客户端发起建立HTTPS连接请求,将SSL协议版本的信息发送给服务器端;
  2. 服务器端将本机的公钥证书(server.crt)发送给客户端;
  3. 客户端读取公钥证书(server.crt),取出了服务端公钥;客户端生成一个随机数(密钥R),用刚才得到的服务器公钥去加密这个随机数形成密文,发送给服务端;
  4. 服务端用自己的私钥(server.key)去解密这个密文,得到了密钥R
  5. 服务端和客户端在后续通讯过程中就使用这个密钥R进行通信了。


2. 证书文件


  1. 服务器端私钥文件:server.key
  2. 服务器端公钥证书:server.pem


3. 配置方法


  1. 证书申请和下载



华为云和阿里云有个人的免费的证书,可以申请,但是尴尬的是,需要域名。如果没有域名的小伙伴可以自己通过jdk或者openssl生成证书,如果不会的话,可以参考文章末尾关于生成证书的章节。2. 配置文件、证书存放目录和静态资源目录


root@iZbp1g1qpfdlqea4avz2sfZ:~/nginx-conf# ll
total 24
drwxr-xr-x  4 root root 4096 Jan  3 00:49 ./
drwx------ 24 root root 4096 Jan  8 23:26 ../
-rw-r--r--  1 root root 7205 Dec 29 13:44 nginx.conf
drwxr-xr-x  2 root root 4096 Jul  6  2021 ssl/
drwxr-xr-x  3 root root 4096 Dec 27 10:43 static/
root@iZbp1g1qpfdlqea4avz2sfZ:~/nginx-conf# ll ssl
total 20
drwxr-xr-x 2 root root 4096 Jul  6  2021 ./
drwxr-xr-x 4 root root 4096 Jan  3 00:49 ../
-rw-r--r-- 1 root root 1679 Jul  6  2021 server.key
-rw-r--r-- 1 root root 4224 Jul  6  2021 server.pem


证书下载好后会有一个server.key和server.pem文件,将文件放置在ssl目录下


  1. 修改nginx.conf
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    #上传大小限制
    client_max_body_size 5000m;
    #下载大小限制
    proxy_max_temp_file_size 5000m;
    gzip  on;
    server {
        listen       443 ssl;
        server_name  cloud-dev.imagecore.com.cn;
        # 指定证书文件存放路径
        ssl_certificate      /etc/nginx/ssl/server.pem;
        # 指定key文件存放路径
        ssl_certificate_key  /etc/nginx/ssl/server.key;
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;
        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;
        add_header Content-Security-Policy "upgrade-insecure-requests"; 
        location / {
            root   /etc/nginx/html;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
                root   html;
        }
    }
}


需要注意的是指定的密钥与证书和挂载的容器数据卷路径是一致的,否则会报找不到证书和密钥的错误。


  1. 创建nginx容器
docker run --name nginx -p 443:443 -v /root/nginx/nginx.conf:/etc/nginx/nginx.conf -v /root/nginx/ssl:/etc/nginx/ssl -v /root/nginx/html:/etc/nginx/html -d nginx


  1. 通过https加域名访问主页



三、双向验证



1. 原理解析


  1. 客户端发起HTTPS连接请求,同时将SSL协议版本的信息发送给服务端;
  2. 服务器端将本机的公钥证书(server.crt)发送给客户端;
  3. 客户端读取公钥证书(server.crt),取出了服务端公钥;
  4. 客户端将客户端公钥证书(client.crt)发送给服务器端;
  5. 服务器端使用根证书(root.crt)解密客户端公钥证书,拿到客户端公钥;
  6. 客户端发送自己支持的加密方案给服务器端;
  7. 服务器端根据自己和客户端的能力,选择一个双方都能接受的加密方案,使用客户端的公钥加密8后发送给客户端;
  8. 客户端使用自己的私钥解密加密方案,生成一个随机数R,使用服务器公钥加密后传给服务器端;
  9. 服务端用自己的私钥去解密这个密文,得到了密钥R
  10. 服务端和客户端在后续通讯过程中就使用这个密钥R进行通信了


2. 证书文件


2.1 接入单个客户端


「使用客户端的公钥证书作为服务器端的验证证书来进行客户端的身份验证」


  1. 服务器端公钥证书:server.pem
  2. 服务器端私钥文件:server.key
  3. 服务器端根证书:client.pem
  4. 客服端公钥证书:client.pem
  5. 客服端私钥文件:client.key
  6. 客服端集成证书(含公私钥):client.p12


2.2 接入多个客户端


「使用服务器端跟证书签发客户端证书文件,然后利用根证书来进行客服端身份验证」


  1. 服务器端公钥证书:server.pem
  2. 服务器端私钥文件:server.key
  3. 服务器端根证书:root.crt
  4. 客服端公钥证书:client.pem
  5. 客服端私钥文件:client.key
  6. 客服端集成证书(含公私钥):client.p12


3. 配置方法


3.1 单个客户端


这个直接申请两套华为云或者阿里云的证书就可以了,不做过多的解释,直接展示Nginx的配置就可以了,具体的启动和展示就不在赘述。


events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    #上传大小限制
    client_max_body_size 5000m;
    #下载大小限制
    proxy_max_temp_file_size 5000m;
    gzip  on;
    server {
        listen       443 ssl;
        server_name  cloud-dev.imagecore.com.cn;
        # 指定证书文件存放路径
        ssl_certificate      /etc/nginx/ssl/server.pem;
        # 指定key文件存放路径
        ssl_certificate_key  /etc/nginx/ssl/server.key;
        # 指定客户端校验证书
        ssl_client_certificate /etc/nginx/ssl/client.pem
        # 开启客户端证书验证
        ssl_verify_client on;
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;
        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;
        add_header Content-Security-Policy "upgrade-insecure-requests"; 
        location / {
            root   /etc/nginx/html;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
                root   html;
        }
    }
}


3.2 多个客户端


接入多个客户端,可以采用多个域名的方式接入,但是不太实用;一般都是使用同一个域名和接口的,剩下的方式就是根证签发客户证书的方式了。


  1. 「安装openssl」
[root@k8snode1 ~]# yum install
Loaded plugins: fastestmirror, product-id, search-disabled-repos, subscription-
              : manager
This system is not registered with an entitlement server. You can use subscripti                                                                              on-manager to register.
Error: Need to pass a list of pkgs to install
 Mini usage:
install PACKAGE...
Install a package or packages on your system
aliases: install-n, install-na, install-nevra
[root@k8snode1 ~]# yum install openssl
Loaded plugins: fastestmirror, product-id, search-disabled-repos, subscription-
              : manager
This system is not registered with an entitlement server. You can use subscripti                                                                              on-manager to register.
Determining fastest mirrors
 * base: mirrors.aliyun.com
 * extras: mirrors.aliyun.com
 * updates: mirrors.aliyun.com
base                                                     | 3.6 kB     00:00
extras                                                   | 2.9 kB     00:00
updates                                                  | 2.9 kB     00:00
(1/2): extras/7/x86_64/primary_db                          | 243 kB   00:01
(2/2): updates/7/x86_64/primary_db                         |  13 MB   00:18
Resolving Dependencies
--> Running transaction check
---> Package openssl.x86_64 1:1.0.2k-19.el7 will be updated
---> Package openssl.x86_64 1:1.0.2k-22.el7_9 will be an update
--> Processing Dependency: openssl-libs(x86-64) = 1:1.0.2k-22.el7_9 for package:                                                                               1:openssl-1.0.2k-22.el7_9.x86_64
--> Running transaction check
---> Package openssl-libs.x86_64 1:1.0.2k-19.el7 will be updated
---> Package openssl-libs.x86_64 1:1.0.2k-22.el7_9 will be an update
--> Finished Dependency Resolution
Dependencies Resolved
================================================================================
 Package            Arch         Version                    Repository     Size
================================================================================
Updating:
 openssl            x86_64       1:1.0.2k-22.el7_9          updates       494 k
Updating for dependencies:
 openssl-libs       x86_64       1:1.0.2k-22.el7_9          updates       1.2 M
Transaction Summary
================================================================================
Upgrade  1 Package (+1 Dependent package)
Total download size: 1.7 M
Is this ok [y/d/N]: y
Downloading packages:
Delta RPMs disabled because /usr/bin/applydeltarpm not installed.
(1/2): openssl-1.0.2k-22.el7_9.x86_64.rpm                  | 494 kB   00:01
(2/2): openssl-libs-1.0.2k-22.el7_9.x86_64.rpm             | 1.2 MB   00:02
--------------------------------------------------------------------------------
Total                                              626 kB/s | 1.7 MB  00:02
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Updating   : 1:openssl-libs-1.0.2k-22.el7_9.x86_64                        1/4
  Updating   : 1:openssl-1.0.2k-22.el7_9.x86_64                             2/4
  Cleanup    : 1:openssl-1.0.2k-19.el7.x86_64                               3/4
  Cleanup    : 1:openssl-libs-1.0.2k-19.el7.x86_64                          4/4
  Verifying  : 1:openssl-1.0.2k-22.el7_9.x86_64                             1/4
  Verifying  : 1:openssl-libs-1.0.2k-22.el7_9.x86_64                        2/4
  Verifying  : 1:openssl-libs-1.0.2k-19.el7.x86_64                          3/4
  Verifying  : 1:openssl-1.0.2k-19.el7.x86_64                               4/4
Updated:
  openssl.x86_64 1:1.0.2k-22.el7_9
Dependency Updated:
  openssl-libs.x86_64 1:1.0.2k-22.el7_9
Complete!


  1. 「生成自签名根证书」
(1)创建根证书私钥:
openssl genrsa -out root.key 1024
(2)创建根证书请求文件:
openssl req -new -out root.csr -key root.key
后续参数请自行填写,下面是一个例子:
Country Name (2 letter code) [XX]:CH
State or Province Name (full name) []:HB
Locality Name (eg, city) [Default City]:WH
Organization Name (eg, company) [Default Company Ltd]:HH
Organizational Unit Name (eg, section) []:HH
Common Name (eg, your name or your server's hostname) []:root
Email Address []:aaa
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
(3)创建根证书:
openssl x509 -req -in root.csr -out root.crt -signkey root.key -CAcreateserial -days 365
(4)执行结果查看
[root@k8snode1 ssl]# ll
total 12
-rw-r--r-- 1 root root 839 Jan  9 11:08 root.crt
-rw-r--r-- 1 root root 647 Jan  9 11:06 root.csr
-rw-r--r-- 1 root root 887 Jan  9 10:57 root.key


  1. 「生成自签名服务器端证书」
(1)生成服务器端证书私钥:
openssl genrsa -out server.key 1024
(2) 生成服务器证书请求文件,过程和注意事项参考根证书,本节不详述:
openssl req -new -out server.csr -key server.key
(3) 生成服务器端公钥证书
openssl x509 -req -in server.csr -out server.crt -signkey server.key -CA root.crt -CAkey root.key -CAcreateserial -days 3650
(4) 执行结果查看
[root@k8snode1 ssl]# ll
total 28
-rw-r--r-- 1 root root 839 Jan  9 11:08 root.crt
-rw-r--r-- 1 root root 647 Jan  9 11:06 root.csr
-rw-r--r-- 1 root root 887 Jan  9 10:57 root.key
-rw-r--r-- 1 root root  17 Jan  9 11:37 root.srl
-rw-r--r-- 1 root root 834 Jan  9 11:37 server.crt
-rw-r--r-- 1 root root 643 Jan  9 11:37 server.csr
-rw-r--r-- 1 root root 887 Jan  9 11:36 server.key


  1. 「生成自签名客户端证书」
(1)生成客户端证书秘钥:
openssl genrsa -out client.key 1024
openssl genrsa -out client2.key 1024
(2) 生成客户端证书请求文件,过程和注意事项参考根证书,本节不详述:
openssl req -new -out client.csr -key client.key
openssl req -new -out client2.csr -key client2.key
(3) 生客户端证书
openssl x509 -req -in client.csr -out client.crt -signkey client.key -CA root.crt -CAkey root.key -CAcreateserial -days 3650
openssl x509 -req -in client2.csr -out client2.crt -signkey client2.key -CA root.crt -CAkey root.key -CAcreateserial -days 3650
(4) 生客户端p12格式证书,需要输入一个密码,选一个好记的,比如123456
openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12
openssl pkcs12 -export -clcerts -in client2.crt -inkey client2.key -out client2.p12
(5) 执行结果查看
[root@k8snode1 ssl]# ll
[root@k8snode1 ssl]# ll
total 60
-rw-r--r-- 1 root root  810 Jan  9 11:45 client2.crt
-rw-r--r-- 1 root root  615 Jan  9 11:45 client2.csr
-rw-r--r-- 1 root root  887 Jan  9 11:43 client2.key
-rw-r--r-- 1 root root 1573 Jan  9 11:46 client2.p12
-rw-r--r-- 1 root root  794 Jan  9 11:45 client.crt
-rw-r--r-- 1 root root  599 Jan  9 11:43 client.csr
-rw-r--r-- 1 root root  891 Jan  9 11:43 client.key
-rw-r--r-- 1 root root 1565 Jan  9 11:45 client.p12
-rw-r--r-- 1 root root  839 Jan  9 11:08 root.crt
-rw-r--r-- 1 root root  647 Jan  9 11:06 root.csr
-rw-r--r-- 1 root root  887 Jan  9 10:57 root.key
-rw-r--r-- 1 root root   17 Jan  9 11:45 root.srl
-rw-r--r-- 1 root root  834 Jan  9 11:37 server.crt
-rw-r--r-- 1 root root  643 Jan  9 11:37 server.csr
-rw-r--r-- 1 root root  887 Jan  9 11:36 server.key


  1. nginx配置文件
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    #上传大小限制
    client_max_body_size 5000m;
    #下载大小限制
    proxy_max_temp_file_size 5000m;
    gzip  on;
    server {
        listen       443 ssl;
        server_name  cloud-dev.imagecore.com.cn;
        # 指定证书文件存放路径
        ssl_certificate      /etc/nginx/ssl/server.crt;
        # 指定key文件存放路径
        ssl_certificate_key  /etc/nginx/ssl/server.key;
        # 指定客户端校验证书
        ssl_client_certificate /etc/nginx/ssl/root.crt
        # 开启客户端证书验证
        ssl_verify_client on;
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;
        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;
        add_header Content-Security-Policy "upgrade-insecure-requests"; 
        location / {
            root   /etc/nginx/html;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
                root   html;
        }
    }
}


四、总结



以上就是Nginx单向校验和双向校验在内容,其中双向部分包含了对client的校验部分,应该是回答了上一篇知友的提问。这里下一篇将讲述双向校验的测试方式,这里暂时先保留一下。其实这一部分的配置及其简单,基本上就只有四个属性的配置:ssl_certificatessl_certificate_key,这一组是服务端检验的参数;ssl_client_certificatessl_verify_client,这一组是客户端检验的参数。

目录
相关文章
|
14天前
|
缓存 前端开发 JavaScript
终极 Nginx 配置指南(全网最详细)
本文详细介绍了Nginx配置文件`nginx.conf`的基本结构及其优化方法。首先通过删除注释简化了原始配置,使其更易理解。接着,文章将`nginx.conf`分为全局块、events块和http块三部分进行详细解析,帮助读者更好地掌握其功能与配置。此外,还介绍了如何通过简单修改实现网站上线,并提供了Nginx的优化技巧,包括解决前端History模式下的404问题、配置反向代理、开启gzip压缩、设置维护页面、在同一IP上部署多个网站以及实现动静分离等。最后,附上了Nginx的基础命令,如安装、启动、重启和关闭等操作,方便读者实践应用。
204 84
终极 Nginx 配置指南(全网最详细)
|
3天前
|
JavaScript 应用服务中间件 开发工具
vue尚品汇商城项目-day07【53.nginx反向代理配置】
vue尚品汇商城项目-day07【53.nginx反向代理配置】
13 4
|
3天前
|
缓存 应用服务中间件 nginx
nginx如何配置?配置项都是什么意思?
nginx如何配置?配置项都是什么意思?
13 1
|
6天前
|
应用服务中间件 nginx Docker
docker应用部署---nginx部署的配置
这篇文章介绍了如何使用Docker部署Nginx服务器,包括搜索和拉取Nginx镜像、创建容器并设置端口映射和目录映射,以及如何创建一个测试页面并使用外部机器访问Nginx服务器。
|
17天前
|
应用服务中间件 网络安全 Apache
HTTPS配置
HTTPS配置
71 11
|
20天前
|
监控 安全 应用服务中间件
如何配置HTTPS协议?
如何配置HTTPS协议?
33 4
|
26天前
|
应用服务中间件 nginx
一文搞定Nginx配置RTMP!
一文搞定Nginx配置RTMP!
63 3
|
27天前
|
Ubuntu 应用服务中间件 数据库
Nginx配置:阻止非国内IP地址访问的设置方法
此外,出于用户隐私和法律合规性的考虑,应慎重考虑阻止特定国家或地区IP地址的决策。在某些情况下,这可能被视为歧视性或违反当地法律。
49 2
|
6天前
|
应用服务中间件 nginx 索引
7-15|Nginx配置
7-15|Nginx配置
|
7天前
|
监控 安全 搜索推荐
设置 HTTPS 协议以确保数据传输的安全性
设置 HTTPS 协议以确保数据传输的安全性
下一篇
无影云桌面