一   nginx作为客户端与上游的SSL/TLS握手

理解上: nginx作为'客户端',此时类似'浏览器'的角色,发请求建立连接

nginx作为server端与下游进行SSL/TLS握手

①  nginx与后端选择什么样的协议

1)如果'nginx与上游'是局域网内,一般通过'http'建立请求,不需要进行'tls'加密

2)nginx与上游需要'ssl/tls握手'场景 -->  '正向代理

   备注: 一般上游服务是'走公网的合作方'的服务,且对'安全级别'要求较高 -->'CDN'之类的

nginx作为反向代理,当后端为https时的一些细节和原理

(1)nginx作为客户端转发https请求时

①  proxy_ssl_ciphers

说明: nginx作为'客户端'自己支持的'加密套件'

备注: 通过'nginx -V'观察'openssl'版本,默认nginx使用'openssl'库提供的'加密套件'

nginx 强制ssl nginx ssl proxy_ssl

②  proxy_ssl_server_name

思考:一个ip绑定'多个域名'很常见,为什么'使用off','默认不启用 SNI'呢?

补充: 只有sslv3和tls1.0'以后'才支持'SNI'

+++++++++++++  "设置off  没有启动SNI现象"  +++++++++++++ 

现象:由于没启用SNI,TLS握手的时候,'上游服务器不知道'用那个域名的证书便使用了'默认'证书返回

nginx 强制ssl nginx ssl proxy_nginx 强制ssl_02

说明:当'on'时,在ssl握手时默认'$proxy_host'传给上游服务器,以便'上游服务器'知道用哪个证书

SNI的理解

③  proxy_ssl_certificate

说明: nginx作为客户端自己的'客户端证书'

nginx 强制ssl nginx ssl proxy_ssl_03

④  proxy_ssl_certificate_key

说明: nginx作为'客户端'自己的'私钥'

nginx 强制ssl nginx ssl proxy_nginx 强制ssl_04

⑤  proxy_ssl_password_file

nginx 强制ssl nginx ssl proxy_nginx_05

⑥  proxy_ssl_protocols

说明: nginx作为'客户端',发起请求进行'SSL'握手的'TLS'版本

nginx 强制ssl nginx ssl proxy_nginx_06

⑦  proxy_ssl_session_reuse 

nginx 强制ssl nginx ssl proxy_nginx 强制ssl_07

nginx作为客户端校验上游服务器的证书

说明: nginx一般'不校验'上游'证书'的有效性

①  proxy_ssl_verify

1)'proxy_ssl_server_name off没有启用SNI',导致TLS握手时候'上游'可能返回一个'默认'证书

2) 虽然'证书返回的不对',但'请求不受影响',HTTPS请求上游时'默认不验证'上游服务器返回的证书

nginx 强制ssl nginx ssl proxy_nginx_08

②  proxy_ssl_verify_depth 

nginx 强制ssl nginx ssl proxy_http_09

相关参考

③  proxy_ssl_certificate

nginx 强制ssl nginx ssl proxy_nginx_10

④   proxy_ssl_trusted_certificate

说明: 用这个'签发证书的CA'去校验'上游'服务器返回的'证书'是否是该'CA'签发的

nginx 强制ssl nginx ssl proxy_nginx_11

⑤  proxy_ssl_name

1)'proxy_ssl_server_name on 启用SNI',默认使TLS与'上游'握手时候插入一个'SNI'

2)默认值是'$proxy_host',可以自定义'插入的SNI'

nginx 强制ssl nginx ssl proxy_客户端_12

nginx 强制ssl nginx ssl proxy_客户端_13

配置CDN的回源SNI 

(3)小结

nginx 强制ssl nginx ssl proxy_ssl_14

nginx 强制ssl nginx ssl proxy_nginx 强制ssl_15

二     nginx作为客户端与上游ssl握手报错汇总

(1)案例1

根因: nginx作为客户端没有开启'SNI',导致与'上游'ssl'握手失败'

①  客户端现象

nginx 强制ssl nginx ssl proxy_http_16

②  nginx记录日志

细节: nginx如果作为'代理服务器'在向'上游'转发请求时报错,'access和error'都有日志记录

access.log:主要表现'upstream_addr是-'表示'没有选中'server,同时status状态码'502'

error.log: 

   关键字: 'SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version'

nginx 强制ssl nginx ssl proxy_客户端_17

③  根因分析

nginx 强制ssl nginx ssl proxy_http_18

④  解决策略

server {

  server_name  www.wzj.com;

  resolver 8.8.8.8 valid=60s;

  set $name www.wzj.com;

  proxy_pass https://${name};

  # 开启'SNI',发送'Client Hello',插入'proxy_ssl_name'指令的值,默认是'$proxy_host'

  proxy_ssl_server_name on;
}

(2)案例2

场景:  nginx作为'反向代理'的时候,后端只支持http协议,但是却配置了https

根因: 上游不支持'https',但是nginx在'proxy_pass'中配置了'https'协议

关键字:'unknown protocol'

nginx 强制ssl nginx ssl proxy_ssl_19

(3)案例3

①  上游没有返回Server Hello

案例解读

1)现象: 三次'握手'成功后,nginx发送了'Client hello'报文,但'上游'却没有回Server hello

 '表现'形式: curl -kv  https://www.wzj.com

2)最终导致'超时',连接'断开'

解读: 三次握手成功了说明'网络、防火墙'是没有问题的,一般是通信链路中间有'代理'服务做转换导致

http和https配置相同端口导致 

(4)案例4

关键字: 'wrong version number'

关联'指令': proxy_ssl_session_reuse on

nginx 强制ssl nginx ssl proxy_http_20

nginx 强制ssl nginx ssl proxy_nginx 强制ssl_21