HTTPS 双向认证(Mutual TLS authentication)
本文最后更新于:2023年4月25日 晚上
描述
单向认证指浏览器与服务器交互需要对服务器证书进行认证,而双向认证就是服务端对客户端也要进行一次认证,认证的主要条件为:客户端需要有一张客户端证书,而这张客户端证书必须是由服务端指定的 CA
根证书签发的(中间 CA 个人没验证过)。
常规操作
服务端的 Nginx 配置:
1 |
|
配置说明
基础部分
- listen:为监听的端口
- server_name:指定访问该服务的域名
- server_tokens:在错误页和“服务器”响应头字段中启用或禁用nginx版本(有道翻译)点此查看具体细节
- access_log:服务日志路径
- error_log:错误日志路径
证书及验证部分
- ssl_certificate:服务器证书
- ssl_certificate_key:服务器证书私钥
- ssl_client_certificate:服务器验证客户端证书的 CA 证书
- ssl_verify_client:是否开启客户端验证
- ssl_verify_depth:验证深度(如果是中间证书颁发的客户端证书深度至少要写2)
- ssl_prefer_server_ciphers:指定在使用SSLv3和TLS协议时,服务器密码应该优于客户端密码(有道翻译)点此查看具体细节
- ssl_session_tickets:是否可以通过 ssl_session_tickets 恢复 session 会话(有道翻译)点此查看具体细节
- ssl_session_cache:设置存储会话参数的缓存的类型和大小(有道翻译)点此查看具体细节
代理部分
- proxy_http_version:代理 http 协议版本
- proxy_ignore_headers:禁止从代理服务器处理某些响应标头字段(有道翻译)点此查看具体细节
- proxy_hide_header:设置不传递的非默认不传递的字段点此查看具体细节
- proxy_set_header:设置请求头
- proxy_pass:设置代理服务器的协议和地址
跨域设置
- add_header:添加头部信息
- Access-Control-Allow-Origin:访问控制允许来源
- Access-Control-Allow-Credentials:响应头告诉浏览器是否将响应公开给前端JavaScript代码
扩展
Nginx 反向代理作为客户端请求服务端进行双向认证
服务端配置:
1 |
|
坑位总结
- 配置问题:代理作为客户端配置客户端证书的字段是
proxy_ssl_certificate
和proxy_ssl_certificate_key
而不是ssl_certificate
和ssl_certificate_key
,前者是服务器证书而不是作为代理的客户端证书。 proxy_ssl_server_name
这个字段默认是off
,这里要改为on
,后端服务需要代理发送SNI
才能正常工作,如果代理服务器不发送SNI
,会返回 502 错误。即无法正常和后端通信。- 头部信息设置时需要将
Host
改为与proxy_pass
一致,不然会无法响应,一直502
,个人理解:SNI
中的server_name
拿取的是proxy_set_header
中的Host
所以如果Host
默认为请求当前服务器的Host
那么代理到example.com
的服务器server_name
就会有问题,找不到对应的路由,当然这只是个人踩坑的解决方案,原理有问题的话,大家可以自动屏蔽。
参考
HTTPS 双向认证(Mutual TLS authentication)
https://agopher.com/2019/12/09/tech/2019_mutual_tls_authentication/