自签名SSL证书以及nginx配置https服务
作者:mmseoamin日期:2024-02-04

自签名SSL证书以及nginx配置https服务

 

服务器SSL的认证流程

单向认证

  1. 客户端发起建立HTTPS连接请求,将SSL协议版本的信息发送给服务端

  2. 服务器端将本机的公钥证书发送给客户端

  3. 客户端读取公钥证书,取出服务端公钥

  4. 客户端生成一个随机数(秘钥R),用刚才得到的服务器公钥去加密这个随机数行程秘文,发送给服务器

  5. 服务器用自己的私钥去解密这个秘文,得到秘钥R

  6. 客户端和服务端在后续的通讯过程中就是用这个秘钥R进行通信

双向认证

  1. 客户端发起建立HTTPS连接请求,将SSL协议版本的信息发送给服务端

  2. 服务器端将本机的公钥证书发送给客户端

  3. 客户端读取公钥证书,取出服务端公钥

  4. 客户端将客户端公钥证书发送给服务端

  5. 服务器端解密客户端公钥证书,拿到客户端公钥

  6. 客户端发送自己支持的加密方案给服务端

  7. 服务端根据自己和客户端的能力,选择一个双方都能接受的加密方式,使用客户端的公钥加密后发送给客户端

  8. 客户端使用自己的私钥解密加密方案,生成一个随机数R,使用服务器公钥加密之后传给服务端

  9. 服务端用自己的私钥去解密这个秘文,得到秘钥R

  10. 客户端和服务端在后续的通讯过程中就是用这个秘钥R进行通信

不难发现双向认证会比单项认证更安全,当然性能肯定是不如单向

自签名SSL证书

需要生成的证书文件

  • 服务端公钥证书:server.crt

  • 服务端私钥证书:server-privatekey.pem

  • 客户端公钥证书:client.crt

  • 客户端私钥证书:client-privatekey.pem

  • 客户端集成证书(包括公钥和私钥,用于浏览器访问场景):client.p12

    在开始生成这一系列证书之前,需要先生成一个CA根证书,通过这个CA根证书颁发服务器公钥和客户端公钥,假装我们是正规的CA机构(手动狗头)

    自建CA

    1. 创建私钥privatekey.pem

      openssl genrsa -out privatekey.pem

      如果不指定-out参数2048bit的私钥会直接在命令行打印

      自签名SSL证书以及nginx配置https服务,第1张

      -out为存储路径

    2. 根据私钥生成一个新的证书请求文件

      openssl req -key privatekey.pem -new -out ca.csr
      • -new 生成一个新的证书请求

      • -out 存储路径

      • -key 指定读取私钥的文件路径,这里使用了上一步中生成的私钥文件,如果不指定会先初始化一个私钥

      执行该命令后根据提示完善一些信息

    3. 自签名SSL证书以及nginx配置https服务,第2张

      • Country Name:国家,这里限制输入两个字符,中国是CN

      • State or Province Name:州或者省份

      • Locality Name:城市

      • Organization Name:组织,可以采用公司名

      • Organizational Unit Name:组织单位,有些ca机构没有该内容

      • Common Name:公用名,这里填域名,没有域名的话用服务器的ip

      • Email Address:邮箱,这里我回车跳过了

      • A challenge password:请求文件的密码,可以直接回车跳过

      如果不想要在对话框中依次输入信息,可以执行下面的命令

      openssl req -key privatekey.pem -new -out ca.csr -subj /C=cn/ST=guangdong/L=guangzhou/O=testcompany/OU=testdepartment/CN=test.com
    4. 创建根证书

      openssl x509 -req -in ca.csr -out ca.crt -signkey privatekey.pem -CAcreateserial -days 365

      x509是一个多功能的证书命令。可以用来展示证书信息、转换证书格式、像mini CA一样签名证书请求或者修改证书信任设置

      • -in 输入文件的读取路径

      • -out 输出文件的存储路径

      • -signkey 私钥文件路径

      • -CAcreateserial 避免没有CA serial number file(该文件只有一行,包含偶数个十六进制的字符)时候的报错。没有的话这里会自动创建一个。

      • -days 证书有效天数

      自签名SSL证书以及nginx配置https服务,第3张

    生成服务器端证书

    1. 生成证书私钥

      openssl genrsa -out server-privatekey.pem
    2. 使用私钥生成服务器端证书的请求文件

      openssl req -key server-privatekey.pem -new -out server.csr -subj /C=cn/ST=guangdong/L=guangzhou/O=testcompany/OU=testdepartment/CN=test.com

      这里我直接沿用了CA证书时候的参数,不然开启SSL双向认证的时候无法正常请求

    3. 生成服务器端证书

      openssl x509 -req -in server.csr -out server.crt -signkey server-privatekey.pem -CA ca.crt -CAkey privatekey.pem -CAcreateserial -days 365

      大部分参数在生成CA证书的时候都有使用,这里说明一下两个之前未使用到的参数

      • -CA 使用的CA证书

      • -CAkey 使用的CA证书私钥

    如果不使用SSL双向认证的话,到这里就可以了,服务端开启ssl有服务端证书server.crt和服务端证书server-privatekey.pem就够了,nginx配置如下

    server {
            #SSL 默认访问端口号为 443
            listen 9090 ssl;
            #请填写绑定证书的域名
            #server_name cloud.tencent.com;
            #请填写证书文件的相对路径或绝对路径
            ssl_certificate cert/server.crt;
            #请填写私钥文件的相对路径或绝对路径
            ssl_certificate_key cert/server-privatekey.pem;
            # ssl_client_certificate cert/client.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;
            ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
            # ...
            # ...
    }

    生成客户端证书

    生成客户端证书的过程基本上和生产服务端证书一致

    1. 生成客户端证书私钥

      openssl genrsa -out client-privatekey.pem
    2. 使用证书私钥生成客户端证书请求文件

      openssl req -key client-privatekey.pem -new -out client.csr -subj /C=cn/ST=guangdong/L=guangzhou/O=testcompany/OU=testdepartment/CN=test.com

      沿用了CA证书时候的参数

    3. 生成客户端证书

      openssl x509 -req -in client.csr -out client.crt -signkey client-privatekey.pem -CA ca.crt -CAkey privatekey.pem -CAcreateserial -days 365
    4. 生成p12格式的证书

      openssl pkcs12 -export -clcerts -in client.crt -inkey client-privatekey.pem -out client.p12

      pkcs12命令用于生成或者转换p12文件

      • -export 生成pkcs#12文件

      • -clcerts 只输出客户端证书

      • -in 输入文件

      • -inkey 私钥

      • -out 输出

    nginx配置

    server {
            #SSL 默认访问端口号为 443
            listen 443 ssl;
            #请填写绑定证书的域名
            #server_name cloud.tencent.com;
            #请填写证书文件的相对路径或绝对路径
            ssl_certificate cert/server.crt;
            #请填写私钥文件的相对路径或绝对路径
            ssl_certificate_key cert/server-privatekey.pem;
            #客户端证书
            ssl_client_certificate cert/client.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;
            ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
            # ...
            # ...
        }

    这里开启了校验客户端证书,校验的话可以注释掉ssl_verify_client on;

    到这里想要访问服务的话就必须要在客户端导入clien.p12证书,否则客户端请求的时候就会报错

    自签名SSL证书以及nginx配置https服务,第4张