使用NGINX做双向认证的网站,访问时需要客户端安装有证书才可继续访问。可用于仅限特定用户群的网站,例如企业内部的业务管理系统,可提高系统安全性,阻止未授权用户访问。
在下述方法中,客户端证书采用自制(可节约成本),服务器端证书可自制也可购买,两者不必同一个CA,建议购买(有免费的域名证书)因为自制的浏览器会出现不信任标志。
自制证书使用openssl工具,使用前需要先安装.
制作证书 CA证书 1 2 3 4 5 openssl genrsa -out ca.key 2048 openssl req -new -x509 -days 3650 -key ca.key -out ca.crt
服务器证书 如果使用购买的服务器证书,可忽略此部分
1 2 3 4 5 6 7 8 9 10 openssl genrsa -out server.key 2048 openssl rsa -in server.key -out server.public.key openssl req -new -key server.public.key -out server.csr openssl x509 -req -sha256 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -out server.crt
客户端浏览器证书 1 2 3 4 5 6 7 8 9 10 11 12 13 openssl genrsa -out client.key 2048 openssl rsa -in client.key -out client.public.key openssl req -new -key client.public.key -out client.csr openssl x509 -req -sha256 -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 365 -out client.crt openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.pfx
生成CSR环节会要求输入一些信息,如下:
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:SH
Locality Name (eg, city) []:SH
Organization Name (eg, company) [Internet Widgits Pty Ltd]:公司名(英文字母)
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:这里要输入你的主机名域名
Email Address []:someone@yourcompany.com
下面这段需要输入的两项保留为空(直接按回车)即可。
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
更改nginx配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 server { listen 443; server_name admin.devmgr.cn; ssl on; # 服务器端证书配置,具体参数请根据证书发行方提供的帮助配置 ssl_certificate /etc/nginx/certs/1_admin.devmgr.cn_bundle.crt; ssl_certificate_key /etc/nginx/certs/2_admin.devmgr.cn.key; ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; ssl_prefer_server_ciphers on; # 下面是配置客户端认证,需要配置使用的CA证书 ssl_client_certificate /etc/nginx/certs/ca.crt; ssl_verify_client on; root /var/www/admin; }
在后端程序内获取客户端证书信息 NGINX会把客户端证书做成内置变量,可通过proxy_set_header传递给应用,在应用内获取request header即可得到证书对应的信息。
1 2 3 4 5 6 7 8 location /webapp { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 把客户端证书的主题信息作为request header (Client-Cert)传递给应用 proxy_set_header Client-Cert $ssl_client_s_dn; }
除了 $ssl_client_s_dn 外,NGINX还提供很多内置变量对应证书的其他部分内容,想起请参考 nginx的ngx_http_ssl_module 模块文档。使用时需要注意nginx版本是否支持对应的变量。