服务器名称指示

服务器名称指示（，缩写：SNI）是TLS的一个扩展协议，在该协议下，在握手过程开始时客户端告诉它正在连接的服务器要连接的主机名称。这允许服务器在相同的IP地址和TCP端口号上呈现多个证书，并且因此允许在相同的IP地址上提供多个安全（HTTPS）网站（或其他任何基于TLS的服务），而不需要所有这些站点使用相同的证书。它与HTTP/1.1基于名称的虚拟主机的概念相同，但是用于HTTPS。

为了使SNI协议起作用，绝大多数访问者必须使用实现它的Web浏览器。使用未实现SNI浏览器的用户将被提供默认证书，因此很可能会收到证书警告。

问题的背景
当进行TLS连接时，客户端从Web服务器请求数字证书。服务器一旦发送证书，客户端就会检查这个证书，并将其尝试连接的名称与证书中包含的名称进行对比。如果发生匹配，则连接正常进行。如果没有找到匹配，则可能会向用户警告该差异，并且可能会中止连接，因为该失配可能表明存在中间人攻击。不过，某些应用程序允许用户绕过警告继续进行连接，由用户承担信任证书以及连接的责任。

一个证书覆盖多个主机名是可以做到的。X.509 v3规范引入了subjectAltName字段，该字段允许一个证书指定多个域名，并在通用名和subjectAltName字段中使用通配符。

然而，由于缺少所有名称的完整列表，可能很难甚至不可能获得涵盖服务器将负责的所有名称的单个证书。负责多个主机名的服务器可能需要为每个名称（或一组名称）提供不同的证书。自2005年以来，CAcert已经在虚拟服务器上运行了TLS的不同用法的实验。大多数实验是不理想和不切实际的。例如，可以使用subjectAltName来包含单个证书中由一个人控制的多个域名。每当域名列表更改时，必须重新发布此类“统一通信证书”。

基于名称的虚拟主机允许多个DNS主机名由同一IP地址上的单个服务器（通常为Web服务器）托管。为了实现这一点，服务器使用客户端提供的主机名作为协议的一部分（对于HTTP，名称显示在主机头中）。但是，当使用HTTPS时，TLS握手发生在服务器看到任何HTTP头之前。因此，服务器不可能使用HTTP主机头中的信息来决定呈现哪个证书，并且因此只有由同一证书覆盖的名称才能由同一IP地址提供。

实际上，这意味着对于安全浏览来说，HTTPS服务器只能是每个IP地址服务一个域名（或一组域名）。为每个站点分配单独的IP地址会增加托管成本，因为对IP地址的请求必须为区域互联网注册机构提供证据而且现在IPv4地址已用尽。其结果是，许多网站在IPv4上使用安全通信实际上都受到了限制。IPv6地址空间未用完，因此使用IPv6提供的网站不受此问题的影响。

 SNI如何解决此问题 
客户端在SNI扩展中发送要连接的主机名称，作为TLS协商的一部分。这使服务器能够提前选择正确的主机名称，并向浏览器提供相应TLS证书。从而，具有单个IP地址的服务器可以在获取公共证书不现实的情况下提供一组域名的TLS连接。

SNI在2003年6月的RFC 3546，《传输层安全（TLS）扩展》中加入到IETF的Internet RFCs中。最新版本的标准是RFC 6066。

 实现 
在2004年，EdelKey项目做了一个用于将TLS/SNI添加到OpenSSL中的补丁。在2006年，这个补丁被移植到OpenSSL的开发分支，并在2007年由OpenSSL 0.9.8支持（首次发布在0.9.8f）。

一个应用程序要实现SNI，它使用的TLS库必须实现SNI，并且该应用程序必须将主机名传递给TLS库。其他复杂的问题有，TLS库可以包括在应用程序中或者作为底层操作系统的组件。因此，一些浏览器在任何操作系统上运行时都能实现SNI，而其他浏览器仅在某些操作系统上运行时才能实现SNI。

安全性

Cloudflare的联合创始人兼首席执行官Matthew Prince曾表示，传统SNI“绝对是加密装甲中的最后缝隙之一”。（really is one of the last chinks in the encryption armor.）

由于SNI信息并未加密，审查者可以识别出使用者访问的网站域名。现已被部分国家用于互联网审查，如防火长城和韩国的KCSC（廣播通信審議委員會）。有两种方法可以解决这个问题。
域前置

域前置通过SNI中使用虚假无害的域名信息，已经被TLS加密的应用层才使用真实的域名信息，将真实流量隐藏在看似无害的流量中，从而使审查者无法区别出来，对于基于CDN的域前置，审查者要么一律放行，要么带有严重附加伤害的一刀切封锁。

Cloudflare在2016年的一些修改让基于其CDN的域前置不再工作。

Google和CloudFront曾经接受域前置，之后停止了，被认为是受到俄罗斯政府的压力，防止Telegram利用该技术来规避审查。

 加密服务器名称指示 
作为TLS的标准扩展实现，TLS 1.3一开始准备通过支持加密SNI以解决这个问题。Cloudflare、Mozilla、Fastly和苹果的开发者制定了关于加密服务器名称指示（Encrypted Server Name Indication）的草案。

2018年9月24日，Cloudflare在其网络上支持并默认启用了ESNI。
2019年7月，Mozilla Firefox开始提供ESNI的草案性实现支持，但預設關閉。2019年8月，研究人员确认ESNI可以有效规避防火长城的SNI审查。

2020年3月，ESNI更名为Encrypted Client Hello（简称ECHO），把加密扩展至整个Client Hello消息。2020年5月，简称更改为ECH。ECH被认为解决了之前ESNI扩展「突出」（stick out），从而容易被互联网服务提供商或审查系统识别的问题。从2023年09月29日开始，Cloudflare在“免费计划”的用户组中默认开启了ECH且无法关闭，付费用户则可以选择性开启。

自2020年7月下旬起，防火长城开始封锁加密服务器名称指示（ESNI）的TLS通信。但没有封锁ECH的TLS通信。而2020年8月开始，俄罗斯互联网服务运营商及旗下移动手机服务运营商Tele2开始封锁加密服务器名称指示（ESNI）的TLS通信。2024年11月起，俄罗斯开始屏蔽来自Cloudflare 的 ECH 连接， 其他 ECH 不受影响，俄国 DPI 系统 TSPU (техническиесредства противодействия угрозам) 目前的检测条件是包含 `cloudflare-ech.com`的 TLS SNI 扩展和 TLS ECH 扩展，缺一不可。

 参考文献 

 外部链接 
 RFC 6066 (obsoletes RFC 4366 (which obsoleted RFC 3546))

Category:互联网标准
Category:网络协议
Category:傳輸層安全協議