TLS (SSL)
源代码: lib/tls.js
node:tls
模块提供了一个基于 OpenSSL 的传输层安全 (TLS) 和安全套接字层 (SSL) 协议实现。可以使用以下方式访问该模块:
import tls from 'node:tls'
const tls = require('node:tls')
判断加密支持是否不可用
Node.js 可能在构建时未包含对 node:crypto
模块的支持。在这种情况下,尝试从 tls
导入或调用 require('node:tls')
将导致抛出错误。
使用 CommonJS 时,可以使用 try/catch 捕获抛出的错误:
let tls
try {
tls = require('node:tls')
} catch (err) {
console.error('tls 支持已禁用!')
}
使用词法 ESM import
关键字时,只有在 在 尝试加载模块(例如,使用预加载模块)之前注册了 process.on('uncaughtException')
处理程序时,才能捕获该错误。
使用 ESM 时,如果代码有可能在未启用加密支持的 Node.js 版本上运行,请考虑使用 import()
函数而不是词法 import
关键字:
let tls
try {
tls = await import('node:tls')
} catch (err) {
console.error('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”):
使用 ECDHE 的完全前向保密默认启用。创建 TLS 服务器时可以使用 ecdhCurve
选项来自定义要使用的受支持 ECDH 曲线的列表。有关更多信息,请参见tls.createServer()
。
DHE 默认禁用,但可以通过将 dhparam
选项设置为 'auto'
来与 ECDHE 一起启用。也支持自定义 DHE 参数,但不建议使用,建议使用自动选择的、众所周知的参数。
在 TLSv1.2 之前,完全前向保密是可选的。从 TLSv1.3 开始,(EC)DHE 始终使用(PSK 仅连接除外)。
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 的条件,可以通过 openssl ciphers -v -s -tls1_3 -psk
获取。在客户端连接上,应该传递自定义的 checkServerIdentity
,因为在没有证书的情况下,默认的 checkServerIdentity
会失败。
根据 RFC 4279,必须支持长度最大为 128 字节的 PSK 标识和长度最大为 64 字节的 PSK。从 OpenSSL 1.1.0 开始,最大标识大小为 128 字节,最大 PSK 长度为 256 字节。
由于底层 OpenSSL API 的限制,当前实现不支持异步 PSK 回调。
要使用 TLS-PSK,客户端和服务器必须指定 pskCallback
选项,这是一个返回要使用的 PSK 的函数(必须与所选密码的摘要兼容)。
它将首先在客户端调用:
- hint: <string> 服务器发送的可选消息,以帮助客户端决定在协商过程中使用哪个标识。如果使用 TLS 1.3,则始终为
null
。 - 返回值: <Object> 格式为
{ psk: \<Buffer|TypedArray|DataView\>, identity: \<string\> }
或null
。
然后在服务器上:
- socket: <tls.TLSSocket> 服务器套接字实例,相当于
this
。 - identity: <string> 客户端发送的身份参数。
- 返回值: <Buffer> | <TypedArray> | <DataView> PSK(或
null
)。
返回值 null
将停止协商过程,并向另一方发送 unknown_psk_identity
警报消息。如果服务器希望隐藏 PSK 标识未知的事实,则回调必须提供一些随机数据作为 psk
,以使连接在协商完成之前以 decrypt_error
失败。
客户端发起重协商攻击缓解
TLS 协议允许客户端重新协商 TLS 会话的某些方面。不幸的是,会话重协商需要服务器端大量的资源,使其成为潜在的拒绝服务攻击载体。
为了降低风险,重协商限制为每十分钟三次。当超过此阈值时,会在 tls.TLSSocket
实例上发出 'error'
事件。限制是可配置的:
tls.CLIENT_RENEG_LIMIT
<数字> 指定重协商请求的次数。默认值:3
。tls.CLIENT_RENEG_WINDOW
<数字> 指定重协商窗口的时间(秒)。默认值:600
(10 分钟)。
如果没有完全理解其含义和风险,则不应修改默认的重协商限制。
TLSv1.3 不支持重协商。
会话恢复
建立 TLS 会话可能相对较慢。通过保存和稍后重用会话状态可以加快此过程。这里讨论了几种机制,从旧到新(以及首选)的顺序排列。
会话标识符
服务器为新的连接生成一个唯一的 ID 并将其发送给客户端。客户端和服务器保存会话状态。重新连接时,客户端发送其保存的会话状态的 ID,如果服务器也具有该 ID 的状态,则可以同意使用它。否则,服务器将创建一个新的会话。有关更多信息,请参见 RFC 2246,第 23 页和 30 页。
大多数 Web 浏览器在进行 HTTPS 请求时都支持使用会话标识符恢复会话。
对于 Node.js,客户端等待 'session'
事件以获取会话数据,并将数据提供给后续 tls.connect()
的 session
选项以重用会话。服务器必须为 'newSession'
和 'resumeSession'
事件实现处理程序,以便使用会话 ID 作为查找键来保存和恢复会话数据以重用会话。为了跨负载均衡器或集群工作器重用会话,服务器必须在其会话处理程序中使用共享会话缓存(例如 Redis)。
会话票据
服务器会加密整个会话状态,并将其作为“票据”发送给客户端。重新连接时,状态会在初始连接中发送到服务器。此机制避免了对服务器端会话缓存的需求。如果服务器由于任何原因(无法解密、票据过期等)不使用票据,它将创建一个新的会话并发送一个新的票据。更多信息请参见RFC 5077。
许多 Web 浏览器在发出 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('node: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
要进行验证,可以使用以下命令显示已设置的密码列表,注意 defaultCoreCipherList
和 defaultCipherList
之间的区别:
node --tls-cipher-list='ECDHE-RSA-AES128-GCM-SHA256:!RC4' -p crypto.constants.defaultCipherList | tr ':' '\n'
ECDHE-RSA-AES128-GCM-SHA256
!RC4
即 defaultCoreCipherList
列表在编译时设置,defaultCipherList
列表在运行时设置。
要在运行时修改默认密码套件,请修改 tls.DEFAULT_CIPHERS
变量,这必须在监听任何套接字之前执行,它不会影响已经打开的套接字。例如:
// 删除已废弃的 CBC 密码和基于 RSA 密钥交换的密码,因为它们不提供前向保密
tls.DEFAULT_CIPHERS +=
':!ECDHE-RSA-AES128-SHA:!ECDHE-RSA-AES128-SHA256:!ECDHE-RSA-AES256-SHA:!ECDHE-RSA-AES256-SHA384' +
':!ECDHE-ECDSA-AES128-SHA:!ECDHE-ECDSA-AES128-SHA256:!ECDHE-ECDSA-AES256-SHA:!ECDHE-ECDSA-AES256-SHA384' +
':!kRSA'
也可以使用 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.3,并且启用了任何 TLSv1.3 密码套件,则始终会选择 TLSv1.3 而非 TLSv1.2。
Node.js 中包含的默认密码套件已仔细选择,以反映当前的安全最佳实践和风险缓解措施。更改默认密码套件会对应用程序的安全性产生重大影响。只有在绝对必要时才应使用 --tls-cipher-list
开关和 ciphers
选项。
默认密码套件更倾向于使用 GCM 密码(针对 Chrome 的“现代密码学”设置),也更倾向于使用 ECDHE 和 DHE 密码以实现完美的前向保密性,同时提供一些向后兼容性。
依赖于不安全和已弃用的基于 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'
默认情况下启用前三个。基于 CCM
的两个套件受 TLSv1.3 支持,因为它们在受限系统上可能性能更高,但由于它们提供的安全性较低,因此默认情况下未启用它们。
OpenSSL 安全级别
OpenSSL 库强制执行安全级别以控制密码操作的最低可接受安全级别。OpenSSL 的安全级别范围为 0 到 5,每个级别都施加更严格的安全要求。默认安全级别为 1,通常适用于大多数现代应用程序。但是,某些遗留功能和协议(例如 TLSv1)需要较低的安全级别(SECLEVEL=0
)才能正常运行。有关详细信息,请参阅OpenSSL 安全级别文档。
设置安全级别
要在 Node.js 应用程序中调整安全级别,可以在密码字符串中包含 @SECLEVEL=X
,其中 X
是所需的安全性级别。例如,要在使用默认 OpenSSL 密码列表的同时将安全级别设置为 0,可以使用:
import { createServer, connect } from 'node:tls'
const port = 443
createServer({ ciphers: 'DEFAULT@SECLEVEL=0', minVersion: 'TLSv1' }, function (socket) {
console.log('Client connected with protocol:', socket.getProtocol())
socket.end()
this.close()
}).listen(port, () => {
connect(port, { ciphers: 'DEFAULT@SECLEVEL=0', maxVersion: 'TLSv1' })
})
const { createServer, connect } = require('node:tls')
const port = 443
createServer({ ciphers: 'DEFAULT@SECLEVEL=0', minVersion: 'TLSv1' }, function (socket) {
console.log('Client connected with protocol:', socket.getProtocol())
socket.end()
this.close()
}).listen(port, () => {
connect(port, { ciphers: 'DEFAULT@SECLEVEL=0', maxVersion: 'TLSv1' })
})
此方法将安全级别设置为 0,允许使用遗留功能,同时仍然利用默认的 OpenSSL 密码。
使用
您也可以使用命令行参数 --tls-cipher-list=DEFAULT@SECLEVEL=X
设置安全级别和密码套件,如修改默认 TLS 密码套件 中所述。但是,通常不建议使用命令行选项来设置密码套件,最好在应用程序代码中为各个上下文配置密码套件,因为这种方法可以提供更精细的控制,并降低全局降低安全级别的风险。
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
添加于: v0.3.4
自 v0.11.3 起已弃用
[稳定性: 0 - 已弃用]
稳定性: 0 稳定性: 0 - 已弃用: 请改用 tls.TLSSocket
。
tls.CryptoStream
类表示加密数据流。此类已弃用,不再应该使用。
cryptoStream.bytesWritten
添加于: v0.3.4
自 v0.11.3 起已弃用
cryptoStream.bytesWritten
属性返回写入到底层套接字的字节总数,包括 TLS 协议实现所需的字节。
类: tls.SecurePair
添加于: v0.3.2
自 v0.11.3 起已弃用
[稳定性: 0 - 已弃用]
稳定性: 0 稳定性: 0 - 已弃用: 请改用 tls.TLSSocket
。
由 tls.createSecurePair()
返回。
事件:'secure'
添加于:v0.3.2
自 v0.11.3 起已弃用
一旦建立安全连接,SecurePair
对象就会发出 'secure'
事件。
与检查服务器 'secureConnection'
事件一样,应检查 pair.cleartext.authorized
以确认所使用的证书是否已正确授权。
类:tls.Server
添加于:v0.3.2
- 继承自:
<net.Server>
使用 TLS 或 SSL 接受加密连接。
事件:'connection'
添加于:v0.3.2
socket
<stream.Duplex>
在 TLS 握手开始之前,建立新的 TCP 流时会发出此事件。socket
通常是 net.Socket
类型对象,但与从 net.Server
的 'connection'
事件创建的套接字不同,它不会接收事件。通常用户不需要访问此事件。
用户也可以显式发出此事件,以将连接注入到 TLS 服务器中。在这种情况下,可以传递任何 Duplex
流。
事件:'keylog'
新增于:v12.3.0, v10.20.0
line
<Buffer> ASCII 文本行,采用 NSSSSLKEYLOGFILE
格式。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'
[历史]
版本 | 变更 |
---|---|
v0.11.12 | 现在支持 callback 参数。 |
v0.9.2 | 新增于:v0.9.2 |
'newSession'
事件在创建新的 TLS 会话时发出。这可以用于将会话存储在外部存储中。数据应提供给 'resumeSession'
回调函数。
当调用监听器回调函数时,会传递三个参数:
sessionId
<Buffer> TLS 会话标识符sessionData
<Buffer> TLS 会话数据callback
<Function> 一个不带参数的回调函数,必须调用此函数才能通过安全连接发送或接收数据。
监听此事件只会影响在添加事件监听器后建立的连接。
事件: 'OCSPRequest'
新增于:v0.11.13
当客户端发送证书状态请求时,将发出 'OCSPRequest'
事件。当调用监听器回调函数时,会传递三个参数:
certificate
<Buffer> 服务器证书issuer
<Buffer> 发行者的证书callback
<Function> 一个必须调用的回调函数,用于提供 OCSP 请求的结果。
可以解析服务器的当前证书以获取 OCSP URL 和证书 ID;获取 OCSP 响应后,将调用 callback(null, resp)
,其中 resp
是包含 OCSP 响应的 Buffer
实例。certificate
和 issuer
都是主证书和发行者证书的 Buffer
DER 表示形式。这些可用于获取 OCSP 证书 ID 和 OCSP 端点 URL。
或者,可以调用 callback(null, null)
,表示没有 OCSP 响应。
调用 callback(err)
将导致 socket.destroy(err)
调用。
OCSP 请求的典型流程如下:
如果证书是自签名的或者发行者不在根证书列表中,则 issuer
可以为 null
。(在建立 TLS 连接时,可以通过 ca
选项提供发行者。)
监听此事件只会影响在添加事件监听器后建立的连接。
可以使用诸如 asn1.js 之类的 npm 模块来解析证书。
事件:'resumeSession'
新增于:v0.9.2
当客户端请求恢复之前的 TLS 会话时,将发出 'resumeSession'
事件。调用监听器回调函数时,将传递两个参数:
sessionId
<Buffer> TLS 会话标识符callback
<Function> 一个回调函数,在恢复之前的会话后调用:callback([err[, sessionData]])
事件监听器应使用给定的 sessionId
在外部存储中查找由 'newSession'
事件处理程序保存的 sessionData
。如果找到,则调用 callback(null, sessionData)
来恢复会话。如果未找到,则无法恢复会话。必须在没有 sessionData
的情况下调用 callback()
,以便握手可以继续并可以创建新的会话。可以调用 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'
新增于:v0.3.2
'secureConnection'
事件在新连接的握手过程成功完成后发出。当被调用时,监听器回调函数会传递一个参数:
tlsSocket
<tls.TLSSocket> 已建立的 TLS 套接字。
tlsSocket.authorized
属性是一个布尔值,指示客户端是否已通过服务器提供的证书颁发机构之一进行验证。如果 tlsSocket.authorized
为 false
,则 socket.authorizationError
会被设置为描述授权失败的原因。根据 TLS 服务器的设置,仍然可能接受未经授权的连接。
tlsSocket.alpnProtocol
属性是一个字符串,包含所选择的 ALPN 协议。当 ALPN 没有选择的协议(因为客户端或服务器没有发送 ALPN 扩展)时,tlsSocket.alpnProtocol
等于 false
。
tlsSocket.servername
属性是一个字符串,包含通过 SNI 请求的服务器名称。
事件:'tlsClientError'
新增于:v6.0.0
当在建立安全连接之前发生错误时,将发出 'tlsClientError'
事件。调用时,监听器回调函数将传递两个参数:
exception
<Error> 描述错误的Error
对象tlsSocket
<tls.TLSSocket> 错误来源的tls.TLSSocket
实例。
server.addContext(hostname, context)
新增于:v0.5.3
hostname
<string> SNI 主机名或通配符(例如'*'
)context
<Object> | <tls.SecureContext> 包含tls.createSecureContext()
options
参数中任何可能的属性(例如key
、cert
、ca
等)的对象,或使用tls.createSecureContext()
本身创建的 TLS 上下文对象。
server.addContext()
方法添加一个安全上下文,如果客户端请求的 SNI 名称与提供的 hostname
(或通配符)匹配,则将使用该上下文。
当存在多个匹配的上下文时,将使用最近添加的一个。
server.address()
新增于:v0.6.0
- 返回值: <Object>
返回由操作系统报告的绑定地址、地址族名称和服务器端口。更多信息参见 net.Server.address()
。
server.close([callback])
新增于:v0.3.2
callback
<Function> 一个监听回调函数,将被注册以监听服务器实例的'close'
事件。- 返回值: <tls.Server>
server.close()
方法停止服务器接受新的连接。
此函数异步操作。当服务器没有更多打开的连接时,将发出 'close'
事件。
server.getTicketKeys()
新增于:v3.0.0
- 返回值: <Buffer> 一个包含会话票据密钥的 48 字节缓冲区。
返回会话票据密钥。
更多信息参见 会话恢复。
server.listen()
启动服务器监听加密连接。此方法与 net.Server
中的 server.listen()
方法相同。
server.setSecureContext(options)
新增于:v11.0.0
options
<Object> 一个对象,包含tls.createSecureContext()
options
参数中任何可能的属性(例如key
、cert
、ca
等)。
server.setSecureContext()
方法替换现有服务器的安全上下文。对服务器的现有连接不会中断。
server.setTicketKeys(keys)
新增于:v3.0.0
keys
<Buffer> | <TypedArray> | <DataView> 一个包含会话票证密钥的 48 字节缓冲区。
设置会话票证密钥。
对票证密钥的更改仅对将来的服务器连接有效。现有或当前挂起的服务器连接将使用以前的密钥。
有关更多信息,请参阅 会话恢复。
类: tls.TLSSocket
新增于: v0.11.4
- 继承自: <net.Socket>
执行写入数据的透明加密和所有必需的 TLS 协商。
tls.TLSSocket
的实例实现了双工 Stream 接口。
返回 TLS 连接元数据的方法(例如 tls.TLSSocket.getPeerCertificate()
)只有在连接打开时才会返回数据。
new tls.TLSSocket(socket[, options])
[历史]
版本 | 变更 |
---|---|
v12.2.0 | 现在支持 enableTrace 选项。 |
v5.0.0 | 现在支持 ALPN 选项。 |
v0.11.4 | 新增于: v0.11.4 |
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
为 true)可以将requestCert
设置为 true 以请求客户端证书。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'
新增于:v12.3.0, v10.20.0
line
<Buffer> 以 NSSSSLKEYLOGFILE
格式表示的 ASCII 文本行。
当套接字生成或接收密钥材料时,keylog
事件会在 tls.TLSSocket
上发出。此密钥材料可以存储用于调试,因为它允许解密捕获的 TLS 流量。它可能在握手完成之前或之后多次发出。
一个典型的用例是将接收到的行追加到一个公共文本文件中,该文件稍后由软件(例如 Wireshark)用于解密流量:
const logFile = fs.createWriteStream('/tmp/ssl-keys.log', { flags: 'a' })
// ...
tlsSocket.on('keylog', line => logFile.write(line))
事件:'OCSPResponse'
新增于:v0.11.13
如果在创建 tls.TLSSocket
时设置了 requestOCSP
选项并且已收到 OCSP 响应,则会发出 'OCSPResponse'
事件。调用时,侦听器回调函数将传递一个参数:
response
<Buffer> 服务器的 OCSP 响应
通常,response
是来自服务器 CA 的数字签名对象,其中包含有关服务器证书吊销状态的信息。
事件:'secureConnect'
新增于:v0.11.4
'secureConnect'
事件在新连接的握手过程成功完成后发出。无论服务器证书是否已授权,侦听器回调函数都会被调用。客户端有责任检查 tlsSocket.authorized
属性以确定服务器证书是否由指定的 CA 之一签署。如果 tlsSocket.authorized === false
,则可以通过检查 tlsSocket.authorizationError
属性找到错误。如果使用了 ALPN,则可以检查 tlsSocket.alpnProtocol
属性以确定协商的协议。
当使用 new tls.TLSSocket()
构造函数创建 <tls.TLSSocket> 时,不会发出 'secureConnect'
事件。
事件:'session'
新增于:v11.10.0
session
<Buffer>
当新的会话或 TLS 票据可用时,'session'
事件会在客户端 tls.TLSSocket
上发出。这可能在握手完成之前或之后,取决于协商的 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()
[历史]
版本 | 变更 |
---|---|
v18.4.0 | family 属性现在返回字符串而不是数字。 |
v18.0.0 | family 属性现在返回数字而不是字符串。 |
v0.11.4 | 新增于:v0.11.4 |
- 返回值: <对象>
返回由操作系统报告的基础套接字的绑定 address
、地址 family
名称和 port
:{ port: 12346, family: 'IPv4', address: '127.0.0.1' }
。
tlsSocket.authorizationError
新增于:v0.11.4
返回对等方证书未经验证的原因。仅当 tlsSocket.authorized === false
时设置此属性。
tlsSocket.authorized
新增于:v0.11.4
如果对等方证书已由创建 tls.TLSSocket
实例时指定的 CA 之一签名,则此属性为 true
,否则为 false
。
tlsSocket.disableRenegotiation()
新增于:v8.4.0
禁用此 TLSSocket
实例的 TLS 重新协商。调用此方法后,尝试重新协商将触发 TLSSocket
上的 'error'
事件。
tlsSocket.enableTrace()
新增于:v12.2.0
启用后,TLS 数据包跟踪信息将写入 stderr
。这可用于调试 TLS 连接问题。
输出格式与 openssl s_client -trace
或 openssl s_server -trace
的输出相同。虽然它是由 OpenSSL 的 SSL_trace()
函数生成的,但其格式未记录,可能随时更改,并且不应依赖于它。
tlsSocket.encrypted
新增于:v0.11.4
始终返回 true
。这可用于区分 TLS 套接字和常规 net.Socket
实例。
tlsSocket.exportKeyingMaterial(length, label[, context])
新增于:v13.10.0, v12.17.0
length
<number> 要从密钥材料中检索的字节数label
<string> 应用程序特定的标签,通常是从 IANA Exporter Label Registry 获取的值。context
<Buffer> 可选地提供上下文。- 返回:<Buffer> 请求的密钥材料字节
密钥材料用于验证,以防止网络协议中各种类型的攻击,例如在 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()
新增于: v11.2.0
- 返回值: <Object>
返回一个表示本地证书的对象。返回的对象包含一些与证书字段对应的属性。
参见 tls.TLSSocket.getPeerCertificate()
查看证书结构示例。
如果没有本地证书,则返回一个空对象。如果套接字已被销毁,则返回 null
。
tlsSocket.getCipher()
[历史]
版本 | 变更 |
---|---|
v13.4.0, v12.16.0 | 返回 IETF 密码名称作为 standardName 。 |
v12.0.0 | 返回最小密码版本,而不是固定字符串 ('TLSv1/SSLv3' )。 |
v0.11.4 | 新增于: v0.11.4 |
- 返回值: <Object>
name
<string> OpenSSL 密码套件名称。standardName
<string> IETF 密码套件名称。version
<string> 此密码套件支持的最小 TLS 协议版本。有关实际协商的协议,请参见tls.TLSSocket.getProtocol()
。
返回一个包含协商密码套件信息的对象。
例如,使用 AES256-SHA 密码的 TLSv1.2 协议:
{
"name": "AES256-SHA",
"standardName": "TLS_RSA_WITH_AES_256_CBC_SHA",
"version": "SSLv3"
}
更多信息,请参见 SSL_CIPHER_get_name。
tlsSocket.getEphemeralKeyInfo()
新增于: v5.0.0
- 返回值: <Object>
返回一个对象,表示客户端连接中完美前向保密的临时密钥交换的参数类型、名称和大小。如果密钥交换不是临时的,则返回一个空对象。由于这仅在客户端套接字上受支持;如果在服务器套接字上调用,则返回null
。支持的类型为'DH'
和'ECDH'
。name
属性仅在类型为'ECDH'
时可用。
例如:{ type: 'ECDH', name: 'prime256v1', size: 256 }
。
tlsSocket.getFinished()
新增于: v9.9.0
- 返回值: <Buffer> | <undefined> 作为 SSL/TLS 握手的一部分发送到套接字的最新
Finished
消息,或者如果尚未发送任何Finished
消息,则返回undefined
。
由于Finished
消息是完整握手的消息摘要(对于 TLS 1.0 总共 192 位,对于 SSL 3.0 更多),因此当 SSL/TLS 提供的身份验证不需要或不足时,它们可用于外部身份验证过程。
对应于 OpenSSL 中的SSL_get_finished
例程,可用于实现来自RFC 5929的tls-unique
通道绑定。
tlsSocket.getPeerCertificate([detailed])
新增于: v0.11.4
返回一个表示对等方证书的对象。如果对等方未提供证书,则返回一个空对象。如果套接字已被销毁,则返回 null
。
如果请求了完整的证书链,则每个证书都将包含一个 issuerCertificate
属性,该属性包含一个表示其颁发者证书的对象。
证书对象
[历史]
版本 | 变更 |
---|---|
v19.1.0, v18.13.0 | 添加 "ca" 属性。 |
v17.2.0, v16.14.0 | 添加 fingerprint512。 |
v11.4.0 | 支持椭圆曲线公钥信息。 |
证书对象具有与证书字段对应的属性。
ca
<boolean> 如果是证书颁发机构 (CA),则为true
,否则为false
。raw
<Buffer> DER 编码的 X.509 证书数据。subject
<Object> 证书主体,用国家/地区 (C
)、州或省 (ST
)、地区 (L
)、组织 (O
)、组织单位 (OU
) 和通用名 (CN
) 来描述。通用名通常是带有 TLS 证书的 DNS 名称。例如:{C: 'UK', ST: 'BC', L: 'Metro', O: 'Node Fans', OU: 'Docs', CN: 'example.com'}
。issuer
<Object> 证书颁发者,用与subject
相同的术语描述。valid_from
<string> 证书有效期开始日期时间。valid_to
<string> 证书有效期结束日期时间。serialNumber
<string> 证书序列号,以十六进制字符串表示。例如:'B9B0D332A1AA5635'
。fingerprint
<string> DER 编码证书的 SHA-1 散列值。它以:
分隔的十六进制字符串形式返回。例如:'2A:7A:C2:DD:...'
。fingerprint256
<string> DER 编码证书的 SHA-256 散列值。它以:
分隔的十六进制字符串形式返回。例如:'2A:7A:C2:DD:...'
。fingerprint512
<string> DER 编码证书的 SHA-512 散列值。它以:
分隔的十六进制字符串形式返回。例如:'2A:7A:C2:DD:...'
。ext_key_usage
<Array> (可选) 扩展密钥用途,一组 OID。subjectaltname
<string> (可选) 包含主体连接名称的字符串,作为subject
名称的替代项。infoAccess
<Array> (可选) 描述 AuthorityInfoAccess 的数组,与 OCSP 一起使用。issuerCertificate
<Object> (可选) 颁发者证书对象。对于自签名证书,这可能是一个循环引用。
证书可能包含有关公钥的信息,具体取决于密钥类型。
对于 RSA 密钥,可能定义以下属性:
bits
<number> RSA 位大小。例如:1024
。exponent
<string> RSA 指数,以十六进制数字表示的字符串表示。例如:'0x010001'
。modulus
<string> RSA 模数,十六进制字符串。例如:'B56CE45CB7...'
。pubkey
<Buffer> 公钥。
对于 EC 密钥,可能定义以下属性:
pubkey
<Buffer> 公钥。bits
<number> 密钥大小(位)。例如:256
。asn1Curve
<string> (可选) 椭圆曲线的 OID 的 ASN.1 名称。众所周知的曲线由 OID 标识。虽然不常见,但曲线也可能由其数学属性标识,在这种情况下,它将没有 OID。例如:'prime256v1'
。nistCurve
<string> (可选) 椭圆曲线的 NIST 名称(如果存在)(并非所有众所周知的曲线都已分配 NIST 名称)。例如:'P-256'
。
示例证书:
{ subject:
{ OU: [ 'Domain Control Validated', 'PositiveSSL Wildcard' ],
CN: '*.nodejs.org' },
issuer:
{ C: 'GB',
ST: 'Greater Manchester',
L: 'Salford',
O: 'COMODO CA Limited',
CN: 'COMODO RSA Domain Validation Secure Server CA' },
subjectaltname: 'DNS:*.nodejs.org, DNS:nodejs.org',
infoAccess:
{ 'CA Issuers - URI':
[ 'http://crt.comodoca.com/COMODORSADomainValidationSecureServerCA.crt' ],
'OCSP - URI': [ 'http://ocsp.comodoca.com' ] },
modulus: 'B56CE45CB740B09A13F64AC543B712FF9EE8E4C284B542A1708A27E82A8D151CA178153E12E6DDA15BF70FFD96CB8A88618641BDFCCA03527E665B70D779C8A349A6F88FD4EF6557180BD4C98192872BCFE3AF56E863C09DDD8BC1EC58DF9D94F914F0369102B2870BECFA1348A0838C9C49BD1C20124B442477572347047506B1FCD658A80D0C44BCC16BC5C5496CFE6E4A8428EF654CD3D8972BF6E5BFAD59D93006830B5EB1056BBB38B53D1464FA6E02BFDF2FF66CD949486F0775EC43034EC2602AEFBF1703AD221DAA2A88353C3B6A688EFE8387811F645CEED7B3FE46E1F8B9F59FAD028F349B9BC14211D5830994D055EEA3D547911E07A0ADDEB8A82B9188E58720D95CD478EEC9AF1F17BE8141BE80906F1A339445A7EB5B285F68039B0F294598A7D1C0005FC22B5271B0752F58CCDEF8C8FD856FB7AE21C80B8A2CE983AE94046E53EDE4CB89F42502D31B5360771C01C80155918637490550E3F555E2EE75CC8C636DDE3633CFEDD62E91BF0F7688273694EEEBA20C2FC9F14A2A435517BC1D7373922463409AB603295CEB0BB53787A334C9CA3CA8B30005C5A62FC0715083462E00719A8FA3ED0A9828C3871360A73F8B04A4FC1E71302844E9BB9940B77E745C9D91F226D71AFCAD4B113AAF68D92B24DDB4A2136B55A1CD1ADF39605B63CB639038ED0F4C987689866743A68769CC55847E4A06D6E2E3F1',
exponent: '0x10001',
pubkey: <Buffer ... >,
valid_from: 'Aug 14 00:00:00 2017 GMT',
valid_to: 'Nov 20 23:59:59 2019 GMT',
fingerprint: '01:02:59:D9:C3:D2:0D:08:F7:82:4E:44:A4:B4:53:C5:E2:3A:87:4D',
fingerprint256: '69:AE:1A:6A:D4:3D:C6:C1:1B:EA:C6:23:DE:BA:2A:14:62:62:93:5C:7A:EA:06:41:9B:0B:BC:87:CE:48:4E:02',
fingerprint512: '19:2B:3E:C3:B3:5B:32:E8:AE:BB:78:97:27:E4:BA:6C:39:C9:92:79:4F:31:46:39:E2:70:E5:5F:89:42:17:C9:E8:64:CA:FF:BB:72:56:73:6E:28:8A:92:7E:A3:2A:15:8B:C2:E0:45:CA:C3:BC:EA:40:52:EC:CA:A2:68:CB:32',
ext_key_usage: [ '1.3.6.1.5.5.7.3.1', '1.3.6.1.5.5.7.3.2' ],
serialNumber: '66593D57F20CBC573E433381B5FEC280',
raw: <Buffer ... > }
tlsSocket.getPeerFinished()
新增于: v9.9.0
- 返回值: <Buffer> | <undefined> 作为 SSL/TLS 握手一部分,从套接字预期或实际接收到的最新的
Finished
消息,如果目前没有Finished
消息则返回undefined
。
由于 Finished
消息是完整握手的消息摘要(TLS 1.0 总共 192 位,SSL 3.0 更多),当 SSL/TLS 提供的认证不足或不需要时,它们可用于外部认证过程。
对应于 OpenSSL 中的 SSL_get_peer_finished
例程,可用于实现 RFC 5929 中的 tls-unique
通道绑定。
tlsSocket.getPeerX509Certificate()
新增于: v15.9.0
- 返回值: <X509Certificate>
返回对端证书作为 <X509Certificate> 对象。
如果没有对端证书,或套接字已被销毁,则返回 undefined
。
tlsSocket.getProtocol()
新增于:v5.7.0
返回一个字符串,包含当前连接协商的 SSL/TLS 协议版本。对于尚未完成握手过程的已连接套接字,将返回 'unknown'
值。对于服务器套接字或已断开的客户端套接字,将返回 null
值。
协议版本包括:
'SSLv3'
'TLSv1'
'TLSv1.1'
'TLSv1.2'
'TLSv1.3'
更多信息请参见 OpenSSL 的 SSL_get_version
文档。
tlsSocket.getSession()
新增于:v0.11.4
返回 TLS 会话数据,如果未协商会话则返回 undefined
。在客户端,该数据可以提供给 tls.connect()
的 session
选项以恢复连接。在服务器端,它可能对调试有用。
更多信息请参见 会话恢复。
注意:getSession()
仅适用于 TLSv1.2 及以下版本。对于 TLSv1.3,应用程序必须使用 'session'
事件(它也适用于 TLSv1.2 及以下版本)。
tlsSocket.getSharedSigalgs()
新增于:v12.11.0
- 返回值:
<Array>
服务器和客户端之间共享的签名算法列表,按优先级递减排序。
更多信息请参见 SSL_get_shared_sigalgs。
tlsSocket.getTLSTicket()
新增于:v0.11.4
对于客户端,如果可用,则返回 TLS 会话票据,否则返回 undefined
。对于服务器,始终返回 undefined
。
它可能对调试有用。
更多信息请参见 会话恢复。
tlsSocket.getX509Certificate()
新增于:v15.9.0
- 返回值:
<X509Certificate>
返回本地证书作为 <X509Certificate>
对象。
如果没有本地证书,或者套接字已被销毁,则返回 undefined
。
tlsSocket.isSessionReused()
新增于: v0.5.6
- 返回值: <boolean> 如果会话被重用,则返回
true
,否则返回false
。
更多信息参见 会话恢复。
tlsSocket.localAddress
新增于: v0.11.4
返回本地 IP 地址的字符串表示形式。
tlsSocket.localPort
新增于: v0.11.4
返回本地端口的数字表示形式。
tlsSocket.remoteAddress
新增于: v0.11.4
返回远程 IP 地址的字符串表示形式。例如,'74.125.127.100'
或 '2001:4860:a005::68'
。
tlsSocket.remoteFamily
新增于: v0.11.4
返回远程 IP 族类的字符串表示形式。'IPv4'
或 'IPv6'
。
tlsSocket.remotePort
新增于:v0.11.4
返回远程端口的数字表示。例如,443
。
tlsSocket.renegotiate(options, callback)
[历史]
版本 | 变更 |
---|---|
v18.0.0 | 将无效回调传递给 callback 参数现在抛出 ERR_INVALID_ARG_TYPE 而不是 ERR_INVALID_CALLBACK 。 |
v0.11.8 | 新增于:v0.11.8 |
options
<对象>rejectUnauthorized
<布尔值> 如果不是false
,则服务器证书将针对提供的 CA 列表进行验证。如果验证失败,则会发出'error'
事件;err.code
包含 OpenSSL 错误代码。默认值:true
。requestCert
callback
<函数> 如果renegotiate()
返回true
,则回调将附加到'secure'
事件一次。如果renegotiate()
返回false
,则callback
将在下一次 tick 中使用错误调用,除非tlsSocket
已被销毁,在这种情况下,callback
将根本不会被调用。返回值: <布尔值> 如果启动了重新协商,则返回
true
,否则返回false
。
tlsSocket.renegotiate()
方法启动 TLS 重新协商过程。完成后,callback
函数将传递一个参数,该参数或者是 Error
(如果请求失败)或者是 null
。
此方法可用于在建立安全连接后请求对等方的证书。
在作为服务器运行时,套接字将在 handshakeTimeout
超时后销毁并报错。
对于 TLSv1.3,无法启动重新协商,该协议不支持它。
tlsSocket.setKeyCert(context)
新增于:v22.5.0, v20.17.0
context
<Object> | <tls.SecureContext> 包含至少key
和cert
属性的对象,这些属性来自tls.createSecureContext()
的options
,或者是由tls.createSecureContext()
创建的 TLS 上下文对象本身。
tlsSocket.setKeyCert()
方法设置套接字使用的私钥和证书。如果您希望从 TLS 服务器的 ALPNCallback
中选择服务器证书,则此方法非常有用。
tlsSocket.setMaxSendFragment(size)
新增于:v0.11.11
tlsSocket.setMaxSendFragment()
方法设置最大 TLS 分片大小。如果设置限制成功,则返回 true
;否则返回 false
。
较小的分片大小会减少客户端的缓冲延迟:较大的分片会由 TLS 层缓冲,直到接收整个分片并验证其完整性;较大的分片可能会跨越多个往返行程,并且由于数据包丢失或重新排序,它们的处理可能会延迟。但是,较小的分片会增加额外的 TLS 帧字节和 CPU 开销,这可能会降低服务器的整体吞吐量。
tls.checkServerIdentity(hostname, cert)
[历史]
版本 | 变更 |
---|---|
v17.3.1, v16.13.2, v14.18.3, v12.22.9 | 针对 CVE-2021-44531,已禁用对 uniformResourceIdentifier 主题替代名称的支持。 |
v0.8.4 | 添加于:v0.8.4 |
验证证书 cert
是否颁发给 hostname
。
失败时返回 <错误> 对象,其中包含 reason
、host
和 cert
信息。成功时返回 <未定义>。
此函数旨在与可传递给 tls.connect()
的 checkServerIdentity
选项结合使用,因此它操作的是 证书对象。对于其他用途,请考虑改用 x509.checkHost()
。
可以通过提供替代函数作为传递给 tls.connect()
的 options.checkServerIdentity
选项来覆盖此函数。当然,覆盖函数可以调用 tls.checkServerIdentity()
来增强已完成的检查,并进行额外的验证。
只有当证书通过所有其他检查(例如由受信任的 CA (options.ca
) 颁发)时,才会调用此函数。
早期版本的 Node.js 如果存在匹配的 uniformResourceIdentifier
主题替代名称,则会错误地接受给定 hostname
的证书(参见 CVE-2021-44531)。希望接受 uniformResourceIdentifier
主题替代名称的应用程序可以使用自定义的 options.checkServerIdentity
函数来实现所需的行为。
tls.connect(options[, callback])
[历史]
版本 | 变更 |
---|---|
v15.1.0, v14.18.0 | 新增 onread 选项。 |
v14.1.0, v13.14.0 | 现在接受 highWaterMark 选项。 |
v13.6.0, v12.16.0 | 现在支持 pskCallback 选项。 |
v12.9.0 | 支持 allowHalfOpen 选项。 |
v12.4.0 | 现在支持 hints 选项。 |
v12.2.0 | 现在支持 enableTrace 选项。 |
v11.8.0, v10.16.0 | 现在支持 timeout 选项。 |
v8.0.0 | 现在支持 lookup 选项。 |
v8.0.0 | ALPNProtocols 选项现在可以是 TypedArray 或 DataView 。 |
v5.0.0 | 现在支持 ALPN 选项。 |
v5.3.0, v4.7.0 | 现在支持 secureContext 选项。 |
v0.11.3 | 新增于:v0.11.3 |
options
<对象>enableTrace
: 查看tls.createServer()
host
<字符串> 客户端应连接到的主机。默认值:'localhost'
。port
<数字> 客户端应连接到的端口。path
<字符串> 创建到路径的 Unix 套接字连接。如果指定此选项,则忽略host
和port
。socket
<stream.Duplex> 在给定的套接字上建立安全连接,而不是创建新的套接字。通常,这是一个net.Socket
的实例,但允许任何Duplex
流。如果指定此选项,则忽略path
、host
和port
,证书验证除外。通常,将套接字传递给tls.connect()
时,它已经连接,但稍后也可以连接。socket
的连接/断开连接/销毁由用户负责;调用tls.connect()
不会导致调用net.connect()
。allowHalfOpen
<布尔值> 如果设置为false
,则当可读端结束时,套接字将自动结束可写端。如果设置了socket
选项,则此选项无效。有关详细信息,请参阅net.Socket
的allowHalfOpen
选项。默认值:false
。rejectUnauthorized
<布尔值> 如果不是false
,则服务器证书将针对提供的 CA 列表进行验证。如果验证失败,则会发出'error'
事件;err.code
包含 OpenSSL 错误代码。默认值:true
。pskCallback
<函数> 对于 TLS-PSK 协商,请参阅 预共享密钥。ALPNProtocols
: <字符串[]> | <Buffer[]> | <TypedArray[]> | <DataView[]> | <Buffer> | <TypedArray> | <DataView> 字符串、Buffer
、TypedArray
或DataView
的数组,或者包含受支持的 ALPN 协议的单个Buffer
、TypedArray
或DataView
。Buffer
应具有[len][name][len][name]...
格式,例如'\x08http/1.1\x08http/1.0'
,其中len
字节是下一个协议名称的长度。传递数组通常要简单得多,例如['http/1.1', 'http/1.0']
。列表中较早的协议比较晚的协议具有更高的优先级。servername
: <字符串> SNI(服务器名称指示)TLS 扩展的服务器名称。它是正在连接到的主机的名称,必须是主机名,而不是 IP 地址。它可以被多宿主服务器用来选择正确的证书来呈现给客户端,参见tls.createServer()
的SNICallback
选项。checkServerIdentity(servername, cert)
<函数> 在检查服务器的主机名(或显式设置的servername
)与证书是否匹配时,将使用此回调函数(而不是内置的tls.checkServerIdentity()
函数)。如果验证失败,则应返回 <错误>。如果servername
和cert
已验证,则此方法应返回undefined
。session
<Buffer> 一个Buffer
实例,包含 TLS 会话。minDHSize
<数字> 接受 TLS 连接的 DH 参数的最小大小(以位为单位)。当服务器提供的 DH 参数大小小于minDHSize
时,TLS 连接将被销毁并抛出错误。默认值:1024
。highWaterMark
: <数字> 与可读流highWaterMark
参数一致。默认值:16 * 1024
。secureContext
: 使用tls.createSecureContext()
创建的 TLS 上下文对象。如果没有提供secureContext
,则会通过将整个options
对象传递给tls.createSecureContext()
来创建一个。onread
<对象> 如果缺少socket
选项,则传入数据将存储在一个buffer
中,并在数据到达套接字时传递给提供的callback
,否则忽略该选项。有关详细信息,请参阅net.Socket
的onread
选项。- ...:
tls.createSecureContext()
中使用的选项,如果缺少secureContext
选项,则使用这些选项,否则忽略它们。 - ...: 所有未列出的
socket.connect()
选项。
callback
<函数>返回值: <tls.TLSSocket>
如果指定了 callback
函数,它将被添加为 'secureConnect'
事件的监听器。
tls.connect()
返回一个 tls.TLSSocket
对象。
与 https
API 不同,tls.connect()
默认情况下不启用 SNI(服务器名称指示)扩展,这可能会导致某些服务器返回不正确的证书或完全拒绝连接。要启用 SNI,请除了 host
之外还要设置 servername
选项。
以下是 tls.createServer()
中回显服务器示例的客户端示例:
// 假设回显服务器正在端口 8000 上监听。
import { connect } from 'node:tls'
import { readFileSync } from 'node:fs'
import { stdin } from 'node:process'
const options = {
// 仅当服务器需要客户端证书身份验证时才需要。
key: readFileSync('client-key.pem'),
cert: readFileSync('client-cert.pem'),
// 仅当服务器使用自签名证书时才需要。
ca: [readFileSync('server-cert.pem')],
// 仅当服务器的证书不是针对“localhost”时才需要。
checkServerIdentity: () => {
return null
},
}
const socket = connect(8000, options, () => {
console.log('客户端已连接', socket.authorized ? '已授权' : '未授权')
stdin.pipe(socket)
stdin.resume()
})
socket.setEncoding('utf8')
socket.on('data', data => {
console.log(data)
})
socket.on('end', () => {
console.log('服务器结束连接')
})
// 假设回显服务器正在端口 8000 上监听。
const { connect } = require('node:tls')
const { readFileSync } = require('node:fs')
const options = {
// 仅当服务器需要客户端证书身份验证时才需要。
key: readFileSync('client-key.pem'),
cert: readFileSync('client-cert.pem'),
// 仅当服务器使用自签名证书时才需要。
ca: [readFileSync('server-cert.pem')],
// 仅当服务器的证书不是针对“localhost”时才需要。
checkServerIdentity: () => {
return null
},
}
const socket = connect(8000, options, () => {
console.log('客户端已连接', socket.authorized ? '已授权' : '未授权')
process.stdin.pipe(socket)
process.stdin.resume()
})
socket.setEncoding('utf8')
socket.on('data', data => {
console.log(data)
})
socket.on('end', () => {
console.log('服务器结束连接')
})
要为此示例生成证书和密钥,请运行:
openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \
-keyout client-key.pem -out client-cert.pem
然后,要为此示例生成 server-cert.pem
证书,请运行:
openssl pkcs12 -certpbe AES-256-CBC -export -out server-cert.pem \
-inkey client-key.pem -in client-cert.pem
tls.connect(path[, options][, callback])
新增于: v0.11.3
path
<string>options.path
的默认值。options
<Object> 参见tls.connect()
。callback
<Function> 参见tls.connect()
。- 返回值: <tls.TLSSocket>
与 tls.connect()
相同,除了 path
可以作为参数而不是选项提供。
如果指定了 path 选项,则它将优先于 path 参数。
tls.connect(port[, host][, options][, callback])
新增于: v0.11.3
port
<number>options.port
的默认值。host
<string>options.host
的默认值。options
<Object> 参见tls.connect()
。callback
<Function> 参见tls.connect()
。- 返回值: <tls.TLSSocket>
与 tls.connect()
相同,除了 port
和 host
可以作为参数而不是选项提供。
如果指定了端口或主机选项,则它将优先于任何端口或主机参数。
tls.createSecureContext([options])
[历史]
版本 | 变更 |
---|---|
v22.9.0, v20.18.0 | 添加了 allowPartialTrustChain 选项。 |
v22.4.0, v20.16.0 | clientCertEngine 、privateKeyEngine 和 privateKeyIdentifier 选项依赖于 OpenSSL 中的自定义引擎支持,该支持在 OpenSSL 3 中已弃用。 |
v19.8.0, v18.16.0 | dhparam 选项现在可以设置为 'auto' 以使用适当的知名参数启用 DHE。 |
v12.12.0 | 添加了 privateKeyIdentifier 和 privateKeyEngine 选项,用于从 OpenSSL 引擎获取私钥。 |
v12.11.0 | 添加了 sigalgs 选项以覆盖支持的签名算法。 |
v12.0.0 | 添加了 TLSv1.3 支持。 |
v11.5.0 | ca: 选项现在支持 BEGIN TRUSTED CERTIFICATE 。 |
v11.4.0, v10.16.0 | 可以使用 minVersion 和 maxVersion 来限制允许的 TLS 协议版本。 |
v10.0.0 | 由于 OpenSSL 的更改,ecdhCurve 不能再设置为 false 。 |
v9.3.0 | options 参数现在可以包含 clientCertEngine 。 |
v9.0.0 | ecdhCurve 选项现在可以是多个以 ':' 分隔的曲线名称或 'auto' 。 |
v7.3.0 | 如果 key 选项是一个数组,则各个条目不再需要 passphrase 属性。Array 条目现在也可以只是 string 或 Buffer 。 |
v5.2.0 | ca 选项现在可以是一个包含多个 CA 证书的单个字符串。 |
v0.11.13 | 添加于:v0.11.13 |
options
<对象>allowPartialTrustChain
<布尔值> 将信任 CA 证书列表中的中间(非自签名)证书视为受信任证书。ca
<字符串> | <字符串数组> | <Buffer> | <Buffer 数组> 可选地覆盖受信任的 CA 证书。默认情况下,信任 Mozilla 策划的知名 CA。当使用此选项显式指定 CA 时,Mozilla 的 CA 将被完全替换。该值可以是字符串或Buffer
,也可以是字符串和/或Buffer
的Array
。任何字符串或Buffer
都可以包含多个连接在一起的 PEM CA。对等方的证书必须可与服务器信任的 CA 连接,才能对连接进行身份验证。当使用不可与知名 CA 连接的证书时,必须将证书的 CA 显式指定为受信任的,否则连接将无法进行身份验证。如果对等方使用与默认 CA 不匹配或与其不连接的证书,请使用ca
选项提供对等方证书可以匹配或与其连接的 CA 证书。对于自签名证书,证书本身就是其 CA,必须提供。对于 PEM 编码的证书,支持的类型为“TRUSTED CERTIFICATE”、“X509 CERTIFICATE”和“CERTIFICATE”。另请参见tls.rootCertificates
。cert
<字符串> | <字符串数组> | <Buffer> | <Buffer 数组> PEM 格式的证书链。应为每个私钥提供一个证书链。每个证书链都应包含提供的私有key
的 PEM 格式证书,后跟 PEM 格式的中间证书(如有),按顺序排列,但不包括根 CA(根 CA 必须为对等方预先知道,请参见ca
)。提供多个证书链时,它们不必与key
中的私钥顺序相同。如果没有提供中间证书,则对等方将无法验证证书,握手将失败。sigalgs
<字符串> 以冒号分隔的支持签名算法列表。该列表可以包含摘要算法(SHA256
、MD5
等)、公钥算法(RSA-PSS
、ECDSA
等)、两者的组合(例如 'RSA+SHA384')或 TLS v1.3 方案名称(例如rsa_pss_pss_sha512
)。有关更多信息,请参见 OpenSSL 手册页。ciphers
<字符串> 密码套件规范,替换默认值。有关更多信息,请参见 修改默认 TLS 密码套件。允许的密码可以通过tls.getCiphers()
获取。为了让 OpenSSL 接受密码名称,必须将其大写。clientCertEngine
<字符串> 可以提供客户端证书的 OpenSSL 引擎的名称。已弃用。crl
<字符串> | <字符串数组> | <Buffer> | <Buffer 数组> PEM 格式的 CRL(证书吊销列表)。dhparam
<字符串> | <Buffer>'auto'
或自定义 Diffie-Hellman 参数,非 ECDHE 完美前向保密 所需。如果省略或无效,则参数将被静默丢弃,并且 DHE 密码将不可用。ECDHE 基于的 完美前向保密 仍然可用。ecdhCurve
<字符串> 描述命名曲线或以冒号分隔的曲线 NID 或名称列表(例如P-521:P-384:P-256
)的字符串,用于 ECDH 密钥协商。设置为auto
以自动选择曲线。使用crypto.getCurves()
获取可用曲线名称列表。在最新版本中,openssl ecparam -list_curves
也会显示每条可用椭圆曲线的名称和描述。默认值:tls.DEFAULT_ECDH_CURVE
。honorCipherOrder
<布尔值> 尝试使用服务器的密码套件首选项而不是客户端的密码套件首选项。设置为true
时,会导致在secureOptions
中设置SSL_OP_CIPHER_SERVER_PREFERENCE
,有关更多信息,请参见 OpenSSL 选项。key
<字符串> | <字符串数组> | <Buffer> | <Buffer 数组> | <对象数组> PEM 格式的私钥。PEM 允许私钥被加密。加密的密钥将使用options.passphrase
解密。可以使用不同算法的多个密钥,可以作为未加密密钥字符串或缓冲区的数组,也可以作为{pem: \<string|buffer\>[, passphrase: \<string\>]}
形式的对象数组提供。对象形式只能出现在数组中。object.passphrase
是可选的。如果提供了加密密钥,则使用object.passphrase
解密,如果没有提供,则使用options.passphrase
解密。privateKeyEngine
<字符串> 获取私钥的 OpenSSL 引擎的名称。应与privateKeyIdentifier
一起使用。已弃用。privateKeyIdentifier
<字符串> OpenSSL 引擎管理的私钥的标识符。应与privateKeyEngine
一起使用。不应与key
一起设置,因为这两个选项都以不同的方式定义私钥。已弃用。maxVersion
<字符串> 可选地设置允许的最大 TLS 版本。'TLSv1.3'
、'TLSv1.2'
、'TLSv1.1'
或'TLSv1'
之一。不能与secureProtocol
选项一起指定;请使用其中一个。默认值:tls.DEFAULT_MAX_VERSION
。minVersion
<字符串> 可选地设置允许的最小 TLS 版本。'TLSv1.3'
、'TLSv1.2'
、'TLSv1.1'
或'TLSv1'
之一。不能与secureProtocol
选项一起指定;请使用其中一个。避免设置为低于 TLSv1.2,但这可能需要进行互操作性。TLSv1.2 之前的版本可能需要降级 OpenSSL 安全级别。默认值:tls.DEFAULT_MIN_VERSION
。passphrase
<字符串> 用于单个私钥和/或 PFX 的共享密码。pfx
<字符串> | <字符串数组> | <Buffer> | <Buffer 数组> | <对象数组> PFX 或 PKCS12 编码的私钥和证书链。pfx
是单独提供key
和cert
的替代方法。PFX 通常是加密的,如果是,则将使用passphrase
解密它。可以将多个 PFX 提供为未加密 PFX 缓冲区的数组,也可以提供为{buf: \<string|buffer\>[, passphrase: \<string\>]}
形式的对象数组。对象形式只能出现在数组中。object.passphrase
是可选的。如果提供了加密的 PFX,则使用object.passphrase
解密,如果没有提供,则使用options.passphrase
解密。secureOptions
<数字> 可选地影响 OpenSSL 协议行为,这通常是不必要的。如果使用的话,应该谨慎使用!该值是来自 OpenSSL 选项 的SSL_OP_*
选项的数字位掩码。secureProtocol
<字符串> 用于选择要使用的 TLS 协议版本的旧机制,它不支持独立控制最小和最大版本,也不支持将协议限制为 TLSv1.3。请改用minVersion
和maxVersion
。可能的值列为 SSL_METHODS,将函数名称用作字符串。例如,使用'TLSv1_1_method'
强制使用 TLS 版本 1.1,或使用'TLS_method'
允许任何 TLS 协议版本,直到 TLSv1.3。不建议使用低于 1.2 的 TLS 版本,但这可能需要进行互操作性。默认值: 无,请参见minVersion
。sessionIdContext
<字符串> 服务器用于确保会话状态不会在应用程序之间共享的不透明标识符。客户端不使用。ticketKeys
: <Buffer> 48 字节的密码学强伪随机数据。有关更多信息,请参见 会话恢复。sessionTimeout
<数字> 服务器创建的 TLS 会话不再可恢复之前的秒数。有关更多信息,请参见 会话恢复。默认值:300
。
tls.createServer()
将 honorCipherOrder
选项的默认值设置为 true
,其他创建安全上下文的 API 则不设置该值。
tls.createServer()
使用从 process.argv
生成的 128 位截断的 SHA1 哈希值作为 sessionIdContext
选项的默认值,其他创建安全上下文的 API 没有默认值。
tls.createSecureContext()
方法创建一个 SecureContext
对象。它可用作多个 tls
API 的参数,例如 server.addContext()
,但没有公共方法。tls.Server
构造函数和 tls.createServer()
方法不支持 secureContext
选项。
对于使用证书的密码,密钥是必需的。可以使用 key
或 pfx
提供密钥。
如果没有提供 ca
选项,则 Node.js 将默认使用 Mozilla 的公开受信任的 CA 列表。
不建议使用自定义 DHE 参数,而是建议使用新的 dhparam: 'auto'
选项。设置为 'auto'
时,将自动选择具有足够强度的知名 DHE 参数。否则,如有必要,可以使用 openssl dhparam
创建自定义参数。密钥长度必须大于或等于 1024 位,否则将抛出错误。虽然允许使用 1024 位,但为了更强的安全性,请使用 2048 位或更大的密钥长度。
tls.createSecurePair([context][, isServer][, requestCert][, rejectUnauthorized][, options])
[历史]
版本 | 变更 |
---|---|
v5.0.0 | 现在支持 ALPN 选项。 |
v0.11.3 | 自 v0.11.3 起已弃用 |
v0.3.2 | 添加于:v0.3.2 |
[稳定性:0 - 已弃用]
稳定性:0 稳定性:0 - 已弃用:请改用 tls.TLSSocket
。
context
<对象> 由tls.createSecureContext()
返回的安全上下文对象isServer
<布尔值>true
指定此 TLS 连接应作为服务器打开。requestCert
<布尔值>true
指定服务器是否应向连接的客户端请求证书。仅当isServer
为true
时适用。rejectUnauthorized
<布尔值> 如果不是false
,服务器会自动拒绝具有无效证书的客户端。仅当isServer
为true
时适用。options
enableTrace
: 请参见tls.createServer()
secureContext
: 来自tls.createSecureContext()
的 TLS 上下文对象isServer
: 如果为true
,则 TLS 套接字将以服务器模式实例化。默认值:false
。server
<net.Server> 一个net.Server
实例requestCert
: 请参见tls.createServer()
rejectUnauthorized
: 请参见tls.createServer()
ALPNProtocols
: 请参见tls.createServer()
SNICallback
: 请参见tls.createServer()
session
<缓冲区> 包含 TLS 会话的Buffer
实例。requestOCSP
<布尔值> 如果为true
,则指定将 OCSP 状态请求扩展添加到客户端 hello,并在建立安全通信之前在套接字上发出'OCSPResponse'
事件。
创建新的安全对对象,其中包含两个流,一个读取和写入加密数据,另一个读取和写入明文数据。通常,加密流通过传入的加密数据流进行管道传输,而明文流则用作初始加密流的替代。
tls.createSecurePair()
返回一个 tls.SecurePair
对象,该对象具有 cleartext
和 encrypted
流属性。
使用 cleartext
的 API 与 tls.TLSSocket
相同。
tls.createSecurePair()
方法现在已被弃用,建议使用 tls.TLSSocket()
。例如,代码:
pair = tls.createSecurePair(/* ... */)
pair.encrypted.pipe(socket)
socket.pipe(pair.encrypted)
可以替换为:
secureSocket = tls.TLSSocket(socket, options)
其中 secureSocket
的 API 与 pair.cleartext
相同。
tls.createServer([options][, secureConnectionListener])
[历史]
版本 | 变更 |
---|---|
v22.4.0, v20.16.0 | clientCertEngine 选项依赖于 OpenSSL 中的自定义引擎支持,该支持在 OpenSSL 3 中已弃用。 |
v19.0.0 | 如果设置了 ALPNProtocols ,则发送具有任何不受支持协议的 ALPN 扩展的传入连接将使用致命的 no_application_protocol 警报终止。 |
v20.4.0, v18.19.0 | options 参数现在可以包含 ALPNCallback 。 |
v12.3.0 | options 参数现在支持 net.createServer() 选项。 |
v9.3.0 | options 参数现在可以包含 clientCertEngine 。 |
v8.0.0 | ALPNProtocols 选项现在可以是 TypedArray 或 DataView 。 |
v5.0.0 | 现在支持 ALPN 选项。 |
v0.3.2 | 新增于:v0.3.2 |
options
<对象>ALPNProtocols
: <字符串数组> | <Buffer 数组> | <TypedArray 数组> | <DataView 数组> | <Buffer> | <TypedArray> | <DataView> 支持的 ALPN 协议的字符串、Buffer
、TypedArray
或DataView
数组,或包含支持的 ALPN 协议的单个Buffer
、TypedArray
或DataView
。Buffer
应具有[len][name][len][name]...
格式,例如0x05hello0x05world
,其中第一个字节是下一个协议名称的长度。传递数组通常更简单,例如['hello', 'world']
。(协议应按优先级排序。)ALPNCallback
: <函数> 如果设置,则当客户端使用 ALPN 扩展打开连接时,将调用此函数。将向回调传递一个参数:一个包含servername
和protocols
字段的对象,分别包含来自 SNI 扩展(如果有)的服务器名称和 ALPN 协议名称字符串数组。回调必须返回protocols
中列出的字符串之一,该字符串将作为选定的 ALPN 协议返回给客户端,或返回undefined
,以致命的警报拒绝连接。如果返回的字符串与客户端的任何 ALPN 协议都不匹配,则会抛出错误。此选项不能与ALPNProtocols
选项一起使用,并且同时设置这两个选项将抛出错误。clientCertEngine
<字符串> 可以提供客户端证书的 OpenSSL 引擎的名称。已弃用。enableTrace
<布尔值> 如果为true
,则会在新连接上调用tls.TLSSocket.enableTrace()
。可以在建立安全连接后启用跟踪,但必须使用此选项来跟踪安全连接设置。默认值:false
。handshakeTimeout
<数字> 如果 SSL/TLS 握手未在指定毫秒数内完成,则中止连接。每当握手超时时,都会在tls.Server
对象上发出'tlsClientError'
。默认值:120000
(120 秒)。rejectUnauthorized
<布尔值> 如果不是false
,则服务器将拒绝任何未经提供的 CA 列表授权的连接。此选项只有在requestCert
为true
时才有效。默认值:true
。requestCert
<布尔值> 如果为true
,则服务器将请求连接的客户端的证书,并尝试验证该证书。默认值:false
。sessionTimeout
<数字> 服务器创建的 TLS 会话在不再可恢复之前经过的秒数。有关详细信息,请参阅 会话恢复。默认值:300
。SNICallback(servername, callback)
<函数> 如果客户端支持 SNI TLS 扩展,则将调用此函数。调用时将传递两个参数:servername
和callback
。callback
是一个错误优先回调,它接受两个可选参数:error
和ctx
。如果提供,ctx
是SecureContext
实例。tls.createSecureContext()
可用于获取正确的SecureContext
。如果callback
使用虚假ctx
参数调用,则将使用服务器的默认安全上下文。如果未提供SNICallback
,则将使用具有高级 API 的默认回调(见下文)。ticketKeys
: <Buffer> 48 字节的加密强伪随机数据。有关详细信息,请参阅 会话恢复。pskCallback
<函数> 对于 TLS-PSK 协商,请参阅 预共享密钥。pskIdentityHint
<字符串> 可选提示,发送给客户端以帮助在 TLS-PSK 协商期间选择身份。将在 TLS 1.3 中忽略。无法设置pskIdentityHint
时,将发出带有'ERR_TLS_PSK_SET_IDENTITY_HINT_FAILED'
代码的'tlsClientError'
。- ...: 可以提供任何
tls.createSecureContext()
选项。对于服务器,通常需要身份选项(pfx
、key
/cert
或pskCallback
)。 - ...: 可以提供任何
net.createServer()
选项。
secureConnectionListener
<函数>返回值: <tls.Server>
创建一个新的 tls.Server
。如果提供了 secureConnectionListener
,则会自动将其设置为 'secureConnection'
事件的侦听器。
ticketKeys
选项会在 node:cluster
模块工作进程之间自动共享。
以下说明了一个简单的回显服务器:
import { createServer } from 'node:tls'
import { readFileSync } from 'node:fs'
const options = {
key: readFileSync('server-key.pem'),
cert: readFileSync('server-cert.pem'),
// 这仅在使用客户端证书身份验证时才需要。
requestCert: true,
// 这仅在客户端使用自签名证书时才需要。
ca: [readFileSync('client-cert.pem')],
}
const server = createServer(options, socket => {
console.log('服务器已连接', socket.authorized ? '已授权' : '未授权')
socket.write('欢迎!\n')
socket.setEncoding('utf8')
socket.pipe(socket)
})
server.listen(8000, () => {
console.log('服务器已绑定')
})
const { createServer } = require('node:tls')
const { readFileSync } = require('node:fs')
const options = {
key: readFileSync('server-key.pem'),
cert: readFileSync('server-cert.pem'),
// 这仅在使用客户端证书身份验证时才需要。
requestCert: true,
// 这仅在客户端使用自签名证书时才需要。
ca: [readFileSync('client-cert.pem')],
}
const server = createServer(options, socket => {
console.log('服务器已连接', socket.authorized ? '已授权' : '未授权')
socket.write('欢迎!\n')
socket.setEncoding('utf8')
socket.pipe(socket)
})
server.listen(8000, () => {
console.log('服务器已绑定')
})
要为此示例生成证书和密钥,请运行:
openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \
-keyout server-key.pem -out server-cert.pem
然后,要为此示例生成 client-cert.pem
证书,请运行:
openssl pkcs12 -certpbe AES-256-CBC -export -out client-cert.pem \
-inkey server-key.pem -in server-cert.pem
可以使用 tls.connect()
中的示例客户端来测试服务器。
tls.getCiphers()
Added in: v0.10.2
- 返回: <string[]>
返回一个包含支持的 TLS 密码套件名称的数组。出于历史原因,名称都小写,但必须大写才能在 tls.createSecureContext()
的 ciphers
选项中使用。
并非所有受支持的密码套件都默认启用。参见 修改默认 TLS 密码套件。
以 'tls_'
开头的密码套件名称用于 TLSv1.3,所有其他名称都用于 TLSv1.2 及以下版本。
console.log(tls.getCiphers()) // ['aes128-gcm-sha256', 'aes128-sha', ...]
tls.rootCertificates
Added in: v12.3.0
一个不可变的字符串数组,表示当前 Node.js 版本提供的捆绑的 Mozilla CA 存储中的根证书(PEM 格式)。
Node.js 提供的捆绑 CA 存储是 Mozilla CA 存储的快照,在发布时固定。在所有支持的平台上都相同。
tls.DEFAULT_ECDH_CURVE
[历史]
版本 | 变更 |
---|---|
v10.0.0 | 默认值更改为 'auto' 。 |
v0.11.13 | 新增于:v0.11.13 |
tls 服务器中用于 ECDH 密钥协商的默认曲线名称。默认值为 'auto'
。有关详细信息,请参阅 tls.createSecureContext()
。
tls.DEFAULT_MAX_VERSION
新增于:v11.4.0
- <字符串>
tls.createSecureContext()
的maxVersion
选项的默认值。它可以赋值为任何受支持的 TLS 协议版本,'TLSv1.3'
、'TLSv1.2'
、'TLSv1.1'
或'TLSv1'
。默认值:'TLSv1.3'
,除非使用 CLI 选项更改。使用--tls-max-v1.2
将默认值设置为'TLSv1.2'
。使用--tls-max-v1.3
将默认值设置为'TLSv1.3'
。如果提供了多个选项,则使用最高的最大值。
tls.DEFAULT_MIN_VERSION
新增于: v11.4.0
- <字符串>
tls.createSecureContext()
的minVersion
选项的默认值。它可以被赋予任何受支持的 TLS 协议版本,'TLSv1.3'
,'TLSv1.2'
,'TLSv1.1'
或'TLSv1'
。低于 TLSv1.2 的版本可能需要降低 OpenSSL 安全级别。默认值:'TLSv1.2'
,除非使用 CLI 选项更改。使用--tls-min-v1.0
将默认值设置为'TLSv1'
。使用--tls-min-v1.1
将默认值设置为'TLSv1.1'
。使用--tls-min-v1.3
将默认值设置为'TLSv1.3'
。如果提供了多个选项,则使用最低的最小值。
tls.DEFAULT_CIPHERS
新增于: v19.8.0, v18.16.0
- <字符串>
tls.createSecureContext()
的ciphers
选项的默认值。它可以被赋予任何受支持的 OpenSSL 密码。默认为crypto.constants.defaultCoreCipherList
的内容,除非使用--tls-default-ciphers
CLI 选项更改。