在线工具
网站地图    收藏    合作   
<

快捷菜单 返回顶部

node中文API-tls安全传输层

tls 安全传输层#

中英对照

稳定性: 2 - 稳定

源代码: lib/tls.js

tls 模块提供了构建在 OpenSSL 之上的传输层安全 (TLS) 和安全套接字层 (SSL) 协议的实现。 该模块可以使用以下方式访问:

const tls = require('tls');

TLS/SSL 概念#

中英对照

TLS/SSL 是一组协议,它依赖于公钥基础设施 (PKI) 来实现客户端和服务器之间的安全通信。 对于最常见的情况,每个服务器都必须有私钥。

可以通过多种方式生成私钥。 以下示例说明了使用 OpenSSL 命令行界面生成 2048 位 RSA 私钥:

openssl genrsa -out ryans-key.pem 2048

使用 TLS/SSL,所有服务器(和一些客户端)都必须有证书。 证书是与私钥相对应的公钥,并且由证书颁发机构或私钥的所有者进行数字签名(此类证书称为“自签名”)。 获取证书的第一步是创建证书签名请求(CSR)文件。

OpenSSL 命令行界面可用于为私钥生成 CSR:

openssl req -new -sha256 -key ryans-key.pem -out ryans-csr.pem

一旦生成 CSR 文件,则它可以发送到证书颁发机构进行签名或用于生成自签名证书。

使用 OpenSSL 命令行界面创建自签名证书如以下示例所示:

openssl x509 -req -in ryans-csr.pem -signkey ryans-key.pem -out ryans-cert.pem

生成证书后,可用于生成 .pfx.p12 文件:

openssl pkcs12 -export -in ryans-cert.pem -inkey ryans-key.pem \
      -certfile ca-cert.pem -out ryans.pfx

在哪里:

  • in: 是签名的证书
  • inkey: 是关联的私钥
  • certfile: 是将所有证书颁发机构 (CA) 证书串联到一个文件中,例如 cat ca1-cert.pem ca2-cert.pem > ca-cert.pem

完美前向保密#

中英对照

术语 前向保密完美前向保密 描述了密钥协议(即密钥交换)方法的一个特征。 也就是说,服务器和客户端密钥用于协商新的临时密钥,这些密钥专门用于且仅用于当前通信会话。 实际上,这意味着即使服务器的私钥被泄露,如果攻击者设法获得专门为会话生成的密钥对,通信也只能被窃听者解密。

完美前向保密是通过在每次 TLS/SSL 握手时随机生成密钥对的密钥对来实现的(与对所有会话使用相同的密钥相反)。 实现这种技术的方法被称为"临时"。

目前常用两种方法来实现完美前向保密(注意繁体缩写后的字符 "E"):

  • DHE: Diffie-Hellman 密钥协议的临时版本。
  • ECDHE: 椭圆曲线 Diffie-Hellman 密钥协议的临时版本。

要使用 DHEtls 模块使用完美前向保密,需要生成 Diffie-Hellman 参数并使用 dhparam 选项指定它们到 tls.createSecureContext()。 以下说明使用 OpenSSL 命令行界面生成此类参数:

openssl dhparam -outform PEM -out dhparam.pem 2048

如果使用 ECDHE 使用完美前向保密,则不需要 Diffie-Hellman 参数,将使用默认 ECDHE 曲线。 创建 TLS 服务器时可以使用 ecdhCurve 属性来指定要使用的受支持曲线的名称列表,有关详细信息,请参阅 tls.createServer()

完美前向保密在 TLSv1.2 之前是可选的,但它对于 TLSv1.3 不是可选的,因为所有 TLSv1.3 密码套件都使用 ECDHE。

ALPN 和 SNI#

中英对照

ALPN(应用层协议协商扩展)和 SNI(服务器名称指示)是 TLS 握手扩展:

  • ALPN: 允许将 TLS 服务器用于多种协议(HTTP,HTTP/2)
  • SNI: 允许将 TLS 服务器用于具有不同证书的多个主机名。

预共享的密钥#

中英对照

TLS-PSK 支持可作为普通基于证书的身份验证的替代方法。 它使用预共享密钥而不是证书来验证 TLS 连接,提供相互验证。 TLS-PSK 和公钥基础设施并不相互排斥。 客户端和服务器可以同时容纳两者,在正常的密码协商步骤中选择它们中的任何一个。

TLS-PSK 只是一个不错的选择,因为存在与每台连接机器安全共享密钥的方法,因此它不会取代大多数 TLS 使用的公钥基础设施(PKI)。 OpenSSL 中的 TLS-PSK 实现近年来出现了许多安全漏洞,主要是因为它仅被少数应用程序使用。 在切换到 PSK 密码之前,请考虑所有替代解决方案。 在生成 PSK 时,使用 RFC 4086 中讨论的足够熵至关重要。 从密码或其他低熵来源导出共享秘密是不安全的。

默认情况下禁用 PSK 密码,因此使用 TLS-PSK 需要使用 ciphers 选项明确指定密码套件。 可用密码列表可以通过 openssl ciphers -v 'PSK' 检索。 所有 TLS 1.3 密码都有资格使用 PSK,但目前仅支持使用 SHA256 摘要的密码,它们可以通过 openssl ciphers -v -s -tls1_3 -psk 检索。

根据 RFC 4279,必须支持最长 128 个字节的 PSK 标识和最长 64 个字节的 PSK。 从 OpenSSL 1.1.0 开始,最大身份大小为 128 字节,最大 PSK 长度为 256 字节。

由于底层 OpenSSL API 的限制,当前的实现不支持异步 PSK 回调。

客户端发起的重协商攻击缓解#

中英对照

TLS 协议允许客户端重新协商 TLS 会话的某些方面。 不幸的是,会话重新协商需要不成比例的服务器端资源,使其成为拒绝服务攻击的潜在载体。

为了降低风险,每十分钟重新协商的次数限制为 3 次。 当超过此阈值时,tls.TLSSocket 实例上会触发 'error' 事件。 限制是可配置的:

  • tls.CLIENT_RENEG_LIMIT <number> 指定重新协商请求的数量。 默认值: 3
  • tls.CLIENT_RENEG_WINDOW <number> 指定时间重新协商窗口(以秒为单位)。 默认值: 600 (10分钟)。

在没有充分了解影响和风险的情况下,不应修改默认的重新协商限制。

TLSv1.3 不支持重新协商。

会话恢复#

中英对照

建立 TLS 会话可能相对较慢。 可以通过保存并稍后重用会话状态来加快进程。 有几种机制可以做到这一点,这里从最旧到最新(和首选)进行了讨论。

会话标识符#

中英对照

服务器为新连接生成唯一的 ID 并将其发送给客户端。 客户端和服务器保存会话状态。 当重新连接时,客户端发送其保存的会话状态的 ID,如果服务器也有该 ID 的状态,它可以同意使用它。 否则,服务器将创建新的会话。 请参阅 RFC 2246 了解更多信息,第 23 和 30 页\。

当发出 HTTPS 请求时,大多数网络浏览器都支持使用会话标识符恢复。

对于 Node.js,客户端等待 'session' 事件获取会话数据,并将数据提供给后续 tls.connect()session 选项以重用会话。 服务器必须为 'newSession''resumeSession' 事件实现句柄,以使用会话 ID 作为查找键来保存和恢复会话数据以重用会话。 要在负载均衡器或集群工作器之间重用会话,服务器必须在其会话处理程序中使用共享会话缓存(例如 Redis)。

会话票证#

中英对照

服务器加密整个会话状态并将其作为"票证"发送给客户端。 当重新连接时,在初始连接时将状态发送到服务器。 这种机制避免了服务器端会话缓存的需要。 如果服务器不使用票证,出于任何原因(无法解密、太旧等),则它将创建新的会话并发送新的票证。 请参阅 RFC 5077 了解更多信息。

当发出 HTTPS 请求时,许多网络浏览器普遍支持使用会话票证恢复。

对于 Node.js,客户端使用相同的 API 来恢复会话标识符和恢复会话票证。 用于调试,如果 tls.TLSSocket.getTLSTicket() 返回值,则会话数据包含票证,否则包含客户端会话状态。

使用 TLSv1.3,请注意服务器可能会发送多个票证,从而导致多个 'session' 事件,请参阅 'session' 了解更多信息。

单进程服务器不需要特定的实现来使用会话票证。 要在服务器重新启动或负载平衡器之间使用会话票证,服务器必须都具有相同的票证密钥。 内部有三个 16 字节的密钥,但 tls API 为方便起见将它们公开为单个 48 字节的缓冲区。

可以通过在一个服务器实例上调用 server.getTicketKeys() 来获取票证密钥然后分发它们,但是安全地生成 48 字节的安全随机数据并使用 tls.createServer()ticketKeys 选项设置它们更合理。 应该定期重新生成密钥,并且可以使用 server.setTicketKeys() 重置服务器的密钥。

会话票证密钥是加密密钥,它们_必须安全存储_。 使用 TLS 1.2 及更低版本,如果它们被泄露,所有使用用它们加密的票证的会话都可以解密。 它们不应该存储在磁盘上,应该定期重新生成。

如果客户端宣传支持票证,则服务器将发送它们。 服务器可以通过在 secureOptions 中提供 require('constants').SSL_OP_NO_TICKET 来禁用票证。

会话标识符和会话票证都超时,导致服务器创建新会话。 超时时间可以用 tls.createServer()sessionTimeout 选项配置。

对于所有机制,当恢复失败时,服务器将创建新会话。 由于无法恢复会话不会导致 TLS/HTTPS 连接失败,所以很容易不会注意到 TLS 性能不必要的糟糕。 OpenSSL CLI 可用于验证服务器是否正在恢复会话。 使用 -reconnect 选项到 openssl s_client,例如:

$ openssl s_client -connect localhost:443 -reconnect

通过调试输出读取。 第一个连接应该说 "New",例如:

New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256

后续连接应该说 "Reused",例如:

Reused, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256

修改默认的 TLS 加密组件#

中英对照

Node.js 是使用默认的启用和禁用 TLS 密码套件构建的。 这个默认密码列表可以在构建 Node.js 时配置,以允许发行版提供自己的默认列表。

以下命令可用于显示默认密码套件:

node -p crypto.constants.defaultCoreCipherList | tr ':' '\n'
TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
TLS_AES_128_GCM_SHA256
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-ECDSA-AES128-GCM-SHA256
ECDHE-RSA-AES256-GCM-SHA384
ECDHE-ECDSA-AES256-GCM-SHA384
DHE-RSA-AES128-GCM-SHA256
ECDHE-RSA-AES128-SHA256
DHE-RSA-AES128-SHA256
ECDHE-RSA-AES256-SHA384
DHE-RSA-AES256-SHA384
ECDHE-RSA-AES256-SHA256
DHE-RSA-AES256-SHA256
HIGH
!aNULL
!eNULL
!EXPORT
!DES
!RC4
!MD5
!PSK
!SRP
!CAMELLIA

可以使用 --tls-cipher-list 命令行开关(直接或通过 NODE_OPTIONS 环境变量)完全替换此默认值。 例如,以下使 ECDHE-RSA-AES128-GCM-SHA256:!RC4 成为默认的 TLS 密码套件:

node --tls-cipher-list='ECDHE-RSA-AES128-GCM-SHA256:!RC4' server.js

export NODE_OPTIONS=--tls-cipher-list='ECDHE-RSA-AES128-GCM-SHA256:!RC4'
node server.js

也可以使用 tls.createSecureContext() 中的 ciphers 选项在每个客户端或服务器的基础上替换默认值,该选项在 tls.createServer()tls.connect() 和创建新的 tls.TLSSocket 时也可用。

密码列表可以包含 TLSv1.3 密码套件名称、以 'TLS_' 开头的名称以及 TLSv1.2 及以下密码套件的规范的混合。 TLSv1.2 密码支持旧规范格式,有关详细信息,请参阅 OpenSSL 密码列表格式文档,但这些规范不适用于 TLSv1.3 密码。 TLSv1.3 套件只能通过在密码列表中包含其全名来启用。 例如,不能使用旧版 TLSv1.2 'EECDH''!EECDH' 规范启用或禁用它们。

尽管 TLSv1.3 和 TLSv1.2 密码套件的相对顺序不同,但 TLSv1.3 协议比 TLSv1.2 安全得多,如果握手表明它受支持,并且如果有的话,总是会被选择而不是 TLSv1.2 TLSv1.3 密码套件已启用。

Node.js 中包含的默认密码套件经过精心挑选,以反映当前的安全最佳实践和风险缓解。 更改默认密码套件会对应用程序的安全性产生重大影响。 只有在绝对必要时才应使用 --tls-cipher-list 开关和 ciphers 选项。

默认密码套件更喜欢 Chrome 的‘现代密码学’设置的 GCM 密码,并且还更喜欢 ECDHE 和 DHE 密码以实现完美的前向保密,同时提供一些向后兼容性。

鉴于影响更大 AES 密钥大小的特定攻击,128 位 AES 优于 192 位和 256 位 AES。

依赖不安全且不推荐使用的 RC4 或基于 DES 的密码(如 Internet Explorer 6)的旧客户端无法使用默认配置完成握手过程。 如果必须支持这些客户端,则 TLS 建议可能会提供兼容的密码套件。 有关格式的更多详细信息,请参阅 OpenSSL 密码列表格式文档。

只有五个 TLSv1.3 密码套件:

  • 'TLS_AES_256_GCM_SHA384'
  • 'TLS_CHACHA20_POLY1305_SHA256'
  • 'TLS_AES_128_GCM_SHA256'
  • 'TLS_AES_128_CCM_SHA256'
  • 'TLS_AES_128_CCM_8_SHA256'

默认启用前三个。 TLSv1.3 支持这两个基于 CCM 的套件,因为它们在受限系统上的性能可能更高,但默认情况下未启用它们,因为它们提供的安全性较低。

X509 证书的错误码#

中英对照

由于 OpenSSL 报告的证书错误,多个功能可能会失败。 在这种情况下,该函数通过其回调提供 <Error>,该回调具有属性 code,该属性可以采用以下值之一:

  • 'UNABLE_TO_GET_ISSUER_CERT': 无法获得颁发者证书。
  • 'UNABLE_TO_GET_CRL': 无法获得证书 CRL。
  • 'UNABLE_TO_DECRYPT_CERT_SIGNATURE': 无法解密证书的签名。
  • 'UNABLE_TO_DECRYPT_CRL_SIGNATURE': 无法解密 CRL 的签名。
  • 'UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY': 无法解码发行者公钥。
  • 'CERT_SIGNATURE_FAILURE': 证书签名失败。
  • 'CRL_SIGNATURE_FAILURE': CRL 签名失败。
  • 'CERT_NOT_YET_VALID': 证书尚未生效。
  • 'CERT_HAS_EXPIRED': 证书已过期。
  • 'CRL_NOT_YET_VALID': CRL 尚未生效。
  • 'CRL_HAS_EXPIRED': CRL 已过期。
  • 'ERROR_IN_CERT_NOT_BEFORE_FIELD': 证书的 notBefore 字段中的格式错误。
  • 'ERROR_IN_CERT_NOT_AFTER_FIELD': 证书的 notAfter 字段中的格式错误。
  • 'ERROR_IN_CRL_LAST_UPDATE_FIELD': CRL 的 lastUpdate 字段中的格式错误。
  • 'ERROR_IN_CRL_NEXT_UPDATE_FIELD': CRL 的 nextUpdate 字段中的格式错误。
  • 'OUT_OF_MEM': 内存不足。
  • 'DEPTH_ZERO_SELF_SIGNED_CERT': 自签名证书。
  • 'SELF_SIGNED_CERT_IN_CHAIN': 证书链中的自签名证书。
  • 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY': 无法获得本地颁发者证书。
  • 'UNABLE_TO_VERIFY_LEAF_SIGNATURE': 无法验证第一个证书。
  • 'CERT_CHAIN_TOO_LONG': 证书链太长。
  • 'CERT_REVOKED': 证书已撤销。
  • 'INVALID_CA': 无效的 CA 证书。
  • 'PATH_LENGTH_EXCEEDED': 超出路径长度限制。
  • 'INVALID_PURPOSE': 不支持的证书用途。
  • 'CERT_UNTRUSTED': 证书不受信任。
  • 'CERT_REJECTED': 证书被拒绝。
  • 'HOSTNAME_MISMATCH': 主机名不匹配。

tls.CryptoStream#

中英对照

稳定性: 0 - 弃用: 改为使用 tls.TLSSocket

tls.CryptoStream 类表示加密数据流。 此类已弃用,不应再使用。

cryptoStream.bytesWritten#

中英对照

cryptoStream.bytesWritten 属性返回写入底层套接字的总字节数_包括_实现 TLS 协议所需的字节数。

tls.SecurePair#

中英对照

稳定性: 0 - 弃用: 改为使用 tls.TLSSocket

tls.createSecurePair() 返回。

'secure' 事件#

中英对照

一旦建立了安全连接,则 SecurePair 对象就会触发 'secure' 事件。

与检查服务器 'secureConnection' 事件一样,应检查 pair.cleartext.authorized 以确认所使用的证书是否已正确授权。

tls.Server#

中英对照

接受使用 TLS 或 SSL 的加密连接。

'connection' 事件#

中英对照

此事件在建立新的 TCP 流时触发,在 TLS 握手开始之前。 socket 通常是 net.Socket 类型的对象。 通常用户不会想访问这个事件。

此事件也可以由用户显式地触发以将连接注入 TLS 服务器。 在这种情况下,任何 Duplex 流都可以通过。

'keylog' 事件#

中英对照

  • line <Buffer> ASCII 文本行,采用 NSS SSLKEYLOGFILE 格式。
  • tlsSocket <tls.TLSSocket> 生成它的 tls.TLSSocket 实例。

keylog 事件在生成或通过与此服务器的连接接收密钥材料时触发(通常在握手完成之前,但不一定)。 该密钥材料可以存储用于调试,因为它允许对捕获的 TLS 流量进行解密。 它可以为每个套接字多次触发。

一个典型的用例是将接收到的行附加到公共文本文件中,稍后软件(例如 Wireshark)使用它来解密流量:

const logFile = fs.createWriteStream('/tmp/ssl-keys.log', { flags: 'a' });
// ...
server.on('keylog', (line, tlsSocket) => {
  if (tlsSocket.remoteAddress !== '...')
    return; // 仅记录特定 IP 的密钥
  logFile.write(line);
});

'newSession' 事件#

中英对照

在创建新的 TLS 会话时触发 'newSession' 事件。 这可用于在外部存储中存储会话。 数据应该提供给 'resumeSession' 回调。

监听器回调在调用时传入三个参数:

  • sessionId <Buffer> TLS 会话标识符
  • sessionData <Buffer> TLS 会话数据
  • callback <Function> 回调函数不带参数,必须调用这些参数才能通过安全连接发送或接收数据。

监听此事件只会对添加事件监听器后建立的连接有影响。

'OCSPRequest' 事件#

中英对照

当客户端发送证书状态请求时会触发 'OCSPRequest' 事件。 监听器回调在调用时传入三个参数:

  • certificate <Buffer> 服务器证书
  • issuer <Buffer> 发行人证书
  • callback <Function> 必须调用的回调函数来提供 OCSP 请求的结果。

可以解析服务器当前的证书,获取 OCSP URL 和证书 ID;获取 OCSP 响应后,再调用 callback(null, resp),其中 resp 是包含 OCSP 响应的 Buffer 实例。 certificateissuer 都是主证书和颁发者证书的 Buffer DER 表示。 这些可用于获取 OCSP 证书 ID 和 OCSP 端点 URL。

或者,可以调用 callback(null, null),表示没有 OCSP 响应。

调用 callback(err) 将导致调用 socket.destroy(err)

OCSP 请求的典型流程如下:

  1. 客户端连接到服务器并发送 'OCSPRequest'(通过 ClientHello 中的状态信息扩展)。
  2. 服务器收到请求并触发 'OCSPRequest' 事件,如果已注册则调用监听器。
  3. 服务器从 certificateissuer 中提取 OCSP URL,并向 CA 执行 OCSP 请求
  4. 服务器从 CA 接收 'OCSPResponse' 并通过 callback 参数将其发送回客户端
  5. 客户端验证响应并销毁套接字或执行握手。

如果证书是自签名证书或颁发者不在根证书列表中,则 issuer 可以是 null。 (在建立 TLS 连接时可以通过 ca 选项提供颁发者。)

监听此事件只会对添加事件监听器后建立的连接有影响。

asn1.js 这样的 npm 模块可用于解析证书。

'resumeSession' 事件#

中英对照

当客户端请求恢复之前的 TLS 会话时,则会触发 'resumeSession' 事件。 监听器回调在调用时传入两个参数:

  • sessionId <Buffer> TLS 会话标识符
  • callback <Function> 恢复前一个会话时要调用的回调函数:callback([err[, sessionData]])

事件监听器应该使用给定的 sessionId 在外部存储中为 'newSession' 事件处理程序保存的 sessionData 执行查找。 如果找到,则调用 callback(null, sessionData) 恢复会话。 如果没有找到,则会话将无法恢复。 callback() 必须在没有 sessionData 的情况下被调用,以便握手可以继续并可以创建新的会话。 可以调用 callback(err) 来终止传入的连接并销毁套接字。

监听此事件只会对添加事件监听器后建立的连接有影响。

以下说明恢复 TLS 会话:

const tlsSessionStore = {};
server.on('newSession', (id, data, cb) => {
  tlsSessionStore[id.toString('hex')] = data;
  cb();
});
server.on('resumeSession', (id, cb) => {
  cb(null, tlsSessionStore[id.toString('hex')] || null);
});

'secureConnection' 事件#

中英对照

'secureConnection' 事件在新连接的握手过程成功完成后触发。 监听器回调在调用时传入一个参数:

tlsSocket.authorized 属性是一个 boolean,指示客户端是否已通过服务器提供的证书颁发机构之一进行验证。 如果 tlsSocket.authorizedfalse,则设置 socket.authorizationError 来描述授权失败的方式。 根据 TLS 服务器的设置,可能仍会接受未经授权的连接。

tlsSocket.alpnProtocol 属性是包含所选 ALPN 协议的字符串。 当 ALPN 没有选择协议时,则 tlsSocket.alpnProtocol 等于 false

tlsSocket.servername 属性是包含通过 SNI 请求的服务器名称的字符串。

'tlsClientError' 事件#

中英对照

在建立安全连接之前发生错误时会触发 'tlsClientError' 事件。 监听器回调在调用时传入两个参数:

  • exception <Error> 描述错误的 Error 对象
  • tlsSocket <tls.TLSSocket> 错误源自的 tls.TLSSocket 实例。

server.addContext(hostname, context)#

中英对照

server.addContext() 方法添加了安全的上下文,如果客户端请求的 SNI 名称与提供的 hostname(或通配符)匹配,则将使用该上下文。

当有多个匹配的上下文时,使用最近添加的一个。

server.address()#

中英对照

返回操作系统报告的绑定地址、地址族名称和服务器端口。 有关详细信息,请参阅 net.Server.address()

server.close([callback])#

中英对照

  • callback <Function> 监听器回调,将被注册以监听服务器实例的 'close' 事件。
  • 返回: <tls.Server>

server.close() 方法阻止服务器接受新连接。

此函数异步地运行。 当服务器没有更多打开的连接时,则将触发 'close' 事件。

server.getTicketKeys()#

中英对照

  • 返回: <Buffer> 包含会话票证密钥的 48 字节缓冲区。

返回会话票证密钥。

请参阅会话恢复了解更多信息。

server.listen()#

中英对照

启动服务器监听加密连接。 此方法与 net.Server 中的 server.listen() 相同。

server.setSecureContext(options)#

中英对照

server.setSecureContext() 方法替换现有服务器的安全上下文。 与服务器的现有连接不会中断。

server.setTicketKeys(keys)#

中英对照

设置会话票证密钥。

更改票证密钥仅对以后的服务器连接有效。 现有的或当前挂起的服务器连接将使用以前的键。

请参阅会话恢复了解更多信息。

tls.TLSSocket#

中英对照

对写入的数据和所有必需的 TLS 协商进行透明加密。

tls.TLSSocket 的实例实现了双工接口。

返回 TLS 连接元数据的方法(例如 tls.TLSSocket.getPeerCertificate() 只会在连接打开时返回数据。

new tls.TLSSocket(socket[, options])#

中英对照

  • socket <net.Socket> | <stream.Duplex> 在服务器端,任何 Duplex 流。 在客户端,任何 net.Socket 实例(对于客户端的通用 Duplex 流支持,必须使用 tls.connect())。
  • options <Object>
    • enableTrace: 参见 tls.createServer()
    • isServer: SSL/TLS 协议是不对称的,TLSSockets 必须知道它们是作为服务器还是客户端运行。 如果 true TLS 套接字将被实例化为服务器。 默认值: false
    • server <net.Server> net.Server 实例。
    • requestCert: 是否通过请求证书来验证远程对等体。 客户端总是请求服务器证书。 服务器(isServer 为真)可以将 requestCert 设置为真以请求客户端证书。
    • rejectUnauthorized: 参见 tls.createServer()
    • ALPNProtocols: 参见 tls.createServer()
    • SNICallback: 参见 tls.createServer()
    • session <Buffer> 包含 TLS 会话的 Buffer 实例。
    • requestOCSP <boolean> 如果为 true, 则指定将 OCSP 状态请求扩展添加到客户端 hello 并在建立安全通信之前在套接字上触发 'OCSPResponse' 事件
    • secureContext: 使用 tls.createSecureContext() 创建的 TLS 上下文对象。 如果 secureContext 未提供,则将通过将整个 options 对象传给 tls.createSecureContext() 来创建。
    • ...: 如果缺少 secureContext 选项,则使用 tls.createSecureContext() 选项。 否则,它们将被忽略。

从现有的 TCP 套接字构造新的 tls.TLSSocket 对象。

'keylog' 事件#

中英对照

  • line <Buffer> ASCII 文本行,采用 NSS SSLKEYLOGFILE 格式。

当套接字生成或接收密钥材料时,keylog 事件在 tls.TLSSocket 上触发。 该密钥材料可以存储用于调试,因为它允许对捕获的 TLS 流量进行解密。 它可能会在握手完成之前或之后多次触发。

一个典型的用例是将接收到的行附加到公共文本文件中,稍后软件(例如 Wireshark)使用它来解密流量:

const logFile = fs.createWriteStream('/tmp/ssl-keys.log', { flags: 'a' });
// ...
tlsSocket.on('keylog', (line) => logFile.write(line));

'OCSPResponse' 事件#

中英对照

如果在创建 tls.TLSSocket 并收到 OCSP 响应时设置了 requestOCSP 选项,则会触发 'OCSPResponse' 事件。 监听器回调在调用时传入一个参数:

  • response <Buffer> 服务器的 OCSP 响应

通常,response 是来自服务器 CA 的数字签名对象,其中包含有关服务器证书吊销状态的信息。

'secureConnect' 事件#

中英对照

'secureConnect' 事件在新连接的握手过程成功完成后触发。 无论服务器的证书是否被授权,都会调用监听回调。 客户端有责任检查 tlsSocket.authorized 属性以确定服务器证书是否由指定的 CA 之一签名。 如果为 tlsSocket.authorized === false,则可以通过检查 tlsSocket.authorizationError 属性来发现错误。 如果使用了 ALPN,可以检查 tlsSocket.alpnProtocol 属性来确定协商的协议。

当使用 new tls.TLSSocket() 构造函数创建 <tls.TLSSocket> 时,则不会触发 'secureConnect' 事件。

'session' 事件#

中英对照

当新会话或 TLS 票证可用时,则客户端 tls.TLSSocket 上会触发 'session' 事件。 这可能会也可能不会在握手完成之前发生,具体取决于协商的 TLS 协议版本。 该事件未在服务器上触发,或者未创建新会话,例如,当连接恢复时。 对于某些 TLS 协议版本,事件可能会多次发出,在这种情况下,所有会话都可以用于恢复。

在客户端,可以将 session 提供给 tls.connect()session 选项来恢复连接。

请参阅会话恢复了解更多信息。

对于 TLSv1.2 及以下版本,握手完成后可以调用 tls.TLSSocket.getSession()。 对于 TLSv1.3,协议只允许基于票证的恢复,发送多张票证,直到握手完成后才发送票证。 所以需要等待 'session' 事件才能得到可恢复的会话。 应用程序应该使用 'session' 事件而不是 getSession() 来确保它们适用于所有 TLS 版本。 只希望获得或使用一个会话的应用程序应该只监听此事件一次:

tlsSocket.once('session', (session) => {
  // 会话可以立即或稍后使用。
  tls.connect({
    session: session,
    // 其他连接选项...
  });
});

tlsSocket.address()#

中英对照

返回操作系统报告的底层套接字的绑定 address、地址 family 名称和 port{ port: 12346, family: 'IPv4', address: '127.0.0.1' }

tlsSocket.authorizationError#

中英对照

返回未验证对等方证书的原因。 此属性仅在 tlsSocket.authorized === false 时设置。

tlsSocket.authorized#

中英对照

如果对等证书由创建 tls.TLSSocket 实例时指定的 CA 之一签名,则返回 true,否则返回 false

tlsSocket.disableRenegotiation()#

中英对照

禁用此 TLSSocket 实例的 TLS 重新协商。 一旦调用,则尝试重新协商将在 TLSSocket 上触发 'error' 事件。

tlsSocket.enableTrace()#

中英对照

当启用后,TLS 数据包跟踪信息将写入 stderr。 这可用于调试 TLS 连接问题。

输出的格式与 openssl s_client -traceopenssl s_server -trace 的输出相同。 虽然它是由 OpenSSL 的 SSL_trace() 函数生成的,但格式未记录,可以在不通知的情况下更改,不应依赖。

tlsSocket.encrypted#

中英对照

总是返回 true。 这可用于将 TLS 套接字与常规 net.Socket 实例区分开来。

tlsSocket.exportKeyingMaterial(length, label[, context])#

中英对照

密钥材料用于验证以防止网络协议中的不同类型的攻击,例如在 IEEE 802.1X 的规范中。

示例

const keyingMaterial = tlsSocket.exportKeyingMaterial(
  128,
  'client finished');

/*
 keyingMaterial 的返回值示例:
 <Buffer 76 26 af 99 c5 56 8e 42 09 91 ef 9f 93 cb ad 6c 7b 65 f8 53 f1 d8 d9
    12 5a 33 b8 b5 25 df 7b 37 9f e0 e2 4f b8 67 83 a3 2f cd 5d 41 42 4c 91
    74 ef 2c ... 78 more bytes>
*/

有关详细信息,请参阅 OpenSSL SSL_export_keying_material 文档。

tlsSocket.getCertificate()#


自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习

京ICP备14009008号@版权所有www.zixuephp.com

网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com