对于 NGINX 的 HTTPS 配置,一般状况下咱们只须要实现服务端认证就行,由于浏览器内置了一些受信任的证书颁发机构(CA),服务器端只须要拿到这些机构颁发的证书并配置好,浏览器会本身校验证书的可用性并经过 SSL 进行通信加密。css
但特殊状况下咱们也须要对客户端进行验证,只有受信任的客户端才能使用服务接口,此时咱们就须要启用双向认证来达到这个目的,只有 当客户端请求带了可用的证书才能调通服务端接口 。html
CA 是权威机构才能作的,而且若是该机构达不到安全标准就会被浏览器厂商“封杀”,前不久的沃通、StartSSL 就被 Mozilla、Chrome 封杀了。不过这并不影响咱们进行双向认证配置,由于咱们是自建 CA 的..nginx
为了方便,咱们就在 NGINX 的目录下进行证书相关制做:浏览器
cd /etc/nginx mkdir ssl cd ssl
制做 CA 私钥安全
openssl genrsa -out ca.key 2048
制做 CA 根证书(公钥)bash
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt
注意:服务器
Common Name
能够随意填写.
吧制做服务端私钥curl
openssl genrsa -out server.pem 1024 openssl rsa -in server.pem -out server.key
生成签发请求ui
openssl req -new -key server.pem -out server.csr
注意:加密
Common Name
得填写为访问服务时的域名,这里咱们用 usb.dev
下面 NGINX 配置会用到.
吧(为了和 CA 根证书匹配)用 CA 签发
openssl x509 -req -sha256 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -out server.crt
和服务端证书相似:
注意:
Common Name
能够随意填写.
吧(为了和 CA 根证书匹配)至此须要的证书都弄好了,咱们能够开始配置 NGINX 了。
server { listen 443 ssl; server_name usb.dev; access_log off; ssl on; ssl_certificate /etc/nginx/ssl/server.crt; ssl_certificate_key /etc/nginx/ssl/server.key; ssl_client_certificate /etc/nginx/ssl/ca.crt; ssl_verify_client on; location / { proxy_pass http://backend$request_uri; } }
其中 ssl_client_certificate /etc/nginx/ssl/ca.crt;
的意思是使用 CA 证书来验证请求带的客户端证书是不是该 CA 签发的。
配置好后就就从新加载 NGINX 吧:
service nginx reload
好了,下面咱们能够开始验证了。
验证过程能够选择在其余机器或是本机,为了可以解析 usb.dev
,还须要配置一下 /etc/hosts
:
127.0.0.1 usb.dev
若是用浏览器验证,须要把客户端证书导出成 p12 格式的,这里略过。咱们重点是经过 curl 进行验证:
curl --insecure --key client.key --cert client.crt 'https://usb.dev'
其中 --insecure
是忽略自建 CA 的非权威性。若是你验证正常那说明你运气好,由于这里有个 深坑:某些版本的 curl 会报错:
<html> <head><title>400 No required SSL certificate was sent</title></head> <body bgcolor="white"> <center><h1>400 Bad Request</h1></center> <center>No required SSL certificate was sent</center> <hr><center>nginx/1.11.0</center> </body> </html>
这些报错版本的 curl 竟然要严格要求 --cert
实参的路径要彻底正确,好比当前目录下面要用 --cert ./client.crt
,用 --cert client.crt
是错误的。爬坑过程是启用了 -v
参数来观察完整的过程,发现其中有一条告警: