# SNI（服务器名称指示）是什么？定义、例子与常见误区

> SNI 是 TLS 的一个扩展，客户端在 ClientHello 中写明要访问的域名，使同一个 IP 能为多个 HTTPS 站点分别返回各自的证书。

Source: https://ssl.sh/zh/glossary/sni/
Last updated: 2026-11-10

SNI（Server Name Indication）是 [RFC 6066](https://www.rfc-editor.org/rfc/rfc6066) 定义的 `server_name` 扩展。客户端在握手的第一条消息 ClientHello 里带上要访问的域名，服务器据此挑选对应的证书和虚拟主机。按规范这个字段只能填域名，不能填 IP 地址。

## 为什么重要
没有 SNI 时，服务器要等握手结束、读到 HTTP 的 Host 头才知道访问的是哪个站点，所以一个 IP 加端口只能挂一张证书。共享虚拟主机、CDN、负载均衡能在同一个 IP 上承载大量 HTTPS 站点，靠的就是 SNI；在 Nginx 或宝塔面板里给多个站点各配一张证书，背后也是按 SNI 分流。客户端没发 SNI，或发了服务器不认识的名字，服务器就返回默认站点的证书，浏览器随即报证书域名不匹配。另外 SNI 是明文传输的，即使在 [TLS 1.3](https://ssl.sh/zh/glossary/tls-1-3/) 中也一样，链路上的设备能看到访问的域名；要隐藏它需要 [ECH](https://ssl.sh/zh/glossary/ech/)。

## 例子
对同一个 IP 指定 SNI，查看返回的证书：

```bash
openssl s_client -connect 203.0.113.10:443 -servername example.com </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -ext subjectAltName
```

去掉 `-servername` 再执行一次。如果拿到的是另一张证书，说明服务器按 SNI 选证书，第二张就是它的默认证书。

## 常见误区
- **每个 HTTPS 站点都要独立 IP。** 这是 SNI 普及之前的情况。如今主流浏览器和 HTTP 客户端都会发送 SNI，多张证书完全可以共用一个 IP。
- **TLS 1.3 把 SNI 加密了。** 没有。TLS 1.3 加密了服务器证书，但 SNI 仍是明文，要加密得靠 ECH。
- **SNI 就是证书里的 SAN。** SNI 是客户端请求的名字，[SAN](https://ssl.sh/zh/glossary/san/) 是证书覆盖的名字，两者匹配连接才算有效。

## 相关术语

- [TLS 握手](https://ssl.sh/zh/glossary/tls-handshake/): TLS 握手是 TLS 连接开始时的一组消息交换，客户端与服务器在其中协商协议版本和密码套件、验证服务器身份并派生会话密钥。
- [ECH](https://ssl.sh/zh/glossary/ech/): ECH 是 TLS 1.3 的扩展，用发布在 DNS 中的公钥加密 ClientHello 的敏感部分（包括 SNI），链路上只能看到前端服务器的公共名称。
- [ESNI](https://ssl.sh/zh/glossary/esni/): ESNI 是一个已被放弃的 TLS 1.3 草案，用发布在 DNS 中的公钥只加密 SNI 字段，现已被 ECH 取代。
- [SAN](https://ssl.sh/zh/glossary/san/): SAN 即主体备用名称，是 X.509 证书中列出其适用的所有域名、IP 地址等身份的扩展，客户端按它校验主机名。
- [TLS 1.3](https://ssl.sh/zh/glossary/tls-1-3/): TLS 1.3 是当前最新的传输层安全协议版本（2018 年的 RFC 8446，现行规范为 RFC 9846），完整握手只需一个往返，且只保留 AEAD 加密算法。
- [多域名证书](https://ssl.sh/zh/glossary/multi-domain-certificate/): 多域名证书是在 SAN 扩展中列出多个不同主机名、让一张证书同时保护多个域名的 TLS 证书。
- [ALPN](https://ssl.sh/zh/glossary/alpn/): ALPN 是一个 TLS 扩展，让客户端和服务器在握手过程中直接商定上层协议，例如 h2 或 http/1.1，不需要额外往返。
