什么是SNI?
SNI(Server Name Indication)是TLS的扩展,用来解决一个服务器拥有多个域名的情况。
在客户端和服务端建立HTTPS的过程中要先进行TLS握手,握手后会将HTTP报文使用协商好的密钥加密传输。在TLS握手信息中并没有携带客户端要访问的目标地址。
这样会导致一个问题,如果一台服务器有多个虚拟主机,且每个主机的域名不一样,使用了不一样的证书,该和哪台虚拟主机进行通信?SNI在TLS握手第一阶段ClientHello的报文中添加,用来解决这个问题。 SNI在建立会话时扮演着重要的角色。它允许客户端告诉服务器它正在连接的主机名称,从而使得服务器可以选择合适的证书进行验证。如果没有SNI,服务器就无法知道客户端想要访问哪个域名,就会默认使用第一个虚拟主机的证书进行验证。
请注意,SNI信息是在握手的过程中,在客户端发送给服务端的第一个握手包中传递的信息。这时候SSL连接还未建立起来,因此SNI信息是明文传输的。
数据包分析
Wireshark关键字 ssl.handshake.extensions_server_name
建立TLS通道前,数据明文传输
建立TLS通道后,数据已加密
简单来说:
- 用户向服务器发起TLS连接时,会在Client Hello消息中包含SNI字段,标明请求的服务器域名
- 防火墙检查SNI中的域名,如果命中了黑名单,则断开连接,不转发Client Hello到服务器
- 如果域名没命中黑名单,则转发Client Hello到服务器,完成后续TLS握手
- 服务器返回证书、加密响应等通过防火墙转发给用户
导致的问题:
- 防火墙可以通过SNI实时监控用户访问了哪些网站
- 防火墙可以屏蔽任意域名的网站使用户不再能访问
解决方案:
使用SNI代理、DoH、DoT等方式绕过监控。比如使用支持SNI隐藏的浏览器,如Chrome与 Firefox的一些版本实现了ESNI技术,可以加密SNI信息,避免泄露实际访问域名。
但是!网络安全是木桶效应非常明显的行业,短板高度决定了木桶的水平面高度。SNI的等价信息可以通过各种其他方式获得,例如IP地址跟踪、DNS名称或服务器证书。
证书信息:服务器在TLS握手期间发送其数字证书给客户端。虽然SNI通常用于选择正确的证书,但证书本身也包含有关服务器的信息,例如主题(Subject)字段中的通用名称(Common Name)或Subject Alternative Name(SAN)扩展中的域名。这些信息可能包含所通信的服务器的等效信息。
IP地址跟踪:虽然SNI允许客户端发送服务器的主机名,但TLS握手的目标IP地址通常也是可见的。通过监视或记录通信中的IP地址,可能可以确定服务器的等效信息。