介绍
sni 是一个 npm 包,可以用于解析 TLS/SSL 握手时的 Server Name Indication(SNI)。SNI 扩展允许客户端在建立 TLS 连接时指定服务器名,以便在支持多个虚拟主机的 Web 服务器上正确选择要连接的主机。该 npm 包提供了一种简单的方式来解析 SNI 信息,并从中提取服务器名。
安装
通过 npm 安装 sni:
npm install sni
使用方法
解析 SNI
我们将通过一个简单的示例来演示如何使用 sni 包。我们首先需要导入 sni 包:
const sni = require('sni')
接下来,我们可以使用该包的 parse
函数来解析 SNI:
const serverName = sni.parse(buffer)
其中,buffer
是一个包含 TLS 握手消息的缓冲区,serverName
是从 SNI 中提取出的服务器名。
示例代码
下面是完整的示例代码:
-- -------------------- ---- ------- ----- --- - -------------- ----- --- - -------------- ----- ------- - - ----- ------------- ----- ---- - ----- ------ - -------------------- -- -- - ------------------------ ----- ---------- - ------------------------------------------ -------------------------- ----------- ------------ --
在此示例中,我们通过 TLS 连接到 github.com,然后从 socket.getPeerCertificate()
中获取证书,并将证书缓冲区传递给 sni.parse()
函数。最后,我们将提取的服务器名打印到控制台上。
深入探索
在深入探索之前,我们首先需要了解一些有关 SNI 和 TLS 握手的基础知识。
SNI
SNI 是 TLS/SSL 握手过程中的一个扩展,由客户端发送到服务器以指定要连接的主机名。当客户端支持 SNI 时,它会在建立 TLS 连接之前发送一个 ClientHello 消息,其中包括一个或多个 SNI 扩展。这些扩展将包含要连接的主机名。
服务器可以使用这些信息来选择正确的证书并设置正确的虚拟主机。如果服务器无法确定要连接的主机名,则它可能会选择默认证书或发出错误。
TLS 握手
TLS 握手包括以下步骤:
- 客户端发送一个 ClientHello 消息,其中包括一些加密协议和密钥交换算法的列表,以及可能包含 SNI 扩展。
- 服务器回复一个 ServerHello 消息,其中包括选定的加密协议和密钥交换算法,以及可能包含 SNI 扩展和证书。
- 客户端验证服务器的证书,并根据需要向服务器发送一个客户端证书。
- 客户端计算会话密钥,并使用服务器传递的公钥加密它。
- 客户端发送一个 ChangeCipherSpec 消息,指示其将从此时开始使用新的加密套件。
- 客户端发送一个 Finished 消息,其中包含握手消息的哈希值(用于验证握手过程的完整性)。
- 服务器接收到 ChangeCipherSpec 消息,并开始使用新的加密套件加密所有后续的通信。
- 服务器发送一个 Finished 消息,其中包含握手消息的哈希值。
建议
- 如果您正在构建一个需要使用 SNI 的客户端,请务必了解您连接的服务器是否支持 SNI。
- 在使用 sni 包时,请确保使用一个包含 SNI 扩展的消息。否则,将无法提取服务器名。
- SNI 扩展不加密,因此,如果您的应用程序需要处理敏感信息,请使用加密协议(例如 HTTPS)来保护数据传输。
- 如果不需要使用 sni 包,不要将其添加到您的项目中。这样可以减少项目的依赖项并提高安全性。
总结
sni 包为解析 SNI 提供了一种简单的方法。除此之外,我们还学习了有关 SNI 和 TLS 握手的基础知识,并探讨了在使用 SNI 时需要考虑的问题。希望这篇文章能够帮助您更好地理解 SNI 和 TLS 握手,并在构建您的 Web 应用程序时提供指导。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/sni