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

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
.cn 域名,1个 12个月
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 企业级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,这一组是客户端检验的参数。

目录
相关文章
|
30天前
|
缓存 负载均衡 安全
Nginx常用基本配置总结:从入门到实战的全方位指南
Nginx常用基本配置总结:从入门到实战的全方位指南
246 0
|
10天前
|
Web App开发 算法 应用服务中间件
nginx开启局域网https访问
【10月更文挑战第22天】为了调试WebRTC功能,需要在局域网内搭建HTTPS协议。具体步骤包括:在已部署Nginx和安装OpenSSL的环境中生成私钥、证书签名请求和自签名证书;将生成的文件放置到Nginx的证书目录并修改Nginx配置文件,最后重启Nginx服务。注意,自签名证书不受第三方机构认可,如需正式使用,需向CA申请签名。
|
1月前
|
安全 应用服务中间件 Shell
nginx配置https的ssl证书和域名
nginx配置https的ssl证书和域名
|
1月前
|
Docker 容器
docker nginx-proxy 添加自定义https网站
docker nginx-proxy 添加自定义https网站
34 4
|
3月前
|
缓存 算法 应用服务中间件
nginx搭建https服务器
nginx搭建https服务器
|
5月前
|
安全 Ubuntu 应用服务中间件
NGINX环境下实现Web网站访问控制的实战指南
在NGINX中设置基于IP的访问控制可提升网站安全性。步骤包括安装NGINX、备份配置文件、编辑`/etc/nginx/sites-available/default`,添加`allow`和`deny`指令限制特定IP访问,如`allow 192.168.1.100; deny all;`,然后测试配置并重启服务。成功后,仅允许的IP能访问网站,否则会收到403错误。这为Web安全提供基础保障,还可扩展实现更多高级控制策略。【6月更文挑战第20天】
596 3
|
5月前
|
弹性计算 应用服务中间件 Linux
双剑合璧:在同一ECS服务器上共存Apache与Nginx的实战攻略
在ECS服务器上同时部署Apache和Nginx的实战:安装更新系统,Ubuntu用`sudo apt install apache2 nginx`,CentOS用`sudo yum install httpd nginx`。配置Nginx作为反向代理,处理静态内容及转发动态请求到Apache(监听8080端口)。调整Apache的`ports.conf`监听8080。重启服务测试,实现两者高效协同,提升Web服务性能。记得根据流量和需求优化配置。【6月更文挑战第21天】
513 1
|
5月前
|
监控 前端开发 应用服务中间件
前端开发者必备:Nginx入门实战宝典,从部署到优化一网打尽(2)
前端开发者必备:Nginx入门实战宝典,从部署到优化一网打尽
82 1
|
4月前
|
缓存 负载均衡 监控
Nginx性能调优5招35式不可不知的策略实战
以上 V 哥总结的5个方面关于 Nginx性能调优的策略,实际应用中需要结合实际项目的情况来测试,希望对你有帮助,欢迎关注威哥爱编程,技术路上我们一起成长。
138 0
|
23天前
|
应用服务中间件 BI nginx
Nginx的location配置详解
【10月更文挑战第16天】Nginx的location配置详解