源起
服务器已经跑起来很久了,但是有需求要限制客户端使用我们服务,一同事说到了SSL双向认证的问题,之前没有玩过,所以查了一些资料。后来想了下,以前其实也碰到过,就是银行和支付宝的证书认证嘛,通过证书对帐号进行认证。还有一些登录的时候不填帐号,只填密码,其实就是在客户证书来当用户名嘛。这个在Nginx双向认证的时候就可以解决,Nginx收到证书信息,然后反向代理到后面服务的时候,可以在头信息里面加一点东西,就可以解决客户登录的时候的帐号填写问题了。当然还可以又填用户名,又使用证书,然后核对证书的用户名和用户填的用户名是否一致,不致的情况下,可以直接吊销证书等等,可以做的事情就很多了。简单记下之前配置的过程吧。
准备工作
可以编辑openssl.cnf,设置一部分默认值,比如国别、组织、机构啊什么的。CentOS在/etc/pki/tls
目录下面,Gentoo在/etc/ssl
目录下面。因为服务是CentOS,下面默认是在CentOS下操作。如果非root用户操作,做部分修改就行。
1 2 3 4 5
| cd /etc/pki/CA
touch index.txt
echo '00' > serial
|
生成CA密钥和证书
自已充当CA认证机构(一般为第三方权威机构),需要生成一个CA的密钥和证书,用于对其它用户的证书请求进行认证。
1 2
| openssl genrsa -des3 -out ca-key.pem 4096 openssl req -new -x509 -days 3650 -key ca-key.pem -out ca-cert.pem
|
生成自签名服务器证书(非必需)
如果可以,最好去第三方权威机构申请证书(非WoSign),或用letsencrypt的证书。实在不行,就像我们这样,自已生成证书算球的,就可以走下面的流程了。
1 2 3 4 5 6 7
| openssl genrsa -des3 -out server-key.pem 1024
openssl rsa -in server-key.pem -out server-key.key
openssl req -new -key server-key.pem -out server-req.csr
openssl ca -policy policy_anything -days 3650 -CA ca-cert.pem -CAkey ca-key.pem -in server-req.csr -out server-cert.pem
|
生成客户证书
与生成服务器证书基本一致,对于CA而言,是一样的。申请过来,进行认证。
1 2 3 4 5 6 7 8
| openssl genrsa -des3 -out client-key.pem 1024
openssl req -new -key client-key.pem -out client-req.csr
openssl ca -policy policy_anything -days 3650 -CA ca-cert.pem -CAkey ca-key.pem -in client-req.csr -out client-cert.pem
openssl pkcs12 -export -clcerts -in client-cert.pem -inkey client-key.pem -out client.p12
|
Nginx配置
/etc/nginx/conf.d/default.conf1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name test.test;
ssl on; ssl_certificate /etc/nginx/ssl/server-cert.pem; ssl_certificate_key /etc/nginx/ssl/server-key.key;
ssl_client_certificate /etc/nginx/ssl/ca-cert.pem; ssl_verify_client optional;
ssl_session_cache shared:SSL:5m; ssl_session_timeout 1h;
ssl_protocols TLSv1.1 TLSv1.2; ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5; ssl_prefer_server_ciphers on;
client_max_body_size 10M;
if ($ssl_client_verify != "SUCCESS") { return 400; } ......
|
参考