概述
一 背景探究驱动
1) curl校验'证书'有效期方式'有误',导致变更'回退' -->"实际证书替换成功"
校验方式: curl -H "Host: www.wzj.com" https://172.25.2.100/check_cert
2)客户端'不支持'SNI["实际版本过低"],导致通过'nginx'转发失败
备注:这里'不再描述'具体的案例,只探究'背后的原理'
二 SNI介绍
(1)SNI产生的背景
(2)SNI的概念
TLS握手的过程
1) 服务器名称指示'Server Name Indication,简称'SNI','是一个'扩展的TLS'计算机联网'协议'
2) 在该协议下,在'握手过程开始时'通过'客户端'告诉它正在连接的服务器的'主机(或虚拟主机)'名称
2) 这允许服务器在'相同的IP地址和TCP端口号'上呈现'多个(不同的)证书'
4) 并且因此允许在相同的IP地址上提供多个安全HTTPS网站'(或其他任何基于TLS的服务)'
备注: 而'不需要'所有这些站点使用'相同'的证书
3)核心过程
[1]、在Client Hello阶段,通过'SNI扩展',将'域名'信息'提前'告诉'Server'端
[2]、服务器根据域名'取得对应的证书返回给客户端'以完成'校验'过程
SNI的发展
二 各种工具对SNI的支持
(1)主流的浏览器 可以理解为客户端工具
(2)curl和wget之类的命令行工具 可以理解为客户端工具
(3)库和编程语言 可以理解为客户端工具
(4)web服务器 可以理解为服务端
三 curl和nginx关于SNI一些细节
已知的问题:curl和jdk'版本过低(客户端不支持SNI)','导致'ssl握手的'SNI'问题
(1)nginx
SNI 在 'TLSv1.2' 开始'得到支持',从 'OpenSSL 0.9.8' 版本开始支持
yum安装'nginx-1.16.1',默认SNI是'开启的'
检查'nginx server端'是否支持SNI扩展协议:'nginx -V'
+++++++++"nginx支持SNI后,每个server_name配置"+++++++++
1)单个主机上'nginx多个证书'的配置,每个'虚拟主机'对应一个
2) 在不同的server上配置'ssl_certificate和ssl_certificate_key'即可
(2)curl
工具版本要求: 'curl 7.18.1' && 'openssl 0.9.8' 可以'支持SNI'
1) curl '7.21.3' 又支持了'–resolve' 参数,可以'直接定位'到IP地址进行访问
2) 对于一个域名'有多个部署节点'的服务来说,这个参数可以'定向的访问某个设备'
curl -H "Host:ww.wzj.com" --resolve ww.wzj.com:443:1.1.1.1 https://ww.wzj.com
+++++++++++'相关参数解读'++++++++++++
'不需要修改'/etc/hosts,curl'直接解析'ip请求域名-->省的测试又得'加本地解析'
四 问题1:证书校验方式有问题
(1)背景:匹配哪个server_name? 也即选哪个虚拟主机?
问题的背景:客户端访问的时候,'nginx'侧总是'莫名其妙'的出现一些'404'的报错?
参考链接
How nginx processes a request
强调1:一定是'端口(不指定端口默认是80)'和'server_name'唯一对应'客户端'的这次请求
强调2:server_name的'匹配'只与请求中的'Host头'有关,与'url中的主机名'无关
++++++++++++++"案例讲解"++++++++++++++
参考链接
(2)深入理解Host请求头
① 浏览器测试
说明:浏览器会自动将'gitlab.wzj.com'填充到'Host字段'中 -->'http1.1'的特性
② curl自定义Host测试
最佳实践:
postman'自定义Host请求头'测试,这种能'清晰'看到'request'和'response'的一系列信息
1)实验环境的准备
2)curl测试
说明:'curl客户端工具'会自动将'gitlab.wzj.com'填充到'Host字段'中
说明:上面写'错'了, 'GET / HTTP/1.1'代指'请求行',对应nginx内置变量'$request'
3)小结
1) 请求必须先到达'nginx',所以'url'中可以是'ip'或者'域名(该域名解析成此ip即可)'
2) server_name中的'域名'不一定要有实际意义,也即'不一定'要能解析、不一定必须得'ping通'
(3) 回归到问题1
1)curl https://www.baidu.com/index.html -v
说明: 在'SSL'握手时,会自动将'www.baidu.com'填充到'扩展'信息中
2) curl -H 'Host:www.baidu.com' https://172.25.2.100/cd
备注: "错误的证书校验方式"
说明:
[1]、会自动将'172.25.2.100'填充到Extension'扩展'信息中
[2]、由于nginx没有匹配'172.25.2.100'的server_name
[3]、会使用默认server_name的证书
--> ('第一个'server_name块或者listen指令中有'default_server'的server_name证书
[4]、但是默认server_name的证书'不是'我们替换的证书,所以与预期'不符'
3) curl --resolve 'www.baidu.com:443:172.25.2.100' https://www.baidu.com/cd
说明:'最佳'实践
++++++++++++"环境准备"++++++++++++
前提条件:
-> 有一个'默认'证书(不指定default_server,用第一个域名作为默认证书)和一个'自定义'域名证书
备注:通过二者的'subject中域名(CN)'来辨析'返回'哪个证书
附加:最好'两个证书的有效期'不一致,这样测试'更明显'
++++++++++++"测试方法"++++++++++++
错误的:curl -H 'www.wzj.com:172.25.2.100' http://172.25.2.100/cert
正确的:curl --resolve www.wzj.com:443:172.25.2.100 https://www.wzj.com/cert
说明:上述是通过'nginx的一个接口'返回一个'证书的有效期'
补充1:--resolve是为了加快'dns解析速度'
补充2:Host头是'SSL握手ok,建立HTTP请求'时,nginx 确定哪个server块处理请求
+++++++++++"输出证书的有效期"+++++++++++
openssl x509 -in www.wzh.com.crt -noout –dates
(4)原理
请求过程:
client和server'先建立tcp连接'-->经过'TLS握手'-->实现'https通信'-->进而发送'HTTP请求'
细节点:
[1]、也就是在TLS'握手阶段','server端'还'没有'获取七层'HTTP'报文的信息
[2]、也即'无法获取'请求头中的'Host'主机头
疑问: server端是通过'什么(what)'来区分应该返回哪个域名的证书?
回答: url中的'主机名',而不是请求头中'Host'的主机名
工作原理:
[1]、SSL'协商'阶段,nginx server根据'url 中的主机域名'查找对应'server块中server_name'
[2]、将'该证书'返回给'客户端'进行校验
大白鲨抓包看SNI
四 参考博客
HTTPS 深入浅出 - 什么是 SNI?
nginx配置多个TLS证书,以及TLS SNI简介
nginx使用SNI功能的方法
最后
以上就是热心烧鹅为你收集整理的nginx(十)SNI理解的全部内容,希望文章能够帮你解决nginx(十)SNI理解所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复