场景:接着笔记(三)的鉴权,需要先调用第三方服务进行鉴权,第三方对应的浏览器需要导入证书,否则就会报400错误,只有当鉴权成功后才能往下进行反向代理,此处就不强调如何生成证书,如何生成证书可以自行百度,此文关注点在如何配置ssl,以及配置验证浏览器的证书后如何获取浏览器证书的信息。
笔记(一)中介绍的是nginx源码安装,此处介绍个Openresty安装。
Centos7安装Openresty通过yum安装
在 /etc/yum.repos.d/ 下新建 OpenResty.repo 内容
[openresty]
name=Official OpenResty Repository
baseurl=https://copr-be.cloud.fedoraproject.org/results/openresty/openresty/epel-$releasever-$basearch/
skip_if_unavailable=True
gpgcheck=1
gpgkey=https://copr-be.cloud.fedoraproject.org/results/openresty/openresty/pubkey.gpg
enabled=1
enabled_metadata=1
yum install openresty -y
默认会安装到 /usr/local/openresty/ 目录下, 目录下包含了 luajit, lualib, nginx, openssl, pcre, zlib 这些组件。
到此就安装好了,简单吧,比源码安装简单多了。
1、nginx 配置
# HTTPS server
#
server {
listen 443 ssl;
server_name proxy.ztns.com;
ssl on;
# 证书公钥 它会被发送到连接服务器的每个客户端
ssl_certificate /usr/local/openresty/nginx/conf/ssl/proxy.server.crt;
# 私钥是用来解密的
ssl_certificate_key /usr/local/openresty/nginx/conf/ssl/proxy.server.key;
# CA签发机构证书
ssl_client_certificate /usr/local/openresty/nginx/conf/ssl/ca.crt;
# 开启浏览器证书验证
ssl_verify_client on;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
location /esns-server {
access_by_lua_file '
local res = ngx.location.capture("/auth",{method = ngx.HTTP_POST})
if res.status == ngx.HTTP_OK then
return
end
if res.status == ngx.HTTP_FORBIDDEN then
ngx.exit(res.status)
end
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
';
proxy_pass https://192.168.2.1/server;
proxy_read_timeout 150;
}
# 鉴权开始
location /auth {
proxy_pass https://192.168.1.1:8080/authentication;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header Host $host:$proxy_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Original-URI $server_url;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Cookie $http_cookie;
proxy_read_timeout 150;
# 解析证书信息
proxy_set_header X-SSL-Client-S-DN $ssl_client_s_dn;
# 解析状态
proxy_set_header X-CLIENT-VERIFY $ssl_client_verify;
# 关键参数:这个变量开启后,才能自定义错误页面,当后端返回404,nginx拦截错误定义错误页面
proxy_intercept_errors on;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# 后期自定义404页面
error_page 404 /404.html;
location = /404.html {
root html;
}
# 自定义403页面
error_page 403 /403.html;
location = /403.html {
root html;
}
location = /favicon.ico {
log_not_found off;
access_log off;
}
}
2、说明
注:ssl_certificate 和 ssl_certificate_key 的路径就是我们ssl证书申请的路径
ssl_certificate证书其实是个公钥,它会被发送到连接服务器的每个客户端,ssl_certificate_key私钥是用来解密的,所以它的权限要得到保护但nginx的主进程能够读取。当然私钥和证书可以放在一个证书文件中,这种方式也只有公钥证书才发送到client。
ssl_session_timeout 客户端可以重用会话缓存中ssl参数的过期时间,内网系统默认5分钟太短了,可以设成30m即30分钟甚至4h。
ssl_protocols指令用于启动特定的加密协议,nginx在1.1.13和1.0.12版本后默认是ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2,TLSv1.1与TLSv1.2要确保OpenSSL >= 1.0.1 ,SSLv3 现在还有很多地方在用但有不少被攻击的漏洞。
ssl_ciphers选择加密套件,不同的浏览器所支持的套件(和顺序)可能会不同。这里指定的是OpenSSL库能够识别的写法,你可以通过 openssl -v cipher ‘RC4:HIGH:!aNULL:!MD5’(后面是你所指定的套件加密算法) 来看所支持算法。
ssl_prefer_server_ciphers on设置协商加密算法时,优先使用我们服务端的加密套件,而不是客户端浏览器的加密套件。
在鉴权的location中,请求头中会带有如下属性,根据下面的属性就能验证证书信息是否正确。
当浏览器有对应的证书时ssl_client_verify对应的值为SUCCESS, ssl_client_s_dn对应的值就是证书的信息
# 解析证书信息
proxy_set_header X-SSL-Client-S-DN $ssl_client_s_dn;
# 解析状态
proxy_set_header X-CLIENT-VERIFY $ssl_client_verify;
关于上面说到的自定义页面,但是如何在自定义页面上加载nginx本地的图片呢?
location =/404.png{
# 图片存放路径
root html/images;
access_log off;
expires 30d;
}
然后在自定义页面上添加如下内容
<div class="wrap">
<div class="logo">
<img src="https://域名/images/404.png" alt="" />
<p>sorry 您要查看的页面不存在或已删除</p>
</div>
</div>
最后启动nginx,就可以看到效果了。