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

本文涉及的产品
.cn 域名,1个 12个月
密钥管理服务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,这一组是客户端检验的参数。

目录
相关文章
|
1月前
|
缓存 应用服务中间件 网络安全
Nginx中配置HTTP2协议的方法
Nginx中配置HTTP2协议的方法
79 7
|
4天前
|
存储 应用服务中间件 nginx
nginx反向代理bucket目录配置
该配置实现通过Nginx代理访问阿里云OSS存储桶中的图片资源。当用户访问代理域名下的图片URL(如 `http://代理域名/123.png`)时,Nginx会将请求转发到指定的OSS存储桶地址,并重写路径为 `/prod/files/2024/12/12/123.png`。
32 5
|
28天前
|
缓存 负载均衡 算法
如何配置Nginx反向代理以实现负载均衡?
如何配置Nginx反向代理以实现负载均衡?
|
1月前
|
存储 负载均衡 中间件
Nginx反向代理配置详解,图文全面总结,建议收藏
Nginx 是大型架构必备中间件,也是大厂喜欢考察的内容,必知必会。本篇全面详解 Nginx 反向代理及配置,建议收藏。
Nginx反向代理配置详解,图文全面总结,建议收藏
|
19天前
|
负载均衡 前端开发 应用服务中间件
负载均衡指南:Nginx与HAProxy的配置与优化
负载均衡指南:Nginx与HAProxy的配置与优化
39 3
|
1月前
|
应用服务中间件 API nginx
nginx配置反向代理404问题
【10月更文挑战第18天】本文介绍了使用Nginx进行反向代理的配置方法,解决了404错误、跨域问题和302重定向问题。关键配置包括代理路径、请求头设置、跨域头添加以及端口转发设置。通过调整`proxy_set_header`和添加必要的HTTP头,实现了稳定的服务代理和跨域访问。
244 1
nginx配置反向代理404问题
|
28天前
|
负载均衡 监控 应用服务中间件
配置Nginx反向代理时如何指定后端服务器的权重?
配置Nginx反向代理时如何指定后端服务器的权重?
49 4
|
28天前
|
安全 应用服务中间件 网络安全
如何测试Nginx反向代理实现SSL加密访问的配置是否正确?
如何测试Nginx反向代理实现SSL加密访问的配置是否正确?
52 3
|
28天前
|
安全 应用服务中间件 网络安全
配置Nginx反向代理实现SSL加密访问的步骤是什么?
我们可以成功地配置 Nginx 反向代理实现 SSL 加密访问,为用户提供更安全、可靠的网络服务。同时,在实际应用中,还需要根据具体情况进行进一步的优化和调整,以满足不同的需求。SSL 加密是网络安全的重要保障,合理配置和维护是确保系统安全稳定运行的关键。
102 3
|
1月前
|
应用服务中间件 网络安全 nginx
轻松上手Nginx Proxy Manager:安装、配置与实战
Nginx Proxy Manager (NPM) 是一款基于 Nginx 的反向代理管理工具,提供直观的 Web 界面,方便用户配置和管理反向代理、SSL 证书等。本文档介绍了 NPM 的安装步骤,包括 Docker 和 Docker Compose 的安装、Docker Compose 文件的创建与配置、启动服务、访问 Web 管理界面、基本使用方法以及如何申请和配置 SSL 证书,帮助用户快速上手 NPM。
195 1