ngx_http_ssl_module
模块提供对 HTTPS 的必要支持。
默认不构建该模块。使用 --with-http_ssl_module
配置参数启用它。
该模块依赖 OpenSSL 库。
为降低处理器负载,建议
将工作进程的数量设置为处理器的数量,
启用 keep-alive 连接,
开启共享会话缓存,
禁用内建的会话缓存,
尽可能延长会话的生命周期(默认,5 分钟):
worker_processes auto;
http {
...
server {
listen 443 ssl;
keepalive_timeout 70;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
ssl_certificate /usr/local/nginx/conf/cert.pem;
ssl_certificate_key /usr/local/nginx/conf/cert.key;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
...
}
Syntax: ssl on | off;
Default: ssl off;
Context: http, server
该指令在版本 1.15.0 中被废弃。应该使用 listen
指令的 ssl
参数替代。
Syntax: ssl_buffer_size size;
Default: ssl_buffer_size 16k;
Context: http, server
该指令出现在版本 1.5.9 中。
设置用于发送数据的缓冲的大小。
默认,缓冲大小是 16k。当发送大响应时,它对应最小的开销。
为最小化首字节时间,可以使用较小的值,比如:
ssl_buffer_size 4k;
Syntax: ssl_certificate file;
Default: —
Context: http, server
为给定的虚拟主机指定 PEM 格式的证书文件。如果除主证书外,还需要指定中间证书,那么应该在相同的文件中按照如下顺序指定它们:前面是主证书,后面是中间证书。PEM 格式的私钥可被放置在相同的文件中。
从版本 1.11.0 开始,可以指定该指令多次,以加载不同类型的证书,比如 RSA 和 ECDSA:
server {
listen 443 ssl;
server_name example.com;
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;
...
}
仅 OpenSSL 1.0.2 或更高的版本支持不同证书的单独证书链。旧版本仅能使用一个证书链。
从版本 1.15.9 起,当使用 OpenSSL 1.0.2 或更高版本时,可以在 file
名称中,使用变量:
ssl_certificate $ssl_server_name.crt;
ssl_certificate_key $ssl_server_name.key;
注意,使用变量意味着将为每次 SSL 握手加载证书,这可能对性能产生负面影响。
从 1.15.10 起,可以指定值 data:$variable
,替代 file
,它从变量中加载证书,而不使用中间文件。注意,不恰当地使用该语法可能产生安全隐患,比如将私钥数据写到 error log。
请记住,由于 HTTPS 协议对最大互操作性的限制,虚拟主机应该监听不同的 IP 地址。
Syntax: ssl_certificate_key file;
Default: —
Context: http, server
为给定的虚拟主机指定 PEM 格式的私钥文件。
从 1.7.9 起,可以指定值 engine:name:id
,替代 file
,它使用指定的 id
,从 OpenSSL 引擎 name
加载私钥。
从 1.15.10 起,可以指定值 data:$variable
,替代 file
,它从变量中加载私钥,而不使用中间文件。注意,不恰当地使用该语法可能产生安全隐患,比如将私钥数据写到 error log。
从版本 1.15.9 起,当使用 OpenSSL 1.0.2 或更高版本时,可以在 file
名称中使用变量。
Syntax: ssl_ciphers ciphers;
Default: ssl_ciphers HIGH:!aNULL:!MD5;
Context: http, server
指定启用的加密算法。用 OpenSSL 库能理解的格式指定加密算法,比如:
ssl_ciphers ALL:!aNULL:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
使用 “openssl ciphers” 命令,查看完整列表。
cipher list 的格式 cipher list 由多个 cipher string 组成,用冒号,逗号或者空格分隔,最常用的是冒号。 cipher string 可以仅包含一个 cipher,比如 RC4-SHA。也可以仅包含一个加密算法,比如 SHA 表示列出所有用到 SHA 的 cipher。 还可以使用三个符号(+、-、!)捏合不同的 cipher,创建 cipher string,比如 MD5+DES 表示同时使用这两种算法的 cipher;!SHA 表示所有未使用 SHA 的 cipher;IDEA-CBC 表示使用 IDEA 但未使用 CBC 的所有 cipher。 OpenSSL 预定义一组通用的 cipher string,包括:
- DEFAULT:缺省的 cipher list
- ALL:所有 cipher
- HIGH、LOW、MEDIUM:分别代表高强度,低强度和中等强度的 cipher list,即对称加密算法的 key 的长度分别大于 128 bit、小于 128 bit 和等于 128 bit 的 cipher
- EXP、EXPORT、EXPORT40:前两者代表法律允许出口的加密算法,包括 key 的长度为 40 bit、56 bit 的算法;后者表示 key 的长度只有 40 bit 的加密算法
- eNULL、NULL:表示不加密的算法
- aNULL:不提供身份验证的加密算法。目前只有 DH 一种。该算法很容易被监听者、路由器等中间设备攻击,所以不提倡使用
Syntax: ssl_client_certificate file;
Default: —
Context: http, server
指定 PEM 格式的受信任 CA 证书文件,这些证书用于验证客户端证书和 OCSP 响应(如果启用 ssl_stapling
)。
证书列表将被发送到客户端。如果不希望这样,那么使用 ssl_trusted_certificate
指令。
Syntax: ssl_conf_command name value;
Default: —
Context: http, server
该指令出现在版本 1.19.4 中。
设置任意 OpenSSL 配置命令。
当使用 OpenSSL 1.0.2 或更高版本时,支持该指令。
可以在相同层级指定多个 ssl_conf_command
指令:
ssl_conf_command Options PrioritizeChaCha;
ssl_conf_command Ciphersuites TLS_CHACHA20_POLY1305_SHA256;
当且仅当当前层级未定义 ssl_conf_command
指令时,从前面的配置层级继承这些指令。
注意,直接配置 OpenSSL 可能导致非预期行为。
Syntax: ssl_crl file;
Default: —
Context: http, server
该指令出现在版本 0.8.7 中。
指定 PEM 格式的被吊销证书(CRL)文件,这些证书用于验证客户端证书。
Syntax: ssl_dhparam file;
Default: —
Context: http, server
该指令出现在版本 0.7.2 中。
指定用于 DHE 算法的 DH 参数文件。
默认不设置任何参数,因此将不使用 DHE 算法。
在版本 1.11.0 前,默认使用内置参数。
Syntax: ssl_early_data on | off;
Default: ssl_early_data off;
Context: http, server
该指令出现在版本 1.15.3 中。
开启或禁用 TLS 1.3 早期数据。
在早期数据中发送的请求容易受到重放攻击。为在应用程序层防止这种攻击,应该使用
$ssl_early_data
变量。proxy_set_header Early-Data $ssl_early_data;
从 1.15.4 起,当使用 OpenSSL 1.1.1 或更高版本和 BoringSSL 时,支持该指令。
Syntax: ssl_ecdh_curve curve;
Default: ssl_ecdh_curve auto;
Context: http, server
该指令出现在版本 1.1.0 和 1.0.6 中。
为 ECDHE 加密算法,指定曲线。
当使用 OpenSSL 1.0.2 或更高版本时,可以指定多个曲线(1.11.0),比如:
ssl_ecdh_curve prime256v1:secp384r1;
特殊值 auto
(1.11.0)命令 nginx 在使用 OpenSSL 1.0.2 或更高版本时,使用被构建进 OpenSSL 库的列表;使用旧版本时,使用 prime256v1
。
在版本 1.11.0 前,默认使用
prime256v1
曲线。
当使用 OpenSSL 1.0.2 或更高版本时,该指令设置服务端支持的曲线列表。因此,为使 ECDSA 证书发挥作用,在证书中包含使用的曲线很重要。
Syntax: ssl_password_file file;
Default: —
Context: http, server
该指令出现在版本 1.7.3 中。
指定私钥的密码文件,每行指定一个密码。加载私钥时,按次序尝试这些密码。
比如:
http {
ssl_password_file /etc/keys/global.pass;
...
server {
server_name www1.example.com;
ssl_certificate_key /etc/keys/first.key;
}
server {
server_name www2.example.com;
# named pipe can also be used instead of a file
ssl_password_file /etc/keys/fifo;
ssl_certificate_key /etc/keys/second.key;
}
}
Syntax: ssl_prefer_server_ciphers on | off;
Default: ssl_prefer_server_ciphers off;
Context: http, server
指定当使用 SSLv3 和 TLS 协议时,服务端加密算法应优先于客户端加密算法。
Syntax: ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2] [TLSv1.3];
Default: ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
Context: http, server
启用指定的协议。
仅当使用 OpenSSL 1.0.1 或更高版本时,TLSv1.1 和 TLSv1.2 参数(1.1.13、1.0.12)才生效。
仅当使用 OpenSSL 1.1.1 或更高版本时,TLSv1.3 参数(1.13.0)才生效。
从 1.23.4 起,默认使用 TLSv1.3 参数。
Syntax: ssl_reject_handshake on | off;
Default: ssl_reject_handshake off;
Context: http, server
该指令出现在版本 1.19.4 中。
如果启用,那么 server
块中的 SSL 握手将被拒绝。
比如,在下面的配置中,拒绝使用除 example.com
外的服务名称的 SSL 握手:
server {
listen 443 ssl default_server;
ssl_reject_handshake on;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate example.com.crt;
ssl_certificate_key example.com.key;
}
xxxxxxxxxx
Syntax: ssl_session_cache off | none | [builtin[:size]] [shared:name:size];
Default: ssl_session_cache none;
Context: http, server
设置存储会话参数的缓存的类型和大小。缓存可以是下面的类型中的任意一个:
off
严格禁止使用会话缓存:nginx 显式地告诉客户端不重用会话
none
不允许使用会话缓存:nginx 告诉客户端可能重用会话,但不真正地在缓存中存储会话参数
builtin
OpenSSL 内置的缓存。仅能被一个工作进程使用。在会话中指定缓存大小。默认保存 20480 个会话。使用内置缓存将导致内存碎片
shared
所有工作进程共享缓存。以字节为单位指定缓存大小;1M 大约可以存储 4000 个会话。每个共享缓存可以拥有任意的名称。可以在多个虚拟主机中使用具有相同名称的缓存。它还用于自动生成、存储和定期轮换 TLS 会话票据密钥(1.23.2),除非使用 ssl_session_ticket_key
指令显式地进行配置。可以同时使用这两种缓存类型,比如:
ssl_session_cache builtin:1000 shared:SSL:10m;
但是仅使用共享缓存,不使用内置缓存更高效。
关于 SSL/TLS Session
每次建立新 SSL/TLS 连接都需要握手,如果会话中断,那么需要重新握手。此时,有两种方法恢复原来的 Session:
Session ID
Session ID 重用的前提是客户端和服务端都保存会话密钥。每次会话都有唯一的编号(Session ID)。会话中断,需要重连时,客户端只要给出该编号,并且服务器端拥有该记录,双方就可以重用已有的会话密钥,而不必重新生成。
在上图中,客户端提供 Session ID,服务端确认该编号存在,双方不再进行握手阶段剩余的步骤,而是直接使用已有的会话密钥。
目前所有浏览器都支持 Session ID,但其缺点是:因为 Session ID 往往只保留在一台服务器上,所以如果客户端的请求发到另一台服务器,那么无法恢复会话。
在 nginx 中,通过 ssl_session_cache
配置 Session ID 重用。
Session Ticket
在 Session Ticket 复用中,服务器不用为每个会话保存状态,而是用一个 blob 数据保存状态,然后将它发送给客户端,用于维护后续连接,Session Ticket 允许服务器将状态存储委托给客户端,类似 HTTP Cookie。
Session Ticket 是加密的数据 blob,其中包含需要重用的 TLS 连接信息,比如会话密钥等。一般使用 Ticket Key 加密它,只有服务器端知道 Ticket Key。在初始握手中,服务端将 Session Ticket 发送到客户端,客户端将其存储到本地;重用会话时,客户端将 Session Ticket 发送到服务端,服务端解密后重用会话。
在 nginx 中,使用 ssl_session_tickets
配置 Session Ticket 复用。
xxxxxxxxxx
Syntax: ssl_session_ticket_key file;
Default: —
Context: http, server
该指令出现在版本 1.5.7 中。
设置用于加密和解密 TLS Session Ticket 的密钥文件。如果多台服务器间必须共享相同的密钥,那么该指令是必需的。默认使用随机生成的密钥。
如果指定多个密钥,那么仅使用第一个密钥加密 TLS Session Ticket。这允许配置密钥轮换,比如:
ssl_session_ticket_key current.key;
ssl_session_ticket_key previous.key;
file
必需包含 80 或 48 字节的随机数据,可以使用如下命令创建:
openssl rand 80 > ticket.key
根据文件大小,使用 AES256(对于 80 字节密钥,1.11.8)或 AES128(对于 40 字节密钥)进行加密。
xxxxxxxxxx
Syntax: ssl_session_tickets on | off;
Default: ssl_session_tickets on;
Context: http, server
该指令出现在版本 1.5.9。
启用或禁用通过 TLS Session Ticket 恢复会话。
xxxxxxxxxx
Syntax: ssl_session_timeout time;
Default: ssl_session_timeout 5m;
Context: http, server
指定客户端可以重用会话参数的时间。
xxxxxxxxxx
Syntax: ssl_trusted_certificate file;
Default: —
Context: http, server
该指令出现在版本 1.3.7 中。
指定 PEM 格式的受信任 CA 证书文件,这些证书用于验证客户端证书和 OCSP 响应(如果启用 ssl_stapling
)。
与 ssl_client_certificate
设置的证书相比,这些证书的列表不被发送给客户端。
xxxxxxxxxx
Syntax: ssl_verify_client on | off | optional | optional_no_ca;
Default: ssl_verify_client off;
Context: http, server
启用客户端证书验证。验证结果被保存在 $ssl_client_verify
变量中。
optional
参数(0.8.7+)请求客户端证书,如果证书存在,那么验证它。
optional_no_ca
参数(1.3.8、1.2.5)请求客户端证书,但不要求其由受信任的 CA 证书签名。主要用于 Nginx 外部的服务执行真正的证书验证的场景。通过 $ssl_client_cert
变量访问证书的内容。
xxxxxxxxxx
Syntax: ssl_verify_depth number;
Default: ssl_verify_depth 1;
Context: http, server
设置客户端证书链的验证深度。
ngx_http_proxy_module
模块中与 SSL 有关的指令Syntax: proxy_ssl_certificate file;
Default: —
Context: http, server, location
该指令出现在版本 1.7.8 中。
指定包含 PEM 格式的证书的文件,该证书用于认证被代理的 HTTPS 服务。
从版本 1.21.0 起,可以在 file
名称中可以使用变量。
Syntax: proxy_ssl_certificate_key file;
Default: —
Context: http, server, location
该指令出现在版本 1.7.8 中。
指定包含 PEM 格式的私钥的文件,该私钥用于认证被代理的 HTTPS 服务。
可以指定值 engine:name:id
,替代 file
(1.7.9),它使用指定的 id
从 OpenSSL 引擎 name
加载私钥。
从版本 1.21.0 起,可以在 file
名称中可以使用变量。
Syntax: proxy_ssl_ciphers ciphers;
Default: proxy_ssl_ciphers DEFAULT;
Context: http, server, location
该指令出现在版本 1.5.6 中。
为到被代理的 HTTPS 服务的请求,指定启用的加密算法。用 OpenSSL 能理解的格式指定加密算法。
使用“openssl ciphers”命令查看完整列表。
Syntax: proxy_ssl_conf_command name value;
Default: —
Context: http, server, location
该指令出现在版本 1.19.4 中。
当与被代理的 HTTPS 服务建立连接时,设置任意 OpenSSL 配置命令。
当使用 OpenSSL 1.0.2 或更高版本时,支持该指令。
在相同的层级可以指定多个 proxy_ssl_conf_command
指令。如果当前层级未定义 proxy_ssl_conf_command
指令,那么从前面的配置层级继承这些指令。
注意,直接配置 OpenSSL 可能导致非预期行为。
Syntax: proxy_ssl_crl file;
Default: —
Context: http, server, location
该指令出现在版本 1.7.0 中。
指定包含 PEM 格式的、被吊销的证书的文件,这些证书用于验证被代理的 HTTPS 服务的证书。
Syntax: proxy_ssl_name name;
Default: proxy_ssl_name $proxy_host;
Context: http, server, location
该版本出现在版本 1.7.0 中。
允许重写用于验证被代理的 HTTPS 服务的证书的服务名称,当与被代理的 HTTPS 服务建立连接时,通过 SNI 传递它。
默认,使用 proxy_pass
URL 的 host 部分。
Syntax: proxy_ssl_password_file file;
Default: —
Context: http, server, location
该指令出现在版本 1.7.8 中。
指定包含私钥的密码的文件,每行指定一个密码。加载私钥时,按次序尝试这些密码。
Syntax: proxy_ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2] [TLSv1.3];
Default: proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
Context: http, server, location
该指令出现在版本 1.5.6 中。
为到被代理的 HTTPS 服务的请求,启用指定的协议。
从 1.23.4 起,默认使用
TLSv1.3
参数。
Syntax: proxy_ssl_server_name on | off;
Default: proxy_ssl_server_name off;
Context: http, server, location
该指令出现在版本 1.7.0 中。
当与被代理的 HTTPS 服务建立连接时,启用或禁用通过 TLS SNI 扩展传递服务名称。
Syntax: proxy_ssl_session_reuse on | off;
Default: proxy_ssl_session_reuse on;
Context: http, server, location
决定是否重用 SSL 会话。如果错误日志中出现错误 SSL3_GET_FINISHED:digest check failed
,那么尝试禁用会话重用。
Syntax: proxy_ssl_trusted_certificate file;
Default: —
Context: http, server, location
该指令出现在版本 1.7.0 中。
指定包含 PEM 格式的、受信任的 CA 证书的文件,这些证书用于验证被代理的 HTTPS 服务的证书。
Syntax: proxy_ssl_verify on | off;
Default: proxy_ssl_verify off;
Context: http, server, location
该指令出现在版本 1.7.0 中。
启用或禁用被代理的 HTTPS 服务证书的验证。
Syntax: proxy_ssl_verify_depth number;
Default: proxy_ssl_verify_depth 1;
Context: http, server, location
该指令出现在版本 1.7.0 中。
设置被代理的 HTTPS 服务证书链的验证深度。