之前的方式只是实现1:1的模式,昨天同事继续实现了n:1的模式,这里我再整理记录下。

由于nginx的ssl_client_certificate参数只能指定一个客户端公钥,如果增加一个客户端进行通信就要重新配一个server。

n:1的模式是通过CA的级联证书模式实现的,首先自己生成一套CA根级证书,再借助其生成二级证书作为client证书。

此时client私钥签名不仅可以通过对应的client公钥验证,还可通过根证书的公钥进行验证。

看到这里应该豁然开朗了吧,下面简单介绍下具体怎么操作:

1 准备工作

1.1 openssl目录准备

一般情况下openssl的配置文件都在这个目录/etc/pki/tls,so:

mkdir /etc/pki/ca_linvo

cd /etc/pki/ca_linvo

mkdir root server client newcerts

echo 01 > serial

echo 01 > crlnumber

touch index.txt

1.2 openssl配置准备

 

修改openssl配置

vi /etc/pki/tls/openssl.cnf

找到这句注释掉,替换为下面那句

#default_ca      = CA_default

default_ca      = CA_linvo

[ CA_default ]整个部分拷贝一份,改成上面的名字[ CA_linvo ]

修改里面的如下参数:

dir = /etc/pki/ca_linvo

certificate = $dir/root/ca.crt

private_key = $dir/root/ca.key

保存退出

2 创建CA根级证书

生成key: openssl genrsa -out /etc/pki/ca_linvo/root/ca.key

生成csr:openssl req -new -key /etc/pki/ca_linvo/root/ca.key -out /etc/pki/ca_linvo/root/ca.csr

生成crt:openssl x509 -req -days 3650 -in /etc/pki/ca_linvo/root/ca.csr -signkey /etc/pki/ca_linvo/root/ca.key -out /etc/pki/ca_linvo/root/ca.crt

生成crl:openssl ca -gencrl -out /etc/pki/ca_linvo/root/ca.crl -crldays 7

生成的根级证书文件都在/etc/pki/ca_linvo/root/目录下

注意:创建证书时,建议证书密码设置长度>=6位,因为java的keytool工具貌似对它有要求。

3 创建server证书

生成key:openssl genrsa -out /etc/pki/ca_linvo/server/server.key

生成csr:openssl req -new -key /etc/pki/ca_linvo/server/server.key -out /etc/pki/ca_linvo/server/server.csr

生成crt:openssl ca -in /etc/pki/ca_linvo/server/server.csr -cert /etc/pki/ca_linvo/root/ca.crt -keyfile /etc/pki/ca_linvo/root/ca.key -out /etc/pki/ca_linvo/server/server.crt -days 3650

说明:

1、这里生成的crt是刚才ca根级证书下的级联证书,其实server证书主要用于配置正常单向的https,所以不使用级联模式也可以:

openssl rsa -in /etc/pki/ca_linvo/server/server.key -out /etc/pki/ca_linvo/server/server.key
openssl x509 -req -in /etc/pki/ca_linvo/server/server.csr -signkey /etc/pki/ca_linvo/server/server.key -out /etc/pki/ca_linvo/server/server.crt -days 3650

2、-days 参数可根据需要设置证书的有效期,例如默认365天

4 创建client证书

生成key:openssl genrsa -des3 -out /etc/pki/ca_linvo/client/client.key 1024

生成csr:openssl req -new -key /etc/pki/ca_linvo/client/client.key -out /etc/pki/ca_linvo/client/client.csr

生成crt:openssl ca -in /etc/pki/ca_linvo/client/client.csr -cert /etc/pki/ca_linvo/root/ca.crt -keyfile /etc/pki/ca_linvo/root/ca.key -out /etc/pki/ca_linvo/client/client.crt -days 3650

说明:

1、这里就必须使用级联证书,并且可以重复该步骤,创建多套client证书

2、生成crt时可能会遇到如下报错:

openssl TXT_DB error number 2 failed to update database

参照这里进行操作。

我使用的是方法一,即将index.txt.attrunique_subject = no

5 配置nginx

这里只列出server段的关键部分:

ssl_certificate  /etc/pki/ca_linvo/server/server.crt;#server公钥
ssl_certificate_key  /etc/pki/ca_linvo/server/server.key;#server私钥
ssl_client_certificate   /etc/pki/ca_linvo/root/ca.crt;#根级证书公钥,用于验证各个二级client
ssl_verify_client on;

重启Nginx

6 测试

6.1 浏览器测试

由于是双向认证,直接通过浏览器访问https地址是被告知400 Bad Request(No required SSL certificate was sent)的,需要在本机安装client证书。

windows上安装的证书需要pfx格式,也叫p12格式,生成方式如下:

openssl pkcs12 -export -inkey /etc/pki/ca_linvo/client/client.key -in /etc/pki/ca_linvo/client/client.crt -out /etc/pki/ca_linvo/client/client.pfx 

然后考到windows中双击即可进行安装,安装时会提示输入生成证书时设置的密码。

安装成功后,重启浏览器输入网址访问,浏览器可能会提示你选择证书,选择刚才安装的那个证书即可。

此时有些浏览器会提示用户该证书不受信任,地址不安全之类,这是因为我们的server证书是我们自己颁发的,而非真正的权威CA机构颁布(通常很贵哦~),忽略它既可。



针对以上脚本中证书的格式转化和生成

根证书ca.pem生成

openssl x509 -in ca.crt   -out ca.pem  -outform PEM

分离p12文件 yeak@md.com.my.p12分离为key.pem和cert.pem

openssl pkcs12 -in client.pfx -out key.pem -nodes -nocerts

openssl pkcs12 -in client.pfx -out cert.pem -nodes -nokeys