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时,记得输入密码