[date: 2018-03-02 17:23] [visits: 14]

Nginx配置HTTPS客户端认证

最近折腾自己个人网站,有一个私人模块,只能自己访问,使用登录授权方式虽然也能达到目的,但每次都要登录,且密码也不一定安全。想起学HTTPS的时,有一个客户端证书的概念,应该可以满足更高的安全性要求,本文记录折腾过程。

原理

TLS握手过程,第二步Server Hello中可以要求客户端提供证书,接着客户端需要将服务器颁发的证书发送给服务器。服务端验证客户端证书,有效则使用证书公钥加密信息发送给客户端,客户端通过私钥解密所需信息,计算出Pre-master,用服务端证书公钥加密,发送给服务器。

如果客户端证书无效,或者过期等,服务端在收到后会断开连接。

准备证书

主要准备三份证书:CA证书、服务器证书、客户端证书。如果只是单个用户需要,可以不需要CA证书,具体如何做,留给大家思考。

新建临时工作区

    cd /root
    mkdir -p tmp/ca/conf
    cd tmp

CA证书

CA证书作为根证书,可以签发众多客户端证书,在TSL握手过程中用于验证客户端证书是否有效。

pwd: /root/tmp/ca

第一步,生成CA证书密钥

    openssl genrsa 2048 > ca.key

第二步,生成CA证书

    openssl req -new -x509 -key ca.key -out ca.crt -days 3650
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [XX]:XX
    State or Province Name (full name) []:XX
    Locality Name (eg, city) [Default City]:XX
    Organization Name (eg, company) [Default Company Ltd]:XX
    Organizational Unit Name (eg, section) []:XX
    Common Name (eg, your name or your server's hostname) []:XX
    Email Address []:XX

第三步,签发证书配置文件

文件初始化

    > conf/openssl.conf
    > conf/index.txt
    echo 00 > conf/serial

conf/openssl.conf文件内容:

    [ ca ] 
    default_ca = XX                             # The default ca section 

    [ XX ] 
    dir = /root/tmp/
    new_certs_dir = /root/tmp/ca/

    certificate = /root/tmp/ca/ca.crt           # The CA cert  
    private_key = /root/tmp/ca/ca.key           # CA private key  

    database = /root/tmp/ca/conf/index.txt      # index file.  
    serial = /root/tmp/ca/conf/serial           # serial no file  

    default_days = 365                          # how long to certify for  
    default_crl_days = 30                       # how long before next CRL  
    default_md = sha1                           # message digest method to use  

    policy = policy_any                         # default policy 

    [ policy_any ] 
    countryName = optional  
    stateOrProvinceName = optional  
    organizationName = optional  
    organizationalUnitName = optional  
    localityName = optional  
    commonName = supplied  
    emailAddress = optional

配置Nginx

    ssl_client_certificate /root/tmp/ca/ca.crt; # move to nginx etc dir.
    ssl_verify_client on;

重启Nginx

   systemctl reload nginx

服务器证书

自己服务器已经是HTTPS,不需要再准备证书,如果需要自己签发,也很简单,可参照客户端证书准备过程。

客户端证书

pwd: /root/tmp

第一步,生成客户端密钥

    openssl genrsa 2048 > client.key

第二步,生成证书请求文件

    openssl req -new -key client.key -out client.csr
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [XX]:CN
    State or Province Name (full name) []:GD
    Locality Name (eg, city) [Default City]:SZ
    Organization Name (eg, company) [Default Company Ltd]:XX 
    Organizational Unit Name (eg, section) []:amsimple
    Common Name (eg, your name or your server's hostname) []:amsimple
    Email Address []:shasharoman@gmail.com

    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:
    An optional company name []:

第三步,签发证书

    openssl ca -in client.csr -cert ca/ca.crt -keyfile ca/ca.key -out client.crt -config ca/conf/openssl.conf
    Using configuration from ca/conf/openssl.conf
    Check that the request matches the signature
    Signature ok
    The Subject's Distinguished Name is as follows
    countryName           :PRINTABLE:'CN'
    stateOrProvinceName   :ASN.1 12:'GD'
    localityName          :ASN.1 12:'SZ'
    organizationName      :ASN.1 12:'XX'
    organizationalUnitName:ASN.1 12:'amsimple'
    commonName            :ASN.1 12:'amsimple'
    emailAddress          :IA5STRING:'shasharoman@gmail.com'
    Certificate is to be certified until Mar  2 07:39:43 2019 GMT (365 days)
    Sign the certificate? [y/n]:y


    1 out of 1 certificate requests certified, commit? [y/n]y
    Write out database with 1 new entries
    Data Base Updated

第四步,转PKCS12

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

第四步OK后,在本机导入P12证书,访问页面,需要选择客户端证书,选择所导入的证书即可。

Tips:

Mac下面导入PKCS12证书时,密码不能为空,所以转PKCS12时,记得输入密码