我是靠谱客的博主 热心烧鹅,最近开发中收集的这篇文章主要介绍nginx(十)SNI理解,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一   背景探究驱动

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理解所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部