目前遇到一个项目有安全性要求,要求只有个别用户有权限访问。本着能用配置解决就绝不用代码解决的原则,在Nginx上做一下限制和修改即可。
这种需求其实实现方式很多,经过综合评估考虑,觉得SSL双向认证方案对用户使用最简单,遂决定用此方案。
注: 本方案在Ubuntu Server 16.04 LTS实施,其他操作系统请酌情修改SSL双向认证绝大多数SSL应用都以单向认证为主,即客户端只要信任服务端,就可以使用服务端的公钥加密后向服务端发起请求,由服务端的私钥解密之后获得请求数据。
如果这个过程反过来,让服务端信任客户端,服务端使用客户端的公钥加密之后将数据返回给客户端,其实也是可以做到的,原理和实现跟单向认证都差不多。
服务端信任客户端的操作往往也会伴随着客户端认证服务端的过程,所以让服务端信任客户端的SSL认证方式往往也被称为SSL双向认证,并且要配置SSL双向认证必须先开启服务端SSL,先配置客户端信任服务端。
Nginx的SSL双向认证配置第一步 开启https访问根据理论知识,我们必须先开启Nginx的SSL配置,即启用https。这个过程较为简单,目前有let s encrypt这种免费的证书方案,再也不用发愁自己搭建CA自签了。申请免费证书的过程略过,直接贴启用https的配置:
server { listen 80; listen 443 ssl http2; server_name example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # 只有Nginx = 1.13.0 版本才支持TLSv1.3协议 # ssl_protocols TLSv1.3; # Nginx低于1.13.0版本用这个配置 ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_dhparam dhparam.pem; # openssl dhparam -out /etc/nginx/dhparam.pem 4096 ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH ssl_ecdh_curve secp384r1; # Requires nginx = 1.1.0 ssl_session_timeout 10m; ssl_session_cache shared:SSL:10m; ssl_session_tickets off; # Requires nginx = 1.5.9 ssl_stapling on; # Requires nginx = 1.3.7 ssl_stapling_verify on; # Requires nginx = 1.3.7 resolver 223.5.5.5 114.114.114.114 valid=300s; resolver_timeout 5s; # 启用HSTS的配置,如果你的域名下还有非标准端口访问的http应用,请勿启用HSTS # add_header Strict-Transport-Security max-age=63072000; includeSubDomains; preload # 下面这个配置会拒绝Frame标签内容,请确认你的网站没有frame / iframe add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection mode=block # 为了let s encrypt续期用,不用let s encrypt不需要这个location location /.well-known { root /usr/share/nginx/html; ... SNIP ... # 强制http跳转为https if ($scheme != https ) { return 301 https://$http_host$request_uri;}以上那一大堆ssl的配置参考来自于: https://cipherli.st/ 加强SSL的安全性配置
特别注意最后的强制https跳转,我们的目的是SSL双向认证,不走https无任何意义,所以必须强制跳转https。
第二步 生成客户端证书并签证(脚本)这个过程详细描述的文章太多了,这里就不啰嗦介绍openssl和签证过程了,本篇内容是快速生成双向认证配置的证书,所以直接贴脚本就行了,命令都是参考互联网上各种openssl双向配置文档,在此基础之上进行了命令上的简化与非交互式的支持。
整个目录结构如图:
# tree /etc/nginx/ssl_certs//etc/nginx/ssl_certs/├── create_ca_cert.sh├── create_client_cert.sh├── revoke_cert.sh0 directories, 3 files
自行创建/etc/nginx/ssl_certs/,放入三个脚本,分别用于生成CA证书以及CA目录(create_ca_cert.sh脚本的作用,只有第一次需要运行),创建客户端证书,并用CA证书签证(create_client_cert.sh脚本的作用,必须先生成CA证书),revoke_cert.sh脚本用于吊销证书,需要收回权限的时候可以使用。
每个脚本内容如下:
create_ca_cert.sh
#!/bin/bash -e# 创建CA根证书# 非交互式方式创建以下内容:# 国家名(2个字母的代号)ST=ShannxiL=Xian# 公司名O=My Company# 组织或部门名OU=技术部# 服务器FQDN或颁发者名CN=www.example.com# 邮箱地址emailAddress=admin@example.commkdir -p ./demoCA/{private,newcerts}touch ./demoCA/index.txt[ ! -f ./demoCA/seria ] echo 01 ./demoCA/serial[ ! -f ./demoCA/crlnumber ] echo 01 ./demoCA/crlnumber[ ! -f ./demoCA/cacert.pem ] openssl req -utf8 -new -x509 -days 36500 -newkey rsa:2048 -nodes -keyout ./demoCA/private/cakey.pem -out ./demoCA/cacert.pem -subj /C=${C}/ST=${ST}/L=${L}/O=${O}/OU=${OU}/CN=${CN}/emailAddress=${emailAddress} [ ! -f ./demoCA/private/ca.crl ] openssl ca -crldays 36500 -gencrl -out ./demoCA/private/ca.crl郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。
新闻热点
疑难解答
图片精选