SSL#
为流代理服务器提供使用 SSL/TLS 协议所需的支持。
当 从源代码构建 时,该模块默认不会被构建;必须通过
构建选项 --with-stream_ssl_module 启用它。
在来自 我们的软件仓库 的包和镜像中,该模块已包含在 构建中。
备注
此模块需要 OpenSSL 库。
配置示例#
为了降低处理器负载,建议:
例如:
worker_processes auto;
stream {
#...
server {
listen 12345 ssl;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
ssl_certificate /usr/local/angie/conf/cert.pem;
ssl_certificate_key /usr/local/angie/conf/cert.key;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# ...
}
指令#
ssl_alpn#
指定支持的 ALPN 协议列表。如果客户端使用 ALPN,则必须 协商 其中一个协议:
map $ssl_alpn_protocol $proxy {
h2 127.0.0.1:8001;
http/1.1 127.0.0.1:8002;
}
server {
listen 12346;
proxy_pass $proxy;
ssl_alpn h2 http/1.1;
}
ssl_certificate#
为给定服务器指定 PEM 格式的证书。中间证书(如有)应紧随主证书之后,位于同一文件或同一值中;PEM 格式的密钥也可以放在其中。
该值的解释方式与 HTTP SSL 模块的 ssl_certificate 指令相同:可以是文件路径,也可以是 data: 前缀之后的证书 PEM 文本。
值中可以包含 变量。此时 Angie 会在每次 SSL 握手期间加载该服务器的所有证书和密钥;ssl_certificate_cache 可将它们保留以供重用,而 ssl_stapling 和 ssl_certificate_compression 对其不起作用。
与 HTTP 不同,变量是在会话内求值的,此时监听地址所对应默认服务器的 set 指令已经执行;它们所赋的值在握手期间可用,同样可用的还有 $ssl_server_name 以及 map 由其派生的变量。如果 TLS 服务器名称选中了另一个服务器,则该服务器的 set 指令此时尚未执行,因此其证书值应改为依赖 $ssl_server_name 和 map。
此指令可以多次指定以加载不同类型的证书,例如 RSA 和 ECDSA:
server {
listen 12345 ssl;
ssl_certificate example.com.rsa.crt;
ssl_certificate_key example.com.rsa.key;
ssl_certificate example.com.ecdsa.crt;
ssl_certificate_key example.com.ecdsa.key;
# ...
}
ssl_certificate_cache#
| |
默认值 |
|
stream, server |
定义一个缓存,用于存储使用变量指定的 SSL 证书 和 私钥。
该指令支持以下参数:
max— 设置缓存中的最大元素数量。当缓存溢出时,最近最少使用(LRU)的元素将被移除。inactive— 定义元素在此时间内未被访问即会被删除的时长,即使其仍处于valid周期内;每次访问都会重置此计时器。默认为 10 秒。valid— 定义缓存元素无需检查即可重用的时长。默认为 60 秒。此时间过后,从文件加载的元素仅在文件已更改时才会重新加载,而通过engine:或store:前缀加载的密钥会再次加载;使用data:前缀指定的元素保持有效。off— 禁用缓存。
受密码短语保护的密钥(参见 ssl_password_file)不会被缓存。
示例:
ssl_certificate $ssl_server_name.crt;
ssl_certificate_key $ssl_server_name.key;
ssl_certificate_cache max=1000 inactive=20s valid=1m;
ssl_certificate_compression#
启用 TLS 1.3 服务器证书 压缩。
备注
使用 OpenSSL 3.2 或更高版本时支持该指令;支持的压缩算法列表由库提供。
备注
使用 BoringSSL 时支持该指令;支持的压缩算法列表包括 zlib。
该指令与 ssl_stapling 不兼容:如果配置在同一服务器中同时启用两者,则配置将加载失败。
ssl_certificate_key#
为给定服务器指定 PEM 格式的密钥。
该值(包括 engine: 和 store: 前缀)的解释方式与 HTTP SSL 模块的 ssl_certificate_key 指令相同,其中的变量按 ssl_certificate 中所述的方式工作。受密码短语保护的密钥使用 ssl_password_file 中的密码短语解密。
ssl_ciphers#
指定启用的密码套件。密码套件以 OpenSSL 库理解的格式指定,例如:
ssl_ciphers ALL:!aNULL:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
密码套件列表取决于已安装的 OpenSSL 版本。
可以使用 openssl ciphers 命令查看完整列表。
警告
使用 OpenSSL 时,ssl_ciphers 指令 不 配置 TLS 1.3 的密码套件;请改用 ssl_conf_command 指令的 Ciphersuites 命令来设置。ssl_ciphers 指令会忽略其值中的 TLS 1.3 密码套件名称,因此这类名称不会限制 TLS 1.3 连接。如果值仅由此类名称组成,例如 TLS_AES_128_GCM_SHA256,配置将无法加载,并报 no cipher match 错误。
在 LibreSSL 中,可以 使用
ssl_ciphers配置 TLS 1.3 密码套件。在 BoringSSL 中,根本无法配置 TLS 1.3 密码套件。
ssl_client_certificate#
指定一个包含 PEM 格式受信任 CA 证书的文件,用于 验证 客户端证书,以及在启用 ssl_stapling 时验证 OCSP 响应。
证书列表将发送给客户端。如果不希望这样,可以使用 ssl_trusted_certificate 指令。
ssl_conf_command#
设置任意 OpenSSL 配置 命令。
备注
使用 OpenSSL 1.0.2 或更高版本时支持该指令。
Ciphersuites 命令用于设置 TLS 1.3 的密码套件,需要 OpenSSL 1.1.1 或更高版本。
可以在同一级别指定多个 ssl_conf_command 指令:
ssl_conf_command Options PrioritizeChaCha;
ssl_conf_command Ciphersuites TLS_CHACHA20_POLY1305_SHA256;
仅当当前级别没有定义 ssl_conf_command 指令时,才会从上一级配置继承这些指令。
警告
直接配置 OpenSSL 可能导致意外行为。
ssl_crl#
指定一个包含 PEM 格式吊销证书 (CRL) 的文件,用于 验证 客户端证书。
ssl_dhparam#
指定用于 DHE 密码套件的 DH 参数文件。
警告
默认情况下不设置任何参数,因此不会使用 DHE 密码套件。
ssl_early_data#
启用或禁用 TLS 1.3 早期数据。
备注
使用 OpenSSL 1.1.1 或更高版本或 BoringSSL 时支持该指令。
ssl_ecdh_curve#
指定用于 ECDHE 密码套件的曲线。
备注
使用 OpenSSL 1.0.2 或更高版本时,可以指定多条曲线,例如:
ssl_ecdh_curve prime256v1:secp384r1;
特殊值 auto 指示 Angie 在使用 OpenSSL 1.0.2 或更高版本时使用 OpenSSL 库内置的列表,或在旧版本中使用 prime256v1。
备注
使用 OpenSSL 1.0.2 或更高版本时,此指令设置服务器支持的曲线列表。因此,为了使 ECDSA 证书正常工作,重要的是在证书中包含使用的曲线。
ssl_encrypted_hello_key#
Added in version 1.11.0.
指定一个文件,其中包含用于 Encrypted Client Hello (ECH) TLS 扩展的密钥和配置,该扩展对网络路径上的观察者隐藏客户端请求的服务器名称。 $ssl_encrypted_hello 变量显示握手中是否使用了该扩展。
该指令可以指定多次,从而实现密钥轮换:所有密钥都用于解密,但只有第一个密钥的配置会 提供给客户端用于重试。
ssl_encrypted_hello_key current.ech;
ssl_encrypted_hello_key previous.ech;
该文件包含一个密钥,其后是 ECHConfigList,两者均为 PEM 格式。使用 OpenSSL 的 ECH 特性分支 时,可用以下命令创建这样的文件:
$ openssl ech -public_name public.example.com -out example.ech
使用 BoringSSL 时,bssl generate-ech
会将密钥和 ECHConfigList 写入两个独立的二进制文件,且两者都不能直接使用。
需要将它们合并为一个 PEM 文件:先把原始密钥封装为 PKCS#8 结构并经 base64
编码放入 PRIVATE KEY 块,其后放入经 base64 编码的 ECHConfigList
(而非单独的 ECHConfig)作为 ECHCONFIG 块。使用 BoringSSL
的构建仅支持 X25519 密钥。文件格式本身不依赖于 TLS 库,因此用上述命令生成的文件
同样适用于使用 BoringSSL 的构建。
Angie 在得知通过 SNI 请求的服务器名称之前就会解密
ClientHello,因此在存在多个虚拟服务器时,必须为它们所监听端口的默认服务器
指定密钥。
备注
ECH 支持来自 TLS 库,因此必须将 Angie 链接到提供该支持的库:OpenSSL 的 ECH 特性分支,其配置方式为
$ ./configure --with-openssl=../openssl-ech
或者 BoringSSL,其配置方式不同。否则该指令将被忽略,并在错误日志中记录警告。
ssl_handshake_timeout#
指定 SSL 握手完成的超时时间。
ssl_keylog_file#
指定一个文件,用于记录由该上下文处理的连接的 SSL/TLS 密钥,采用 SSLKEYLOGFILE 格式,Wireshark 等工具使用该格式来解密捕获的 TLS 流量。
该指令不应与 LibreSSL 一起使用。
警告
该文件包含敏感的 TLS 密钥材料,可用于解密相应连接的已捕获流量。请仅将该指令 用于调试或协议分析,限制对该文件的访问,并在不再需要时将其删除。
ssl_ntls#
使用 Tongsuo 库启用服务器端 NTLS 支持。
listen ... ssl;
ssl_ntls on;
备注
Angie 必须使用 --with-ntls 配置参数和支持 NTLS 的 SSL 库进行构建:
$ ./configure --with-openssl=../Tongsuo-8.3.0 \
--with-openssl-opt=enable-ntls \
--with-ntls
ssl_ocsp#
启用客户端证书链的 OCSP 验证。leaf 参数仅启用客户端证书的验证。
要使 OCSP 验证正常工作, ssl_verify_client 指令应设置为 on 或 optional。
要解析 OCSP 响应器主机名,还应指定 resolver 指令。
示例:
ssl_verify_client on;
ssl_ocsp on;
resolver 127.0.0.53;
ssl_ocsp_cache#
设置用于存储 OCSP 验证客户端证书状态的缓存的名称和大小。缓存在所有工作进程之间共享。具有相同名称的缓存可以在多个虚拟服务器中使用。
off 参数禁止使用缓存。
ssl_ocsp_responder#
覆盖证书扩展 "Authority Information Access" 中指定的 OCSP 响应器 URI,用于客户端证书的 验证。
仅支持 http:// OCSP 响应器:
ssl_ocsp_responder http://ocsp.example.com/;
ssl_password_file#
指定包含 密钥 密码短语的文件,其中每个密码短语单独占一行。加载密钥时依次尝试这些密码短语。
示例:
stream {
ssl_password_file /etc/keys/global.pass;
...
server {
listen 127.0.0.1:12345;
ssl_certificate_key /etc/keys/first.key;
}
server {
listen 127.0.0.1:12346;
# 命名管道也可以用来代替文件
ssl_password_file /etc/keys/fifo;
ssl_certificate_key /etc/keys/second.key;
}
}
ssl_prefer_server_ciphers#
指定在使用 SSLv3 和 TLS 协议时,服务器密码套件应优先于客户端密码套件。
ssl_protocols#
| |
默认值 |
|
stream, server |
启用指定的协议。
备注
TLSv1.1 和 TLSv1.2 参数仅在使用 OpenSSL 1.0.1 或更高版本时有效。
TLSv1.3 参数仅在使用 OpenSSL 1.1.1 或更高版本时有效。
ssl_reject_handshake#
如果启用,server 块中的 SSL 握手将被拒绝。
例如,在以下配置中,与服务器名称不是 example.com 的 SSL 握手将被拒绝:
server {
listen 12345 ssl default_server;
ssl_reject_handshake on;
}
server {
listen 12345 ssl;
server_name example.com;
ssl_certificate example.com.crt;
ssl_certificate_key example.com.key;
}
ssl_session_cache#
| |
默认值 |
|
stream, server |
设置存储会话参数的缓存类型和大小。缓存可以是以下任意类型:
| 严格禁止使用会话缓存:Angie 明确告知客户端会话不能被重用。 |
| 温和地禁止使用会话缓存:Angie 告知客户端会话可以被重用,但实际上不在缓存中存储会话参数。 |
| OpenSSL 内置缓存;仅由一个工作进程使用。缓存大小以会话数指定。如果未给出大小,则等于 20480 个会话。使用内置缓存可能导致内存碎片。 |
| 在所有工作进程之间共享的缓存。缓存大小以字节为单位指定;一兆字节可以存储约 4000 个会话。每个共享缓存应具有任意名称。具有相同名称的缓存可以在多个服务器中使用。它还用于自动生成、存储和定期轮换 TLS 会话票证密钥,除非使用 ssl_session_ticket_key 指令显式配置。 |
两种缓存类型可以同时使用,例如:
ssl_session_cache builtin:1000 shared:SSL:10m;
但仅使用共享缓存而不使用内置缓存应该更高效。
ssl_session_ticket_key#
设置包含用于加密和解密 TLS 会话票证的密钥的文件。如果必须在多个服务器之间共享相同的密钥,则此指令是必需的。默认情况下,使用随机生成的密钥。
如果指定了多个密钥,则仅使用第一个密钥来加密 TLS 会话票证。这允许配置密钥轮换,例如:
ssl_session_ticket_key current.key;
ssl_session_ticket_key previous.key;
该文件必须包含 80 或 48 字节的随机数据,可以使用以下命令创建:
$ openssl rand 80 > ticket.key
根据文件大小,将使用 AES256(用于 80 字节密钥)或 AES128(用于 48 字节密钥)进行加密。
ssl_session_tickets#
启用或禁用通过 TLS 会话票证 进行会话恢复。
ssl_session_timeout#
指定客户端可以重用会话参数的时间。
ssl_stapling#
启用或禁用服务器 装订 OCSP 响应。 示例:
ssl_stapling on;
resolver 127.0.0.53;
要使 OCSP 装订正常工作,应该知道服务器证书颁发者的证书。 如果 ssl_certificate 文件不包含中间证书, 则服务器证书颁发者的证书应该存在于 ssl_trusted_certificate 文件中。
警告
为了解析 OCSP 响应器主机名,还应该指定 resolver 指令。
ssl_stapling_file#
设置后,装订的 OCSP 响应将从指定的文件中获取, 而不是查询服务器证书中指定的 OCSP 响应器。
该文件应该是 DER 格式,由 openssl ocsp 命令生成。
ssl_stapling_responder#
覆盖证书扩展 "Authority Information Access" 中指定的 OCSP 响应器的 URI。
仅支持 http:// OCSP 响应器:
ssl_stapling_responder http://ocsp.example.com/;
ssl_stapling_verify#
启用或禁用服务器对 OCSP 响应的验证。
要使验证正常工作,应该使用 ssl_trusted_certificate 指令将服务器证书颁发者的证书、根证书和所有中间证书配置为受信任的证书。
ssl_trusted_certificate#
指定一个包含 PEM 格式受信任 CA 证书的文件,用于 验证 客户端证书。
与 ssl_client_certificate 设置的证书集不同,这些证书列表不会发送给客户端。
ssl_verify_client#
启用客户端证书验证。验证结果存储在 $ssl_client_verify 变量中。如果在客户端证书验证期间发生错误,或者客户端未提供所需的证书,则连接将被关闭。
| 请求客户端证书,如果证书存在则进行验证。 |
| 请求客户端证书,但不要求其由受信任的 CA 证书签名。这适用于由 Angie 外部的服务执行实际证书验证的情况。 |
ssl_verify_depth#
设置客户端证书链中的验证深度。
内置变量#
返回在 SSL 握手期间通过 ALPN 选择的协议,否则返回空字符串。 返回已建立的 SSL 连接所使用的加密套件名称。 返回客户端支持的加密套件列表。已知的加密套件以名称列出,未知的以十六进制显示,例如: 备注 仅在使用 OpenSSL 1.0.2 或更高版本时完全支持该变量。对于旧版本,该变量仅适用于新会话,并且仅列出已知的加密套件。 返回已建立的 SSL 连接的客户端证书(PEM 格式),除第一行外的每一行都以制表符开头。 返回已建立的 SSL 连接的客户端证书的 SHA1 指纹。 根据 RFC 2253 返回已建立的 SSL 连接的客户端证书的"颁发者 DN"字符串。 返回已建立的 SSL 连接的客户端证书(PEM 格式)。 根据 RFC 2253 返回已建立的 SSL 连接的客户端证书的"主题 DN"字符串。 返回已建立的 SSL 连接的客户端证书的序列号。 返回已建立的 SSL 连接的客户端证书的 签名算法。 备注 仅在使用 OpenSSL 3.5 或更高版本时支持该变量。对于旧版本,该变量值将为空字符串。 备注 该变量仅适用于新会话。 返回客户端证书的结束日期。 返回客户端证书到期前的剩余天数。 返回客户端证书的起始日期。 返回客户端证书验证的结果: 返回 SSL 握手密钥交换过程中协商使用的曲线。已知的曲线以名称列出,未知的以十六进制显示,例如: 备注 仅在使用 OpenSSL 3.0 或更高版本时支持该变量。对于旧版本,该变量值将为空字符串。 返回客户端支持的曲线列表。已知的曲线以名称列出,未知的以十六进制显示,例如: 备注 仅在使用 OpenSSL 1.0.2 或更高版本时支持该变量。对于旧版本,该变量值将为空字符串。 备注 该变量仅适用于新会话。 如果使用了 TLS 1.3 早期数据 且握手未完成,则返回 "1",否则返回 ""。 Added in version 1.11.0. 如果 返回已建立的 SSL 连接的协议。 根据服务器证书和密钥的类型,取值为 返回通过 SNI 请求的服务器名称。 返回已建立的 SSL 连接的会话标识符。 如果 SSL 会话被重用则返回 "r",否则返回 "."。 返回已建立的 SSL 连接的服务器证书的 签名算法。 备注 仅在使用 OpenSSL 3.5 或更高版本时支持该变量。对于旧版本,该变量值将为空字符串。 备注 该变量仅适用于新会话。 返回客户端在 SSL 握手期间提供的 签名算法 列表,以冒号分隔。 备注 从 OpenSSL 4.0 版本起,算法按名称返回;对于没有名称的算法,则回退为其原始十六进制代码。使用旧版签名算法 API 的 SSL 库会将所有算法作为原始十六进制代码返回。不提供受支持签名算法 API 的构建返回空值。stream_ssl 模块支持以下变量:$ssl_alpn_protocol#$ssl_cipher#$ssl_ciphers#AES128-SHA:AES256-SHA:0x00ff
$ssl_client_cert#$ssl_client_fingerprint#$ssl_client_i_dn#$ssl_client_raw_cert#$ssl_client_s_dn#$ssl_client_serial#$ssl_client_sigalg#$ssl_client_v_end#$ssl_client_v_remain#$ssl_client_v_start#$ssl_client_verify#SUCCESS、FAILED:reason,如果证书不存在则返回 NONE。$ssl_curve#prime256v1
$ssl_curves#0x001d:prime256v1:secp521r1:secp384r1
$ssl_early_data#$ssl_encrypted_hello#ClientHello 是通过 Encrypted Client Hello (ECH)
TLS 扩展解密的,则返回 "1",否则返回 ""。$ssl_protocol#$ssl_server_cert_type#RSA、DSA、ECDSA、ED448、
ED25519、SM2、RSA-PSS 或 unknown。$ssl_server_name#$ssl_session_id#$ssl_session_reused#$ssl_sigalg#$ssl_sigalgs#