nginx(六十七)http_ssl模块 client与nginx的ssl握手

一   HTTPS握手机制

关注点: 'SSL/TLS握手'的细节与nginx'配置指令'的关系

核心: 讲解'客户端(下游)'与作为'server'端的nginx之间的'握手'

最佳实践: 建议在'http块'中通过'include ssl.conf'把共工部分抽离处理

'ssl/tls报错'原因:可能是'客户端'或'服务端(openssl库处理)'的原因 

案例: '单向'和'双向认证'怎么配置?

①  ngx_http_ssl_module模块

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第1张图片

(1)HTTPS单向认证涉及的指令 

②   ssl

解读: 让'nginx'支持'https'

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第2张图片

 高版本使用ssl指令提示信息 

新版本推荐listen指令 

1) 'http1.2' --> listen 443 ssl http2 

2) 'http1.1' --> listen 443 ssl

③  ssl_certificate

说明: 配置'数字证书',一般是'代理CA'颁发的数字证书

了解: '数字证书'的内容 -->'服务端的公钥'、'证书的有效期'、'证书的颁发机构'等

补充:  了解证书的'格式' --> 常见是'pem、crt、p12'

附加1: 了解'nginx版本'与'openssl版本'的适配问题、'nginx高版本'支持'变量形式'

附加2: file的'相对(nginx.conf所在的路径)'和'绝对'路径

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第3张图片

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第4张图片

将中间CA的证书合并到主证书中

④  ssl_certificate_key

说明: 一般是'CA机构'颁发的'私钥文件','不能'泄露

注意: 文件'权限',保证'nginx的master进程'能够读取

补充: 私钥是'解用公钥加密的对称(会话)密钥'的,进而通过'会话密钥'来解'加密的data数据'

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第5张图片

⑤  ssl_ciphers

常见'报错'场景: 浏览器支持的加密套件'nginx并没有'配置,,所以握手失败

细节:多个算法用':'分隔,'ALL'表示全部算法,'!'表示'不启用'该算法,'+'将该算法排到最后面去

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第6张图片

1)不同'ssl/tls'版本支持的'加密套件'不同,'加密套件的安全性'也不同

2)加密套件一般'由多个'组成,在'双方协商'的'时候'会选取'server端'匹配上的'第一个'加密套件

 默认值的含义、官网参考

 openssl ciphers使用案例

 浏览器支持的加密套件 nginx并没有配置 所以握手失败,导致SSL握手报错

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第7张图片

源码: openssl的加密套件在's3_lib.c'的'ssl3_ciphers数组'中定义

重点: openssl  ciphers -v 'nginx中ssl_ciphers指令的配置值' 

类似: openssl ciphers 'MD5' -v|column -t

场景: 查看nginx中到底支持'哪些'加密套件 

--> 备注:'不准确',因为'nginx'和'操作系统'使用openssl版本可能'不一致'

查看openssl支持加密方式 

最佳实践: 'HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4:!RSA'

细节点:  没有'CBC'、'RSA'、'CAMELLIA'

注意: nginx要配置合适的'ssl版本协议'

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第8张图片

++++++++++++++  "查看服务端支持的加密套件"  ++++++++++++++

1) nmap --script ssl-cert,ssl-enum-ciphers -p 'port' 'ip|域名'

2) openssl s_client -connect 'ip|域名:port'

细节点: 必须显示指定'port'

⑥  ssl_password_file

entropy_avail熵不足(小于1000)导致证书加解密失败,需要通过haveged程序补充熵池

1)如果'私钥'之前加密过,需要指定'私钥'的解密'密码';如果没有'加密',则不需要配置该指令

   备注:为了'自动(非交互)'的执行

2)解'私钥'的密码不建议是'明文'的

3)生产建议: 在'reload'的时候,通过'工具'动态生成'解密证书'的'密码'

4)细节点:如果'所有域名证书的私钥'密码都一样,建议在'http块'配置;个性化的话在'server'配置

备注: 一般在'ssl'目录下放置'crt、passwd、key'后缀文件,前缀为'域名'

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第9张图片

nginx多个server怎么配置ssl_nginx多密码SSL证书管理

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第10张图片

  

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第11张图片

⑦  ssl_protocols

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第12张图片

1)ssl_protocols'不具有兼容性',要支持'多个协议'需要'全部'写上

  举例: 如果'client'说自己支持'TLSv1.2',但是'nginx'没有配置'TLSv1.2'则'协商不通过'

2)支持的'加密套件'也与'ssl/tls'版本有关

3)如何支持'TLSv1.3'? -->'nginx和openssl'的版本

备注: 主流的是'TLSv1.2'

说明: TLS v1.0'以上'的版本是比较'安全'的,最好是'弃用SSLv3以下'的版本

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第13张图片

(2)HTTPS双向认证的指令

双向认证中'server到client'认证目的: 服务端只允许'特定的客户'才能访问

场景: 一般'client证书'是由'自定的CA证书'签发的

①   ssl_verify_client

作用: 检验'client端'证书,是一个'开关'选项

特点: 常用'on'代表'强制'启用客户端认证;非法客户端'无证书、证书不可信'都会返回'400'

细节: 如果是'浏览器'必须提前导入'证书'、如果是'命令行工具(curl)'携带参数

curl命令进行单向和双向认证 

浏览器如何导入客户端证书

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第14张图片

②   ssl_trusted_certificate

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第15张图片

③   ssl_verify_depth

解读: 

  1)验证'客户端证书'的'有效性和合法性','目标是'需要层层'回溯到CA根证书'

  2)但是回溯'多少次'由ssl_verify_depth决定

细节

  1)当'ssl_verify_depth 1'时,回溯层数为0,即'任何中间证书'都不会通过验证,除非是'根'证书

  2)如果'中间证书的深度'要'小于'ssl_verify_depth的值,才会'验证'通过

ssl_verify_depth 

④   ssl_client_certificate

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第16张图片

1)ssl_client_certificate就是'客户端证书的CA证书'了,代表'此CA签发'的证书都是'可信'的

+++++++ 'ssl_trusted_certificate' 和 'ssl_client_certificate'对比 +++++++

 1)这两个配置'效果都是一样'的

 2)唯一的'区别'是 ssl_client_certificate 会将'信任的 CA 列表'发送给'客户端'

 3)二者是'效率'和'安全性'的对比

 4)'ssl_client_certificate'优先级更高

备注1: 客户端如果'有很多证书',让客户端'一个一个去尝试'哪一个能建连是没有'意义并且很浪费'的

备注2: 'ssl_trusted_certificate'更安全,避免了'CA根证书'的泄露

⑤  ssl_crl 

细节:

 1)ssl_crl这个配置,代表Nginx会读取一个'CRL(Certificate Revoke List)文件'

 2) 之前说过,可能会有收回用户权限的需求,因此我们必须有吊销证书的功能

 3) 产生一个CRL文件'让Nginx知道'哪些证书被吊销了即可

注意: 

 1) Nginx配置都是'静态'的,读取配置文件之后都会'加载到内存'中,即使文件内容变化也不会重新读取

 2) 因此当CRL文件发生变更之后,Nginx并'不能意识'到有新的证书被吊销了

 3) 所以必须使用reload指令让Nginx'重新读取'配置文件:

    --> service nginx reload或nginx -s reload

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第17张图片

(3)TLS/SSL优化握手性能 

①  ssl_session_cache

作用: 开启了TLS'缓存复用'

机制: 在缓存中查找对应的'Session ID',如果存在则'接受并恢复'会话,返回'相同'的Session ID

优化的地方: 减少'TLS'握手,少了一次'RTT'的往返时间

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第18张图片

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第19张图片

nginx开启SSL会话复用,能提升多少性能?

②  ssl_session_timeout

③  ssl_session_tickets  ssl_session_ticket_key

说明: 使用'会话票证'tickets复用session

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第20张图片

 (4)不太常用的指令

①  ssl_reject_handshake

1)自 '1.19.4 起',nginx 支持 ssl_reject_handshake 参数

2)设置为'on',当客户端'传过来的SNI'与'已配置的 server name'都不匹配时,会'拒绝' SSL 握手

3)访问'客户端(浏览器)'会报 SSL_ERROR_UNRECOGNIZED_NAME_ALERT

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第21张图片

应用场景  nginx设置严格域名校验

②  ssl_prefer_server_ciphers

1)ssl_prefer_server_ciphers 'on|off' 作用, 是否'由服务器决定'采用'哪种'加密算法

备注: 默认是'off',推荐设置为'on'

特点:决定使用'交集中'客户端的第一个加密套件,还是'服务端'加密套件'列表'的第一个,推荐服务端

2)如果ssl协议'支持tlsv1 tls1.1'这种'老'协议,设置为 'on' ,并配合ssl_ciphers使用

3)如果ssl协议'只支持tlsv1.2 tlsv1.3''新'协议,设置为 off ,因为新协议'不再采纳'此参数

4)当为on时,在使用'SSLv3和TLS协议'时,服务器加密算法将'优于'客户端加密算法

③  ssl_crl

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第22张图片

常见: 有人'泄露'证书的私钥,'CA机构会吊销证书',使证书在'到期日期之前'无效

生效: 'reload | restart'才能让nginx'重新加载CRL',这样'被吊销的证书'将无法访问网站了

SSL证书吊销列表 CRL

④  ssl_buffer_size

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第23张图片

⑤  ssl_conf_command

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第24张图片

SSL_CONF_cmd查找

⑥  ssl_ocsp    ssl_ocsp_cache    ssl_ocsp_responder

说明: '了解'即可

什么是OCSP  OCSP的调试

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第25张图片

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第26张图片

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第27张图片

⑦  ssl_stapling  ssl_stapling_file  ssl_stapling_responder  ssl_stapling_verify

OCSP stapling配置

⑧  ssl_early_data

说明: 是'TLSv1.3'的特性

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第28张图片

⑨  ssl_ecdh_curve

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第29张图片

 ⑩  HSTS强制浏览器使用https

(5)ssl模块提供的ssl/tls握手相关变量  重点

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第30张图片

1) '重点'掌握'$ssl_cipher'、'$ssl_ciphers'、'$ssl_protocol'、'$ssl_server_name'

   '$ssl_ciphers': '查看客户端支持的加密套件',一般是'Chrome浏览器'

   '$ssl_server_name':与'SNI'强相关

   '$ssl_cipher': '客户端和服务端'最终协商的'加密套件'

2) 免去'tcpdump'部分抓包分析的痛苦

3) 注意'ssl变量'使用的'注意'事项 --> "nginx和openssl"的版本

4) 学会从'ssl相关的变量'挖掘'隐含'信息

5) 需求:session有没有复用?  --> "两个综合判断"

  $ssl_session_id

  $ssl_session_reused

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第31张图片

(6)案例讲解

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第32张图片

(7)errors  重点

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第33张图片

二   nginx ssl握手报错 汇总

①   排查思路

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第34张图片

②  客户端不支持SNI导致报错

③  双向认证校验客户端证书的CA配置错误

关键字: 'certificate not trusted'

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第35张图片

④   不支持客户端的加密套件

关键字:error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:'no shared cipher'

说明:nginx作为服务端'没有'客户端支持的'加密算法套件',导致'SSL'握手报错

⑤  相关参考

关键字:ssl3_'get_client_key_exchange':EC lib) while SSL handshaking

⑥  证书格式有误

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第36张图片

⑦   握手超时

关键字: (110:'Connection timed out') while SSL handshaking)

⑧  证书编码格式

关键字:'no start line'

 nginx(六十七)http_ssl模块 client与nginx的ssl握手_第37张图片

证书的顺序

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第38张图片

⑨   私钥长度太短 

关键字: SSL_CTX_use_certificate:ee 'key too small'

nginx(六十七)http_ssl模块 client与nginx的ssl握手_第39张图片

⑩  证书格式不对有空格

关键字1:nginx: [emerg] SSL_CTX_use_PrivateKey_file(".key") failed 

关键字2:x509 certificate routines:X509_check_private_key:'key values mismatch'

⑪  后续案例补充

++++++++++"分割线[SSL问题]"++++++++++
 
"SSL_do_handshake() failed" 	SSL'握手失败'
 
'SSL_write() failed (SSL:) while sending to client'
 
'ngx_slab_alloc() failed: no memory in SSL session shared cache'	
 
 ssl_session_cache'大小不够'等原因造成
 
'could not add new SSL session to the session cache while SSL handshaking'

'wrong version number'

'upstream SSL certificate does not match'

'certificate signature failure'

'SSL routines:ssl3_read_bytes:ccs received early' while SSL handshaking

ssl3_get_client_hello:no shared cipher  --> "服务端没有支持的加密套件"

重点: 'ssl'的报错还是从'握手阶段和原理'理解、'偶发'还是'必显'

git的certificate verify failed哪 

nginx-https安全最佳实践

服务器选择算法原则

你可能感兴趣的:(nginx,nginx,ssl,服务器)