安全HTTP¶
模块: mod_openssl mod_mbedtls mod_wolfssl mod_gnutls mod_nss
关键词: lighttpd, SSL, TLS
- 目录
- 安全HTTP
描述¶
- lighttpd 支持使用
mod_openssl
,mod_mbedtls
,mod_wolfssl
,mod_gnutls
或mod_nss
的 TLS/SSL。
简史¶
- openssl 支持在历史上是 lighttpd 1.4.x 核心的内置功能,但自 lighttpd 1.4.46 起,它现在是一个独立的模块 (
mod_openssl
)。 mod_openssl
也可以构建为使用 BoringSSL 或 LibreSSL 提供的 openssl 兼容层。- 自 lighttpd 1.4.56 起,支持 mbedTLS (
mod_mbedtls
)、wolfSSL (mod_wolfssl
) 和 GnuTLS (mod_gnutls
)。 - 对于 openssl 的 TLS 模块替代方案,许多
ssl.*
选项从 openssl 映射到其他 TLS 库中的等效选项,包括ssl.openssl.ssl-conf-cmd
,但并非完全如此,并且没有计划完全重新实现 openssl SSL_CONF_cmd() (ssl.openssl.ssl-conf-cmd
)。
- 自 lighttpd 1.4.56 起,NSS (
mod_nss
) 的实验性支持可用,但由于 NSS 服务器端限制而不建议使用;NSS 开发者几乎只专注于客户端。
快速开始¶
- 虽然有许多配置选项,但最小配置只需
server.modules += ("mod_openssl") $SERVER["socket"] == ":443" { ssl.engine = "enable" ssl.pemfile = "/path/to/fullchain.pem" # public cert and intermediate cert chain, if any ssl.privkey = "/path/to/privkey.pem" }
- 其他简单示例配置和 Let's Encrypt 支持请参考HowToSimpleSSL
- 将 HTTP 请求重定向到 HTTPS
- 使用 mod_setenv 的 HTTP 严格传输安全 (HSTS)
保持安全¶
安全软件必须进行维护。- 请定期检查您的系统是否运行着 TLS 库的最新补丁。建议至少每月检查一次。
- 不要运行已达到生命周期结束 (EOL) 且不再接收安全补丁的软件版本!
https://endoflife.software/applications/security-libraries/openssl
openssl 0.9.8 EOL: 2015年12月31日
openssl 1.0.0 EOL: 2015年12月31日
openssl 1.0.1 EOL: 2016年12月31日
openssl 1.0.2 EOL: 2019年12月31日
openssl 1.1.0 EOL: 2018年8月31日
openssl 1.1.1 EOL: 2023年9月11日
截至 2023年9月11日,只有 openssl 3.0 及更高版本继续从 openssl.org 接收安全补丁。
https://openssl-library.org/post/2023-09-11-eol-111/
SSLv2, SSLv3, TLSv1, TLSv1.1 已被国际标准组织弃用。
在 lighttpd 1.4.56 及更高版本中,这些已弃用的协议默认是禁用的,但仍可在 lighttpd.conf 中明确启用。
配置¶
基本选项
选项 | 描述 |
---|---|
ssl.engine | 启用/禁用 ssl 引擎 |
ssl.pemfile | PEM 文件证书链的路径(必须包含证书链和私钥(除非设置了 ssl.privkey)) |
ssl.privkey | PEM 文件私钥的路径(如果私钥不在 ssl.pemfile 中,则必需)(自 1.4.53 起) |
lighttpd 1.4.78 及更高版本可以配置为大约每分钟检查并重新加载证书。
此功能默认禁用,并且可能不适用于 lighttpd chroot 或 lighttpd 降权,具体取决于文件路径和证书权限。
server.feature-flags "ssl.refresh-certs" => "enable"
定期(每 64 秒)检查并重新加载更新的文件:TLS 证书和私钥(默认:禁用)
功能选择(可选)
选项 | 描述 |
---|---|
ssl.openssl.ssl-conf-cmd | 指定 openssl 配置文件命令(自 1.4.48 起)(提交 c09acbeb) 例如 ("MinProtocol" => "TLSv1.2") 将协议限制为仅 TLS 1.2 或更高版本(注意:优先使用 lighttpd 默认设置) 例如 ("CipherString" => "...") 配置允许的 TLS 密码(注意:优先使用 lighttpd 默认设置) 例如 ("Options" => "-ServerPreference") 根据客户端偏好选择密码(注意:优先使用 lighttpd 默认设置) |
ssl.stapling-file | 包含二进制 OCSP 响应(DER 格式)的文件路径(自 1.4.56 起)(参见OCSP 装订) |
ssl.stek-file | 包含二进制会话票据加密密钥 (STEK) 的文件路径(全局设置)(自 1.4.56 起)(参见会话票据) |
ssl.acme-tls-1 | 包含 TLS-ALPN-01 ("acme-tls/1") 挑战的目录路径(Let's Encrypt 选项)(自 1.4.53 起) |
ssl.read-ahead | 启用/禁用 SSL 预读(lighttpd 1.4.45+)(默认:禁用)(仅限mod_openssl ) |
ssl.ech-opts | TLS_ECH TLS 加密客户端问候选项(自 1.4.77 起)(仅限mod_openssl ) |
ssl.ech-public-name | TLS_ECH TLS 加密客户端问候公共名称;用于标记包含 $HTTP["host"] 为仅限 ECH(自 1.4.77 起)(仅限mod_openssl ) |
客户端证书验证(可选)
选项 | 描述 |
---|---|
ssl.verifyclient.activate | 启用/禁用客户端验证 |
ssl.verifyclient.enforce | 启用/禁用强制客户端验证 |
ssl.verifyclient.depth | 客户端验证的证书深度 |
ssl.verifyclient.exportcert | 启用/禁用客户端证书导出到环境变量作为 SSL_CLIENT_CERT |
ssl.verifyclient.username | 要导出到环境变量作为 REMOTE_USER 的客户端证书实体(例如 SSL_CLIENT_S_DN_emailAddress, SSL_CLIENT_S_DN_UID 等) |
ssl.verifyclient.ca-file | 用于客户端证书验证的证书颁发机构 (CA) 文件路径(自 1.4.60 起)(1.4.60 之前的ssl.ca-file ) |
ssl.verifyclient.ca-dn-file | 客户端应从中选择客户端证书的证书颁发机构 (CA) 文件路径(如果需要)(自 1.4.60 起)(自 1.4.46 到 1.4.60 之前的ssl.ca-dn-file ) |
ssl.verifyclient.ca-crl-file | 客户端证书的证书吊销列表 (CRL) 文件路径(自 1.4.60 起)(自 1.4.46 到 1.4.60 之前的ssl.ca-crl-file ) |
lighttpd 1.4.78 及更高版本可以配置为大约每分钟检查并重新加载 TLS 证书吊销列表 (CRL)。
此功能默认禁用,并且可能不适用于 lighttpd chroot 或 lighttpd 降权,具体取决于文件路径和证书权限。
server.feature-flags "ssl.refresh-crls" => "enable"
定期(每 64 秒)检查并重新加载更新的文件:TLS 证书吊销列表 (CRL)(默认:禁用)
传统选项(除非您知道自己在做什么,否则请优先使用默认设置)
选项 | 描述 |
---|---|
ssl.cipher-list | 配置允许的 TLS 密码 (已弃用;推荐使用 ssl.openssl.ssl-conf-cmd "CipherString") |
ssl.honor-cipher-order | 启用/禁用在密码选择时遵循服务器排序偏好 (ssl.cipher-list)(默认:启用) (PFS 所需,除非 ssl.cipher-list 仅包含支持 PFS 的密码套件) (允许客户端偏好可让客户端选择 ChaCha20-Poly1305, 这可能更适合没有优化 AES 指令集的移动处理器) (已弃用;推荐使用 ssl.openssl.ssl-conf-cmd "Options" => "[+-]ServerPreference") |
ssl.dh-file | Diffie-Hellman 密钥协商协议参数的 PEM 文件路径(仅限 lighttpd >= 1.4.29) (已弃用;推荐使用 ssl.openssl.ssl-conf-cmd "DHParameters")(自 1.4.68 起) |
ssl.ec-curve | 定义了一组椭圆曲线密码学域参数,称为“命名曲线”(仅限 lighttpd >= 1.4.29) (已弃用;推荐使用 ssl.openssl.ssl-conf-cmd "Groups") |
ssl.use-sslv2 | (已弃用)启用/禁用 SSL 版本 2 的使用(仅限 lighttpd < 1.4.21,更新版本不支持 SSLv2) |
ssl.use-sslv3 | (已弃用)启用/禁用 SSL 版本 3 的使用(仅限 lighttpd >= 1.4.29)(自 1.4.36 起默认禁用) |
ssl.disable-client-renegotiation | (已弃用)启用/禁用缓解 TLSv1.2 或更早版本中客户端触发的重新协商(参见 CVE-2009-3555)(默认:启用缓解) |
ssl.ca-file | (已弃用)重命名为 ssl.verifyclient.ca-file (自 1.4.60 起) |
ssl.ca-dn-file | (已弃用)重命名为 ssl.verifyclient.ca-dn-file (自 1.4.60 起) |
ssl.ca-crl-file | (已弃用)重命名为 ssl.verifyclient.ca-crl-file (自 1.4.60 起) |
注意:ssl.*
配置选项通常仅在全局范围或 $SERVER["socket"]
配置条件的顶层有效,因为它们在建立套接字连接时(在知道主机之前)就需要。在客户端添加 SNI(服务器名称指示)的情况下,某些 ssl.*
选项可以在 $HTTP["host"]
或 $HTTP["scheme"]
条件中指定,例如,为该特定连接选择证书。所有其他条件都在 TLS 协商完成后发生,因此嵌套在其他配置条件(包括嵌套在其他配置条件中的 $SERVER["socket"]
或 $HTTP["host"]
或 $HTTP["scheme"]
)中的 ssl.*
指令可能会被忽略。
以下选项除了可在全局范围或 $SERVER["socket"]
条件中使用外,还可在 $HTTP["host"]
或 $HTTP["scheme"]
条件中使用。在其他条件中使用可能在某些 lighttpd 版本中有效,但不能保证。请测试您的配置以验证实际操作是否符合您的预期。
ssl.pemfile ssl.privkey ssl.verifyclient.activate ssl.verifyclient.enforce ssl.verifyclient.depth ssl.verifyclient.exportcert ssl.verifyclient.username ssl.verifyclient.ca-file ssl.verifyclient.ca-dn-file ssl.acme-tls-1 ssl.ech-public-name (allowed only in $HTTP["host"])
在 lighttpd 1.4.56 及更高版本中,ssl.verifyclient.ca-crl-file
应与 ssl.verifyclient.ca-file
在同一作用域中设置,以便产生正确的效果。(mod_openssl 在启动时加载证书文件,并且 openssl 和 wolfssl 要求将 CA 和 CRL 都加载到同一个 (X509_STORE *)
中)
在 CPU 受限的系统(例如嵌入式系统)上,建议使用 ssl.read-ahead = "disable"
,这也是默认设置。如果系统不足以快速处理加密,则一个启用了 ssl.read-ahead = "enable"
的连接可能会垄断 CPU 并使其他连接饥饿,甚至可能延迟其自身连接上的服务器响应。在运行 TLS 加密的 CPU 速度快于网络线速的系统上,ssl.read-ahead = "enable"
可能会略微提高性能。在 lighttpd 1.4.56 及更高版本中,ssl.read-ahead = "enable"
可以按 $HTTP["host"]
设置。一旦启用,就不能在连接上禁用预读,因为服务器可能已经将额外的块读入内存。
详细信息¶
要启用 SSL,您必须提供证书并在每个套接字作用域中启用 SSL 引擎,即在每个应启用 SSL 的 $SERVER["socket"]
中以及在全局作用域中(如果 server.bind
和 server.port
应启用 SSL)设置 ssl.engine = "enable"
。ssl.pemfile
应包含证书和私钥,除非通过 ssl.privkey
指定了私钥路径。ssl.pemfile
还应包含证书的正确排序的证书链。
要使 lighttpd 仅支持 SSL,只需在主配置中添加以下内容。默认情况下,lighttpd 监听“0.0.0.0:80”,除非 server.bind 和 server.port 设置为其他值。要在端口“0.0.0.0:443”上监听而不在端口 80 上监听
server.port = 443 ssl.engine = "enable" ssl.pemfile = "/etc/lighttpd/ssl/www.example.org/fullchain.pem" ssl.privkey = "/etc/lighttpd/ssl/www.example.org/privkey.pem"
除了在端口 80 上使用普通 HTTP 外,若要在端口 443 上启用 SSL/TLS,请将
ssl.engine
配置放在 $SERVER["socket"]
条件块中。$SERVER["socket"] == ":443" { ssl.engine = "enable" ssl.pemfile = "/etc/lighttpd/ssl/www.example.org/fullchain.pem" ssl.privkey = "/etc/lighttpd/ssl/www.example.org/privkey.pem" }
如果您想从全局范围提供不同的站点,可以在
$SERVER["socket"]
条件内部更改文档根目录。$SERVER["socket"] == ":443" { ssl.engine = "enable" ssl.pemfile = "/etc/lighttpd/ssl/www.example.org/fullchain.pem" ssl.privkey = "/etc/lighttpd/ssl/www.example.org/privkey.pem" server.document-root = "/www/servers/www.example.org/secure/" }
当您使用 lighttpd 1.4.19 或更高版本时,您还可以使用
$HTTP["scheme"]
条件来区分安全请求和普通请求。请注意,您不能将 $HTTP["scheme"]
条件用于上述 ssl.engine
,因为 lighttpd 需要知道要在哪个端口启用 SSL。$HTTP["scheme"] == "https" { server.document-root = "/www/servers/www.example.org/secure/" }
作为 lighttpd 1.4.46 及更高版本中的一个特殊情况,如果
ssl.pemfile
和其他 ssl.* 指令位于全局范围,那么 $SERVER["socket"]
块可以通过设置 ssl.engine = "enable"
并在 $SERVER["socket"]
块中不包含任何其他 ssl.* 指令来继承全局配置。自 lighttpd 1.4.65 起,ssl.engine
也从全局范围继承。以下配置将使 lighttpd 在默认的 INADDR_ANY (0.0.0.0) 和 in6addr_any ([::]) 通配符地址上,在端口 80 上提供 HTTP,在端口 443 上提供 HTTPS。server.document-root = "/www/servers/www.example.org/" ssl.pemfile = "/etc/lighttpd/ssl/www.example.org/fullchain.pem" ssl.privkey = "/etc/lighttpd/ssl/www.example.org/privkey.pem" server.port = 80 $SERVER["socket"] == "[::]:80" { } $SERVER["socket"] == ":443" { ssl.engine = "enable" } $SERVER["socket"] == "[::]:443" { ssl.engine = "enable" }
如果
ssl.engine = "enable"
指令也在全局范围中,则对于某些服务器套接字,可以使用 ssl.engine = "disable"
设置纯 HTTP。以下示例演示了 IPv4/IPv6 双栈服务器,其 HTTP 和 HTTPS 连接的端口均已打开。server.document-root = "/www/servers/www.example.org/" ssl.pemfile = "/etc/lighttpd/ssl/www.example.org/fullchain.pem" ssl.privkey = "/etc/lighttpd/ssl/www.example.org/privkey.pem" ssl.engine = "enable" server.port = 443 $SERVER["socket"] == "[::]:443" { ssl.engine = "enable" } $SERVER["socket"] == ":80" { ssl.engine = "disable" } $SERVER["socket"] == "[::]:80" { ssl.engine = "disable" }
如果您有
.crt
和 .key
文件,请指定ssl.pemfile = "/path/to/host.crt"
ssl.privkey = "/path/to/host.key"
或者,将它们
cat
到一个单独的 PEM 文件中(顺序不严格重要):$ cat host.key host.crt > host.pem
并指定 ssl.pemfile = "/path/to/host.pem"
ssl.openssl.ssl-conf-cmd
"CipherString" 是您在进行 SSL 通信时想要(或不想要)使用的密码列表。有关密码列表以及如何包含/排除它们,请参阅 openssl 手册页 openssl-ciphers 中的“CIPHER LIST FORMAT”和“CIPHER STRINGS”部分。有关推荐的强密码的最新列表,请参阅 https://ssl-config.mozilla.org/#server=lighttpd&config=modern 并定期重新访问该页面。有关 lighttpd TLS 默认设置(通常应优先使用)的更多详细信息,请参阅密码选择。
权限¶
请务必保护您的 .pem 文件!lighttpd 在启动时读取所有 pem 文件,如果 lighttpd 以 root 身份启动,这将在降权之前完成。如果 lighttpd 以 root 身份启动,您可以将 pem 文件所有者设置为 root 且仅 root 可读$ chown root:root /etc/lighttpd/ssl/example.org/privkey.pem
$ chmod 400 /etc/lighttpd/ssl/example.org/privkey.pem
然而,以这种方式保护密钥意味着 lighttpd 必须完全停止然后重新启动才能应用任何配置更改。在 lighttpd 降权后,无法进行优雅重启,因为 lighttpd 需要那些初始权限才能在启动时读取受 root 权限保护的私钥。
如果 lighttpd 服务器不是以 root 身份运行,则 lighttpd 运行的用户帐户必须具有读取证书的权限。私钥仍应限制其他帐户读取。$ chmod 400 /etc/lighttpd/ssl/example.org/privkey.pem
链式证书¶
大多数证书颁发机构使用链式证书。这意味着您的 Web 服务器证书不是由 CA 根证书直接签名,而是由中间证书(又由根 CA 签名)签名。由于浏览器通常只包含根证书而不包含所有中间证书,因此如果您不向浏览器提供中间证书,浏览器将无法验证您的链式证书。
为了让 lighttpd 提供证书链,每个 ssl.pemfile
都应包含一个有序的证书链。顺序是证书,后跟其颁发者的证书,依此类推,直到根证书。最终(根)证书是可选的。
正确配置您的证书链
https://medium.com/@superseb/get-your-certificate-chain-right-4b117a9c0fce
替代方案(已弃用):历史上,openssl 中存在一个特性/缺陷,它会重用 openssl (SSL_CTX *)
中的受信任 CA 证书列表 (lighttpd ssl.verifyclient.ca-file
) 来完成服务器证书链(如果 openssl (SSL *)
没有设置链)。换句话说,即使 CA 列表旨在用于客户端证书验证,如果服务器证书没有设置链,openssl 也会将该列表用于服务器证书。作为在 ssl.pemfile
中包含完整证书链的推荐方法的替代方案,您可以将 ssl.verifyclient.ca-file = "/etc/lighttpd/ssl/ca.crt"
设置为包含完成 ssl.pemfile
中证书的服务器证书链所需的中间证书的路径。
完善前向保密 (PFS)¶
https://en.wikipedia.org/wiki/Forward_secrecy
"在密码学中,前向保密 (FS),也称为完善前向保密 (PFS),是特定密钥协商协议的一项特性,它确保即使服务器的私钥被泄露,会话密钥也不会受到损害。前向保密保护过去的会话免受未来秘密密钥或密码泄露的影响。通过为用户启动的每个会话生成唯一的会话密钥,单个会话密钥的泄露不会影响除受该特定密钥保护的特定会话中交换的数据之外的任何数据。"
如果 lighttpd TLS 模块配置为使用支持 PFS 的协议和密码(默认启用),则 lighttpd 支持 PFS。要强制使用 PFS(并禁止降级),请仅指定支持 PFS 的密码。(TLSv1.3 仅使用支持 PFS 的密码。)有关更多详细信息,请参见下面的密码选择。
密码选择¶
自 lighttpd 1.4.68 起: lighttpd 选择的默认 TLS 密码是强大的并支持完善前向保密 (PFS)。
除非您有特定要求,否则不建议更改强大的默认 TLS 密码。
在 lighttpd 1.4.68 之前: 如果 lighttpd.conf 中未明确设置 ssl.cipher-list
,lighttpd 会隐式应用 ssl.cipher-list = "HIGH"
(自 lighttpd 1.4.54 起)。这是现代互联网上一个合理的默认设置。为了更高的安全性,请使用 "SUITEB192"
或 "SUITEB128"
。为了与更旧的客户端兼容,请尝试 "MEDIUM"
。还有许多其他选项(openssl 密码)可与 mod_openssl
一起使用,尽管 mod_mbedtls
、mod_wolfssl
、mod_gnutls
、mod_nss
对 ssl.openssl.ssl-conf-cmd
或 ssl.cipher-list
的解析仅支持一小部分。
当所有列出的密码都支持完善前向保密时,推荐使用 ssl.openssl.ssl-conf-cmd = ("Options" => "-ServerPreference")
或 ssl.honor-cipher-order = "disable"
(效果相同),例如 Mozilla ssl-configurator lighttpd 现代配置。一旦密码列表被限制为支持完善前向保密的密码,允许使用客户端偏好进行密码选择会很有用,因为移动设备通常缺乏 AES 硬件加速,在这些设备上,ChaCha20-Poly1305 可能快达 3 倍,为移动用户提供更好的体验并消耗更少的电池寿命。在台式机上,硬件通常具有 AES 加速的原生硬件,基于 AES 的密码通常是最快的。(历史上,lighttpd 中的默认设置是使用服务器偏好进行密码选择(ssl.honor-cipher-order = "enable"
),以防止密码降级攻击到较弱的密码,例如不支持完善前向保密的密码。)
lighttpd 1.4.56 与 openssl 1.1.1 或更高版本将使用 openssl 选项 SSL_OP_PRIORITIZE_CHACHA
,以利于移动用户,即使 ssl.honor-cipher-order = "enable"
且 AES 密码列在 ChaCha20-Poly1305 之前。
参考资料
https://blog.cloudflare.com/do-the-chacha-better-mobile-performance-with-cryptography/
https://security.googleblog.com/2014/04/speeding-up-and-strengthening-https.html
# OLD DEFAULT: As of Sep 2020, default in lighttpd 1.4.56 and widely supported by clients, except very old clients w/o TLSv1.2 #ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.2", # in openssl 1.0.2: "Protocol" => "-ALL, TLSv1.2" # "Options" => "ServerPreference, # "CipherString" => "HIGH") # (lighttpd 1.4.55 and earlier: For increased security, you should disable SessionTicket or you should restart lighttpd server daily) #ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.2", # "Options" => "ServerPreference,-SessionTicket", #(lighttpd 1.4.55 and earlier) # "CipherString" => "HIGH") # OLDER STRONGER: As of Sep 2020, a strong set of ciphers for PFS and widely supported by clients #ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.2", # "Options" => "-ServerPreference", # "CipherString" => "EECDH+AESGCM:AES256+EECDH:CHACHA20") # DEFAULT: As of Jan 2023 with lighttpd 1.4.68: # # STRONGER: As of Sep 2020, a strong set of ciphers for PFS and widely supported by modern clients, without CBC ciphers reported as weak by SSLLabs #ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.2", # "Options" => "-ServerPreference", # "CipherString" => "EECDH+AESGCM:AES256+EECDH:CHACHA20:!SHA1:!SHA256:!SHA384") # DEFAULT: As of Mar 2024 with lighttpd 1.4.75: # # STRONGER: As of Mar 2024, a strong set of ciphers for PFS and authenticated encryption (AEAD), and widely supported by modern clients #ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.2", # "Options" => "-ServerPreference", # "CipherString" => "EECDH+AESGCM:CHACHA20:!PSK:!DHE") # DEFAULT: As of Jan 2025 with lighttpd 1.4.77: # # STRONGEST: As of Sep 2020, for use w/ modern clients only; not compat w/ older clients #ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.3", # "Options" => "-ServerPreference")
# Expanded cipher list equivalent to "CipherString" => "EECDH+AESGCM:CHACHA20:!PSK:!DHE" # for mod_mbedtls, mod_wolfssl, mod_gnutls, whose modules do not support the shorter syntax #ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.2", # "Options" => "-ServerPreference", # # mbedtls (pseudo-syntax) # "CipherString" => "TLS1-3-AES-256-GCM-SHA384:TLS1-3-CHACHA20-POLY1305-SHA256:TLS1-3-AES-128-GCM-SHA256:TLS1-3-AES-128-CCM-SHA256:TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256:TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256:TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256" # # wolfssl (pseudo-syntax) # "CipherString" => "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305" # # gnutls (pseudo-syntax) (GnuTLS priority string syntax) # "CipherString" => +AES-256-GCM:+AES-128-GCM:+CHACHA20-POLY1305:-RSA:-PSK:-DHE-RSA:-AES-256-CCM:-AES-128-CCM:-AES-256-CBC:-AES-128-CBC" # ) # Expanded cipher list equivalent to ssl.cipher-list = "EECDH+AESGCM:AES256+EECDH:CHACHA20" # for mod_wolfssl whose modules do not support the shorter CipherString syntax #ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.2", # "Options" => "-ServerPreference", # "CipherString" => "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-CCM8:ECDHE-ECDSA-AES256-CCM:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:RSA-PSK-CHACHA20-POLY1305:DHE-PSK-CHACHA20-POLY1305:ECDHE-PSK-CHACHA20-POLY1305:PSK-CHACHA20-POLY1305") # Expanded cipher list equivalent to "CipherString" => "EECDH+AESGCM:AES256+EECDH:CHACHA20:!SHA1:!SHA256:!SHA384" # for mod_mbedtls, mod_wolfssl, mod_gnutls, whose modules do not support the shorter syntax #ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.2", # "Options" => "-ServerPreference", # "CipherString" => "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-CCM8:ECDHE-ECDSA-AES256-CCM:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:RSA-PSK-CHACHA20-POLY1305:DHE-PSK-CHACHA20-POLY1305:ECDHE-PSK-CHACHA20-POLY1305:PSK-CHACHA20-POLY1305")
强烈推荐使用 ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.2")
(如果客户端支持,也可使用 "TLSv1.3"
)(注意:优先使用 lighttpd 默认设置)
TLSv1.2 之前的 TLS 协议已弃用,TLSv1.3 是首选。主流客户端浏览器计划在 2020 年停止支持 TLSv1.0 和 TLSv1.1。
https://sensorstechforum.com/apple-microsoft-google-drop-support-tls1-0-tls1-1/
https://www.thesslstore.com/blog/apple-microsoft-google-disable-tls-1-0-tls-1-1/
https://scotthelme.co.uk/legacy-tls-is-on-the-way-out/
会话票据¶
会话票据是 TLS 1.2 的一个可选扩展,可用于在客户端重新连接时减少延迟,也称为会话恢复。会话票据允许服务器将会话状态的存储委托给客户端,但会使用服务器端会话票据加密密钥 (STEK) 对该状态进行加密。然而,如果 STEK 具有无限生命周期,例如从不轮换,则完善前向保密 (PFS) 将会丢失。另一方面,替换 STEK 会使当前会话票据失效,在新连接时需要进行完整的 TLS 握手,而不是更快的会话恢复,因此替换不应过于频繁。
lighttpd 1.4.55 及更早版本没有明确配置会话票据,但底层的 openssl 库默认启用了会话票据,并且从不轮换 STEK。自 lighttpd 1.4.48 起,可以使用 ssl.openssl.ssl-conf-cmd = ("Options" => "-SessionTicket")
在 lighttpd 中禁用会话票据。
在 lighttpd 1.4.56 中,会话票据仍默认启用,但在所有 lighttpd TLS 模块中(mod_nss 除外)都会自动轮换。默认情况下,lighttpd 将轮换 STEK,并且每个密钥的生命周期为 24 小时。这是一个合理的折衷方案,既允许在指定时间窗口内恢复会话,又在 STEK 轮换并丢弃旧 STEK 后保留完善前向保密。此默认设置对于单个 lighttpd 进程(即不使用多个工作进程的 lighttpd)是足够的。对于多个工作进程,请使用 ssl.stek-file
(自 1.4.56 起)。
ssl.stek-file
允许管理员控制 STEK 的生命周期和轮换计划,这在使用多个 lighttpd 工作进程或在多台服务器上运行 lighttpd 以服务相同站点时非常有用。如果在全局配置范围中配置了 ssl.stek-file
,则内置的 STEK 轮换行为将被禁用。相反,lighttpd 将从文件中读取 STEK,并每 64 秒检查一次文件是否需要重新读取以获取新的 STEK。lighttpd mod_openssl 最多存储三个 (3) STEK,因此如果加密密钥生命周期为 24 小时,则建议每 8 小时生成一个新的 STEK。lighttpd mod_mbedtls 使用 mbedtls 内部机制,最多存储两个 (2) STEK,因此建议每 12 小时生成一个新的 STEK。lighttpd mod_gnutls 在任何时候都只有一个活动的 STEK,因此建议每 24 小时生成一个新的 STEK。如果 lighttpd 使用多个工作进程,建议使用 ssl.stek-file
,因为此机制允许每个 lighttpd 工作进程以及多台服务器使用相同的密钥。您负责通过外部作业生成 STEK 文件。STEK 文件应存储在非持久性存储中,例如 /dev/shm/lighttpd/stek-file(在内存中),并设置适当的权限以防止其他用户读取 stek-file。在可能的情况下,系统也应配置为不使用交换分区,以防止密钥意外地交换到持久性存储中。
ssl.stek-file
的格式是- 4 字节 - 格式版本(始终为 0;用于格式更改时)
- 4 字节 - 激活时间戳
- 4 字节 - 过期时间戳
- 16 字节 - 会话票据密钥名称
- 32 字节 - 会话票据 HMAC 加密密钥
- 32 字节 - 会话票据 AES 加密密钥
STEK 文件可以使用以下命令创建,例如
cd /dev/shm/lighttpd && \ dd if=/dev/random bs=1 count=80 status=none | \ perl -e 'print pack("iii",0,time()+300,time()+86400),<>' \ > STEK-file.$$ && mv STEK-file.$$ STEK-file # (alternative: 'openssl rand 80' can be substituted for 'dd if=/dev/random bs=1 count=80 status=none' above)上述命令将激活时间延迟 5 分钟(+300 秒),以允许文件传播到其他机器。(管理员必须独立处理此问题)如果在启动 lighttpd 之前立即执行 STEK 生成,管理员应立即激活密钥(无需 +300)。此示例中使用 /dev/shm/lighttpd,必须由管理员创建并设置权限。lighttpd 读取 stek 文件,但不创建 stek 文件或路径的任何部分。
请注意,如果在 lighttpd 1.4.56 之前使用带有多个 lighttpd 工作进程的 lighttpd,除了通过(某些外部作业)重启 lighttpd 之外,进程之间不会发生协调的 STEK 轮换。重启 lighttpd 会生成一个新密钥,该密钥在新的生命周期内由 lighttpd 工作进程共享。如果轮换周期到期而 lighttpd 未重启,lighttpd 工作进程将生成新的独立密钥,从而降低会话票据用于会话恢复的效率,因为客户端将来连接到同一 lighttpd 工作进程的可能性较低。然而,一切仍将正常工作,如果会话恢复失败,将创建新会话。在 lighttpd 1.4.56 之前,如果启用会话票据并配置了多个 lighttpd 工作进程,管理员应计划至少每 24 小时重启 lighttpd 一次。(通过向父 lighttpd 进程发送 SIGUSR1 可以实现优雅重启。)密钥分发的难度、复杂性和每个环境的特性是为什么定期重启 lighttpd(或 nginx、Apache)通常是轮换 STEK 的推荐方法。正确使用带有 lighttpd 1.4.56 的 ssl.stek-file
使这变得更容易,并且不需要服务器重启。
如果在多个独立的 lighttpd 服务器(具有独立的 STEK)前面有一个连接负载均衡器,并且负载均衡器未执行 SSL 终止,那么配置负载均衡器算法以尝试粘性路由(如果可用)可能会很有益,这样客户端有更好的机会被定向到可以验证会话票据并允许会话恢复的同一服务器。同样,当使用 lighttpd 1.4.56 和 ssl.stek-file
时,如果 STEK 文件已传播到每个服务器以共享密钥,则此操作不是必需的。
警告:2020年6月:GnuTLS 3.6.4 至 GnuTLS 3.6.13 易受 CVE-2020-13777 攻击。如果使用 mod_gnutls,请使用 GnuTLS 3.6.14 或更高版本,或者使用 ssl.openssl.ssl-conf-cmd = ("Options" => "-SessionTicket")
在 lighttpd 中禁用会话票据。
警告:mod_nss 中的限制:NSS 不提供用于轮换 STEK 的公共接口。lighttpd mod_nss 不支持 STEK 轮换。如果使用 mod_nss,请使用 ssl.openssl.ssl-conf-cmd = ("Options" => "-SessionTicket")
在 lighttpd 中禁用会话票据,或者考虑每 24 小时重启 lighttpd 服务器。
会话缓存¶
自 lighttpd 1.4.56 起,会话缓存已被禁用。会话票据 (TLSv1.2) 被推荐替代会话缓存,因为会话票据更优越,内存占用更少,并且当会话票据加密密钥共享(和轮换)时,更容易在多个 lighttpd 工作进程和多个服务器之间移植。使用会话缓存实现类似功能需要更复杂的基础设施(某些其他 Web 服务器支持),但在 TLSv1.2 及更高版本中使用会话票据时不再需要。
server.feature-flags += ("ssl.session-cache" => "enable")
可用于恢复 lighttpd-1.4.56 之前的默认行为。如果设置,lighttpd 将不会明确禁用 TLS 库会话缓存,而是使用 TLS 库的默认设置。注意:会话缓存尚未在 mod_mbedtls
或 mod_gnutls
中实现(并且优先级较低,因为会话票据应优先使用。)
OCSP 装订¶
ssl.stapling-file
(自 lighttpd 1.4.56 起)可以与 ssl.pemfile
在同一作用域中设置。如果文件存在,文件内容(OCSP 响应)将与证书一起作为 TLS 握手的一部分进行装订。
该文件必须定期维护和更新,以使 OCSP 响应不会过期。在过期前几分钟,lighttpd 大约每分钟检查一次是否有更新的 ssl.stapling-file
。如果无法确定过期时间(例如,OCSP 响应不包含“下次更新”字段),则 lighttpd 每小时重新读取一次 ssl.stapling-file
。OCSP 响应文件必须可由 server.username
中配置的用户读取。
ssl.stapling-file
的内容可以通过填充适当的变量生成:openssl ocsp -issuer "$CHAIN_PEM" -cert "$CERT_PEM" -respout "$OCSP_RESP" -noverify -no_nonce -url "$OCSP_URI"
。在 lighttpd 源代码树中,doc/scripts/cert-staple.sh
提供了一个示例脚本,可以通过计划任务定期运行。
注意:mbedTLS 目前不支持 OCSP 装订,这对于使用自签名证书的小型服务器来说是可以的,但不适用于带有 OCSP Must-Staple 标记的证书。
HTTP/2 和 TLS¶
RFC 7540 HTTP/2 第 9.2 节“使用 TLS 功能”规定了将 TLS 与 HTTP/2 一起使用的要求。默认情况下,在 lighttpd 1.4.56 及更高版本中,lighttpd TLS 模块根据 RFC 7540 的要求,在 TLSv1.2 中禁用 TLS 压缩和 TLS 重新协商。RFC 7540 对密码的 HTTP/2 限制可以通过为 mod_openssl
指定“STRONGER”密码集 "CipherString" => "EECDH+AESGCM:AES256+EECDH:CHACHA20:!SHA1:!SHA256:!SHA384"
来实现(对于其他 lighttpd TLS 模块可能略有不同;有关替代密码字符串,请参阅上面的完善前向保密 (PFS) 部分)。lighttpd 默认(自 lighttpd 1.4.54 起)的 "CipherString" => "HIGH"
是为了更广泛的兼容性,并且不足以实现 HTTP/2 的建议。请使用上面推荐的 STRONGER 或 STRONGEST 配置以遵循 RFC 7540 中更严格的指导。
TLS 加密客户端问候 (ECH)¶
lighttpd 1.4.77 中对 TLS 加密客户端问候 (ECH) 的实验性支持。详细信息:TLS_ECH
kTLS¶
kTLS - 内核 TLS - 可用于在 TLS 握手后执行对称 TLS 的内核卸载。
lighttpd 对 kTLS 的支持始于 lighttpd 1.4.68,其性能改进在 HTTP/1.x 中最为显著,尤其是在响应静态文件或使用 X-Sendfile
从后端响应时。请注意,由于 HTTP/2 帧,lighttpd 无法在 HTTP/2 下利用 openssl SSL_sendfile() 或 gnutls gnutls_record_send_file()。kTLS 是一种可选的性能功能,如果您不确定是否需要此功能,那么您很可能不需要它。如果您选择配置 kTLS,请测试以验证结果是否提高了您的系统对您的站点流量模式的性能。
kTLS 可能在 Linux 内核 4.13 及更高版本以及 FreeBSD 13 及更高版本中受支持,尽管在操作系统发行版中可能默认不提供。Debian 12 及更高版本默认启用 kTLS。Fedora 默认不启用 kTLS (https://fedoraproject.org/wiki/Changes/KTLSSupportForGnuTLS)。有关如何临时和持久(在系统启动时发生)加载 Linux 和 FreeBSD 内核模块以支持 TLS 的步骤,请参阅博客文章 Using Kernel TLS (kTLS) and TLS NIC offloading with OpenSSL。另请参阅 Fedora:使用内核模块:持久模块加载。如果以 root 身份运行,lighttpd 1.4.74 及更高版本中的 lighttpd mod_openssl 和 lighttpd mod_gnutls 将尝试加载 Linux tls 内核模块,如果内核 tls 尚不可用。
对于 lighttpd mod_gnutls,gnutls 的系统范围配置(例如 /etc/gnutls/config 或 /etc/crypto-policies/back-ends/gnutls.config)必须配置为在 gnutls 中启用 ktls。
https://www.gnutls.org/manual/gnutls.html#Enabling_002fDisabling-system_002facceleration-protocols
要为 lighttpd 指定自定义 gnutls 库配置文件,可以在启动 lighttpd 之前在 shell 中设置 GNUTLS_SYSTEM_PRIORITY_FILE 环境变量。
https://www.gnutls.org/manual/gnutls.html#System_002dwide-configuration-of-the-library
如果使用专用硬件设备进行加密加速,您也必须确保内核模块已正确加载和配置,例如 https://docs.nvda.net.cn/doca/sdk/tls-offload/index.html
要禁用 kTLS,请配置ssl.openssl.ssl-conf-cmd += ("Options" => "-KTLS")
FreeBSD 14 上可能存在与 openssl 3.0.12 的 FreeBSD 包补丁相关的问题。构建和使用官方上游 openssl 源代码似乎与 kTLS 配合良好。
https://github.com/openssl/openssl/issues/23824#issuecomment-1992664175
多域名上的 SSL¶
传统上,SSL 与基于名称的虚拟主机结合使用时存在一个问题,即 SSL 连接建立发生在 HTTP 请求之前。因此,当 lighttpd 需要向客户端发送其证书时,它尚不知道客户端将请求哪个域名。这意味着它只能提供默认证书(并使用相应的密钥进行加密),实际上,SSL 只能为该默认域启用。针对此问题有多种解决方案,客户端支持程度各不相同。
服务器名称指示 (SNI)¶
服务器名称指示 (SNI) 是 TLS 握手的一个 TLS 扩展,它允许客户端发送其想要联系的主机名。服务器随后可以使用此信息来选择正确的证书。SNI 通常受到大多数客户端的良好支持,但并非所有移动客户端都支持。
要在 lighttpd 中使用 SNI,只需在 $HTTP["host"]
条件内部放置额外的 ssl.pemfile
配置指令。在 $SERVER["socket"]
条件中仍然需要一个默认的 ssl.pemfile
。
$SERVER["socket"] == ":443" { ssl.engine = "enable" ssl.pemfile = "/etc/lighttpd/ssl/the-default-domain.com.pem" } $HTTP["host"] == "www.example.org" { ssl.pemfile = "/etc/lighttpd/www.example.org.pem" } $HTTP["host"] == "mail.example.org" { ssl.pemfile = "/etc/lighttpd/mail.example.org.pem" }
每个域名一个 IP 地址¶
这是经典的解决方案,它为每个域名分配一个独立的 IP 地址。由于 lighttpd 在 SSL 协商之前就知道客户端连接的 IP 地址,因此它可以简单地根据 IP 地址选择正确的证书。这种方法最明显的缺点是它需要多个地址,这些地址并非总是可用且可能成本高昂。这种方法适用于所有客户端,但也使用了许多 IP 地址。
要在 lighttpd 中实现此功能,请使用 $SERVER["socket"]
条件
$SERVER["socket"] == "10.0.0.1:443" { ssl.engine = "enable" ssl.pemfile = "/etc/lighttpd/ssl/www.example.org.pem" } $SERVER["socket"] == "10.0.0.2:443" { ssl.engine = "enable" ssl.pemfile = "/etc/lighttpd/ssl/mail.example.org.pem" }
从全局配置范围继承 ssl.* 配置¶
要在多个 $SERVER["socket"]
上下文中启用 TLS/SSL 并共享 ssl.*
配置,可以复制每个 $SERVER["socket"]
内的 ssl.*
配置,或者将 ssl.*
指令放在全局上下文中,并让 $SERVER["socket"]
配置块包含 ssl.engine = "enable"
而不包含该 $SERVER["socket"]
配置块中的任何其他 ssl.*
指令。(自 lighttpd 1.4.65 起,如果 ssl.engine = "enable"
在全局范围中,则它将被每个 $SERVER["socket"]
配置块继承,无需重复。)
ssl.pemfile = "/etc/lighttpd/ssl/www.example.org.pem" $SERVER["socket"] == "10.0.0.1:443" { ssl.engine = "enable" } $SERVER["socket"] == "10.0.0.2:443" { ssl.engine = "enable" }
UCC / SAN 证书¶
可以将多个名称放入单个证书中。这些证书通常被称为 UCC(统一通信证书)证书或 SAN(主题备用名称)证书。这些证书使用 SAN 属性将多个域名存储在一个证书中。这允许 lighttpd 始终使用相同的证书,该证书对其服务的所有域名都有效。
这种方法的主要缺点是您将拥有一个包含大量域名的单个证书,并且每次添加新域名时都需要更改证书。在为不同方提供服务时,这可能是一个问题。
根据 digicert 的 SAN 兼容性,SAN 证书几乎所有浏览器(除了一些移动浏览器)都支持,并且应该非常安全地使用。
通配符证书¶
证书支持使用通配符,这对于支持多个子域名非常有用。例如,可以获取 *.example.org 域名的证书以支持 example.org 域名的所有子域名。
当然,这种方法无法很好地扩展到多个不同域。同样,根据 digicert 的 通配符兼容性,通配符证书应受到几乎所有客户端的支持。
其他问题¶
Let's Encrypt 引导¶
lighttpd 支持使用 TLS-ALPN-01 验证挑战(自 lighttpd 1.4.53 起)进行 Let's Encrypt 引导。
参见 HowToSimpleSSL 中的步骤。
自签名证书¶
自签名 SSL 证书可以像这样生成::
$ openssl req -new -x509 \
-keyout server.pem -out server.pem \
-days 365 -nodes
仅在 SSL IP 下服务您想要的域名¶
上面建议的简单配置,在服务多个主机时(每个 IP 一个,这是传统且仍然最常见的方式,直到 Windows XP 消失且几乎所有浏览器都支持 SNI),可能过于“模糊”。考虑以下配置
$SERVER["socket"] == "10.0.0.1:443" {
ssl.engine = "enable"
ssl.pemfile = "/etc/lighttpd/ssl/domain1.com.pem"
server.document-root = "/www/servers/domain1.com"
}
$SERVER["socket"] == "10.0.0.2:443" {
ssl.engine = "enable"
ssl.pemfile = "/etc/lighttpd/ssl/domain2.com.pem"
server.document-root = "/www/servers/domain1.com"
}
您的 DNS 配置可能是
domain1.com A 10.0.0.1
domain2.com A 10.0.0.2
像这样通常一切都很好。但是,如果您的客户端的 DNS 被污染或过时,或者存在 /etc/hosts 条目并发出以下请求
连接到 IP 10.0.0.2,因为它以某种方式将 domain1.com 解析为 10.0.0.2(见上文)。然后 lighty 即使在请求头中收到“Host:domain1.com”,也会提供 domain2 的内容!您受到一定程度的保护,因为您的客户端应该在此处发出 SSL 域名不匹配警告。然而,就像我们配置中那样,domain1 和 domain2 实际上是子域名,并由同一个通配符证书覆盖 => 没有 SSL 警告!
因此,我们仅仅因为过时的 DNS 就从“错误”的域名/文档根获取了内容。
为了更“严格”的配置,我们建议
server.document-root = "/www/servers/other-catchall # e.g. HTTP/1.0 clients sending HTTP request headers _without_ Host: $SERVER["socket"] == "10.0.0.1:443" { ssl.engine = "enable" ssl.pemfile = "/etc/lighttpd/ssl/domain1.com.pem" $HTTP["host"] == "domain1.com" { server.document-root = "/www/servers/domain1.com" } } $SERVER["socket"] == "10.0.0.2:443" { ssl.engine = "enable" ssl.pemfile = "/etc/lighttpd/ssl/domain2.com.pem" $HTTP["host"] == "domain2.com" { server.document-root = "/www/servers/domain2.com" } }这确保 10.0.0.2:443 将仅服务带有“Host: domain2.com”请求头的内容。如果从 10.0.0.2:443 请求 domain1.com,lighty 将响应 404。
故障排除¶
- 请注意,证书文件在服务器执行 chroot(如果配置为 chroot)之前打开。因此,这些路径是系统范围的。
- 在服务器端,ssldump 是您的好帮手:
ssldump -i your_network_interface_goes_here port 443
- 在客户端,openssl 将帮助您:
openssl s_client -connect your_server_name_goes_here:443
- SSL 选项不工作或被忽略?将选项放在您启用 SSL (ssl.engine = "enable") 的同一代码块中。
SSL 密码¶
- 如果您为 SSL 证书设置了密码,那么每次 lighttpd 启动时,都会要求您手动输入。例如:“Enter PEM pass phrase:”。为了防止这种情况,请从私钥文件中删除密码。目前没有配置选项可以在 lighttpd 配置文件中存储 SSL 证书密码(但这样做意义不大,因为将密码存储在磁盘上并不比根本没有密码更安全)。
Diffie-Hellman 和椭圆曲线 Diffie-Hellman 参数¶
Diffie-Hellman 和椭圆曲线 Diffie-Hellman 密钥协商协议将在 lighttpd 1.4.29 中支持。默认情况下,Diffie-Hellman 和椭圆曲线 Diffie-Hellman 密钥协商协议分别使用来自 RFC 5114 的 1024 位 MODP 群和 160 位素数阶子群,以及来自 RFC 4492 的“prime256v1”(也称为“secp256r1”)椭圆曲线。OpenSSL 从 0.9.8f 版本开始支持椭圆曲线 Diffie-Hellman 密钥协商协议。为了最大程度的互操作性,OpenSSL 仅支持 RFC 4492 中的“命名曲线”。
使用 ssl.dh-file
和 ssl.ec-curve
配置变量,您可以定义自己的一组 Diffie-Hellman 域参数。例如
ssl.dh-file = "/etc/lighttpd/ssl/dh2048.pem"
ssl.ec-curve = "secp384r1"
可以像这样生成一组 Diffie-Hellman 域参数(参见 OpenSSL dhparam 文档获取帮助)
$ openssl dhparam -out dh2048.pem -outform PEM -2 2048
支持的椭圆曲线集可以像这样获取(参见 OpenSSL ecparam 文档获取帮助)
$ openssl ecparam -list_curves
限制¶
- mbedTLS 目前不支持 OCSP 装订。这对于使用自签名证书的小型服务器来说是可以的,但不适用于带有 OCSP Must-Staple 标记的证书。
mod_nss
不支持 EC 证书或ssl.verifyclient.ca-file
。NSS 库倾向于将证书存储在证书数据库中,并且不支持单个文件(这是其他 TLS 库的典型用法)。NSS 没错,只是不同而已。欢迎提交补丁。
链接¶
- HowToSimpleSSL
- 将 HTTP 请求重定向到 HTTPS
- IPv6 配置
- Qualsys SSL Labs SSL/TLS 部署最佳实践
进一步的 TLS 安全增强¶
参考
- https://depthsecurity.com/blog/pins-and-staples-enhanced-ssl-security
- https://web.archive.org/web/20190604160808/https://depthsecurity.com/blog/pins-and-staples-enhanced-ssl-security
以下是一些关键词和短语,您可以输入搜索引擎进行进一步研究。
- DNS 证书颁发机构授权 (CAA)
- RFC 6844 DNS 证书颁发机构授权 (CAA) 资源记录
- 防止其他 CA(非您选择的 CA)被欺骗为您的域颁发证书的预防措施
- https://sslmate.com/caa/
- https://scotthelme.co.uk/certificate-authority-authorization/
- 证书透明度 (CT)
- RFC 6962 证书透明度
- 要求 CA 公开证书颁发记录,供公众验证
- 通常是 CA 标准操作程序的一部分
- https://scotthelme.co.uk/certificate-transparency-an-introduction/
- HTTP 响应头 Expect-CT 指示客户端报告或拒绝缺少签名证书时间戳 (SCT) 信息的证书
- 已弃用;请参见 https://mdn.org.cn/en-US/docs/Web/HTTP/Headers/Expect-CT
- HTTP 严格传输安全 (HSTS)
- RFC 6797 HTTP 严格传输安全 (HSTS)
- 用于与客户端共享站点 HTTPS 策略的 HTTP 响应头
- 使用 mod_setenv 的 HTTP 严格传输安全
- OCSP 装订
- RFC 6961 传输层安全 (TLS) 多证书状态请求扩展
- 服务器将在线证书状态协议 (OCSP) 响应与服务器自身的证书一起发送给客户端
-ssl.stapling-file
(自 1.4.56 起)
- OCSP 必须装订
RFC 7633 X.509v3 传输层安全 (TLS) 功能扩展
- 指示客户端如果 TLS 握手未同时提供 OCSP 装订状态信息,则拒绝证书
- OCSP Must-Staple X.509v3 扩展必须在发送给证书颁发机构 (CA) 的证书签名请求 (CSR) 中请求
- HTTP 响应头 Expect-Staple 也可用于在部署带有 Must-Staple 的新证书之前验证站点 OCSP 装订操作和程序的结果。
- HTTP 公钥锁定 (HPKP)
- RFC 7469 HTTP 公钥锁定扩展
- 由于操作负担和危险,不再推荐使用
- https://scotthelme.co.uk/hpkp-is-no-more/