mod_gnutls
mod_gnutls 使用 GnuTLS 监听单独的套接字以进行 TLS 连接 (https)
gnutls(设置)
设置 TLS 套接字
gnutls options;
- 选项
- 一个包含以下条目的键值表
- 监听
- (必填)要监听的套接字地址(与“listen”:plugin_core.html#plugin_core__setup_listen 相同),可以多次指定以使用相同选项设置多个套接字
- pem文件
- (必填)包含私钥、证书、中间证书(通常不包含根证书)和 OCSP 响应的文件;或者,它可以是一个键值列表,其中包含一个“key”和“cert”条目,以及一个可选的“ocsp”条目。
- PIN码
- 使用 PKCS #11 模块或加密密钥时使用的 PIN 码(或密码)。该 PIN 码保存在内存中。
- 优先级
- GnuTLS 优先级字符串,指定加密套件和其他 GnuTLS 选项(默认:“NORMAL”)
- dh参数
- 包含生成的 dh-params 的文件名(默认:固定的 4096 位参数)
- 防范BEAST攻击
- 是否通过在优先级字符串后附加“:-CIPHER-ALL:+ARCFOUR-128”来强制 TLS1.0 和 SSL3.0 连接使用 RC4(默认:false)
- 会话数据库大小
- 会话数据库大小,0 表示禁用会话支持(如果 GnuTLS 支持,TLS 票证支持始终启用)
- sni后端
- “fetch”后端名称,用于以 SNI 服务器名称为键搜索证书(仅当 lighttpd2 中启用了 SNI 时可用)
- sni回退pem文件
- 如果请求包含 SNI 服务器名称,但 sni 后端未找到任何内容时使用的证书;如果请求未包含 SNI,则使用标准“pemfile”(s);与“pemfile”类似,它也可以是一个包含“key”和“cert”条目的键值列表。
IPv4 和 IPv6 上的简单 TLS
setup {
module_load "mod_gnutls";
gnutls (
"priority" => "PFS:-3DES-CBC:-ARCFOUR-128:-VERS-SSL3.0:-SHA1:+SHA1:+RSA:%SERVER_PRECEDENCE",
"listen" => "0.0.0.0:443",
"listen" => "[::]:443",
"pemfile" => "/etc/certs/lighttpd.pem"
);
}
带简单 SNI 的 TLS
setup {
module_load "mod_gnutls";
gnutls (
"priority" => "PFS:-3DES-CBC:-ARCFOUR-128:-VERS-SSL3.0:-SHA1:+SHA1:+RSA:%SERVER_PRECEDENCE",
"listen" => "0.0.0.0:443",
"listen" => "[::]:443",
"pemfile" => "/etc/certs/www.example.com.pem"
"pemfile" => "/etc/certs/mail.example.com.pem"
);
}
从 fetch 后端获取 SNI 的 TLS
对于 SNI 主机名 example.com
,lighttpd2 将尝试在 /etc/certs/lighttpd_sni_example.com.pem
中查找私钥和证书。
setup {
fetch.files_static "sni" => "/etc/certs/lighttpd_sni_*.pem";
module_load "mod_gnutls";
gnutls (
"priority" => "PFS:-3DES-CBC:-ARCFOUR-128:-VERS-SSL3.0:-SHA1:+SHA1:+RSA:%SERVER_PRECEDENCE",
"sni-backend" => "sni",
"listen" => "0.0.0.0:443",
"listen" => "[::]:443",
"pemfile" => "/etc/certs/lighttpd.pem"
);
}
IPv4 和 IPv6 上的简单 TLS,使用单独的密钥文件、证书文件和加密密钥
setup {
module_load "mod_gnutls";
gnutls (
"priority" => "PFS:-3DES-CBC:-ARCFOUR-128:-VERS-SSL3.0:-SHA1:+SHA1:+RSA:%SERVER_PRECEDENCE",
"listen" => "0.0.0.0:443",
"listen" => "[::]:443",
"pin" => "passwordForEncryptedKey",
"pemfile" => (
"key" => "/etc/certs/lighttpd_key.pem",
"cert" => "/etc/certs/lighttpd_cert.pem"
)
);
}
IPv4 和 IPv6 上的简单 TLS,使用 SoftHSM
setup {
module_load "mod_gnutls";
gnutls (
"priority" => "PFS:-3DES-CBC:-ARCFOUR-128:-VERS-SSL3.0:-SHA1:+SHA1:+RSA:%SERVER_PRECEDENCE",
"listen" => "0.0.0.0:443",
"listen" => "[::]:443",
"pin" => "SoftHSM-pin",
"pemfile" => (
"key" => "pkcs11:model=SoftHSM;manufacturer=SoftHSM;serial=1;token=master-key;id=%ac%d5%52%69%16%09%2c%0c%9c%b0%ec%6c%3d%3b%c6%4d%55%4c%40%49;object=my-key;object-type=private",
"cert" => "pkcs11:model=SoftHSM;manufacturer=SoftHSM;serial=1;token=master-key;id=%ac%d5%52%69%16%09%2c%0c%9c%b0%ec%6c%3d%3b%c6%4d%55%4c%40%49;object=my-key;object-type=cert"
)
);
}
IPv4 和 IPv6 上的简单 TLS,带 OCSP 装订
setup {
module_load "mod_gnutls";
gnutls (
"priority" => "PFS:-3DES-CBC:-ARCFOUR-128:-VERS-SSL3.0:-SHA1:+SHA1:+RSA:%SERVER_PRECEDENCE",
"listen" => "0.0.0.0:443",
"listen" => "[::]:443",
"pemfile" => (
"key" => "/etc/certs/lighttpd.pem",
"cert" => "/etc/certs/lighttpd.pem",
"ocsp" => "/etc/certs/lighttpd-ocsp.der",
)
);
}
服务器名称指示 (SNI)
TLS SNI 意味着客户端可以在 TLS 握手过程中未加密地发送其尝试连接的服务器的主机名。
如果要在同一 IP 地址上托管多个主机名(这很常见),有以下几种方法(它们可以组合使用)
- 在证书中使用通配符作为“CommonName”(CN),例如
*.example.com
(尽管这通常不匹配example.com
) - 在证书中使用“Subject Alternative Names”(主题备用名称)
- 根据 TLS 握手中的 SNI 主机名提供不同的证书。
支持 SNI 的客户端通常也支持其他选项,但并非所有客户端都支持 SNI。
GnuTLS 内置了一些基本的 SNI 支持;如果在选项中指定多个 pemfile
,它将选择第一个具有与 SNI 主机名匹配的证书的文件。
lighttpd2 具有可选的扩展 SNI 支持(必须在编译时启用,并且是 sni-*
选项可用的前提)。它旨在通过 fetch API 按需从后端(文件、SQL 等)异步加载证书。
在这种情况下,lighttpd2 将在 GnuTLS 为连接启动之前,根据 SNI 主机名从指定的 sni-backend
获取证书。
如果客户端提供了 SNI 主机名,但在后端未找到证书,它将使用 sni-fallback-pemfile
(如果已设置)而不是 pemfile
。
组合使用 sni-backend
、sni-fallback-pemfile
和多个 pemfile
将不起作用——它只会使用第一个配置的 pemfile
(如果客户端未提供 SNI 主机名,否则将使用 sni-*
证书)。
另请注意,lighttpd2 不会验证 SNI 主机名是否与 HTTP 请求中的主机名匹配。SNI 仅由客户端用于告知服务器应发送哪个主机名的证书(即客户端用于验证的内容)。
GnuTLS 优先级字符串
GnuTLS 优先级字符串配置了可用的加密套件和协议版本,以及少量选项(激活变通方法等)。
示例:"SECURE:-VERS-SSL3.0:-SHA1:+SHA1:-RSA:+RSA:%SERVER_PRECEDENCE"
-
SECURE
:以SECURE
级别开始:仅安全加密套件和安全曲线 -
-VERS-SSL3.0
:禁用 SSL3.0 支持(现在所有客户端都应至少支持 TLS1.0) -
-SHA1:SHA1
将 SHA1 放回 MAC 算法列表(优先使用其他 SHA 变体) -
-RSA:+RSA
:优先选择 (RSA) DHE/ECDHE 密钥交换而非简单的 RSA -
%SERVER_PRECEDENCE
:一个标志,告诉 GnuTLS 使用其自己的优先级顺序,而不是客户端提供的顺序。
另请参阅
- 优先级字符串 (GnuTLS 手册)
- GnuTLS 优先级字符串
gnutls-cli -l --priority "SECURE:-VERS-SSL3.0:-SHA1:+SHA1:-RSA:+RSA:%SERVER_PRECEDENCE"
OCSP 装订
OCSP 装订 用于向客户端保证证书仍然有效(即未被吊销);您可以将 OCSP 响应放入证书文件中的“OCSP RESPONSE”-PEM 块中(可能没有针对此的标准,只需对您拥有的 DER 响应进行 base64 编码),或者在“pemfile”块中使用“ocsp”指定(DER 或 PEM 格式的)OCSP 响应作为单独的文件。
服务器名称指示 (SNI) 应该正常工作,因为 OCSP 响应仅在其与连接中使用的证书匹配时才会被使用。
如果 OCSP 响应以 PEM 块形式附加,则 fetch 后端支持 OCSP 装订。
Lighttpd 不会自动重新加载 OCSP 响应;您必须重启才能加载新的 OCSP 响应(cron 任务可能是正确的方法)。
如果您的证书和颁发者证书(签署您的证书的那个)是分开的文件,您可以这样请求 OCSP 响应(使用 GnuTLS 的“ocsptool”)
ocsptool --ask --load-issuer issuer.pem --load-cert cert.pem --outfile ocsp.der
转换为 PEM 格式可以这样做
(echo "-----BEGIN OCSP RESPONSE-----"; base64 --wrap=64 ocsp.der; echo "-----END OCSP RESPONSE-----") > ocsp.pem
如果您在确定需要哪些证书时遇到困难,这里有更详细的解释
您通常在传递给 lighttpd 的 PEM 文件中有一个证书列表。第一个证书通常有一个指向您的服务器名称 (CN) 的“Subject”,例如:“Subject: CN=lighttpd.net”。它还有一个“Issuer”属性(例如“C=US, O=Let’s Encrypt, CN=Let’s Encrypt Authority X3”)。颁发者证书需要一个与该“Issuer”匹配的“Subject”,并且应该是 PEM 文件中的第二个证书(除非它已经是根 CA,在这种情况下通常省略)。
ocsptool
总是使用文件中的第一个证书并忽略其他证书,因此您可以使用传递给 lighttpd 的普通 PEM 文件作为 --load-cert
后的参数,但如果您没有单独的颁发者证书文件,则需要提取它。以下 awk
脚本从文件中提取第二个 PEM 块
awk '
BEGIN { block = 0 }
/^-----BEGIN / { ++block; }
{ if (block > 1) print; }
' "certs.pem" > "issuer.pem"
防范BEAST攻击
现在许多客户端都认为 BEAST 攻击 已得到缓解,因此不再推荐此解决方法,并且默认禁用。
如果启用,它将强制在 TLS1.0 及更早版本上使用 RC4(TLS1.1 和 TLS1.2 不受影响);但 RC4 本身存在问题。
DH 参数
DHE_RSA
密钥交换需要参数(类似于 ECDHE_RSA
中使用的曲线);这些参数指定了乘法整数模 p 群的一个素数 p
和一个群生成元 g
(即对于 1..p-1
中的所有 x
,都存在一个 e
使得 g^e = x
);有时 g
可能只创建一个足够大的子群(例如大小为 (p-1)/2
的子群)。
DH 密钥交换的安全性(除其他因素外)取决于 p
的位长度;因此 lighttpd 包含默认的 4096 位参数(由 GnuTLS certtool 在 3.0.22 版本中通过 certtool --get-dh-params --bits=4096
提供),这些参数应该是安全的(一些较旧的客户端不支持大于 1024 位的密钥长度;如果您需要支持这些客户端,则必须禁用 DH 密钥交换或指定 1024 位参数)。
您可以使用 GnuTLS 或 openssl 生成自己的参数
certtool --generate-dh-params --bits=2048
openssl dhparam -dsaparam 2048
openssl dhparam -2 2048
openssl dhparam -5 2048
GnuTLS 的 certtool
仅生成“DSA”参数(任何具有大生成元的素数),而 openssl
可以生成具有生成元 2 或 5 并结合 Sophie Germain 素数 (p-1)/2
(即 p
和 (p-1)/2
都是素数)的“DH”参数,或使用 -dsaparam
选项的“DSA”参数。
生成“DH”参数需要更多时间,但您可以重复使用其密钥(尽管不建议这样做,请在 openssl 手册中搜索 SSL_CTX_set_tmp_dh_callback
上的 SSL_OP_SINGLE_DH_USE
)。“DSA”参数的密钥不应重复使用,即每个连接都应生成一个新的私钥,mod_gnutls 就是这种情况。lighttpd 提供的默认参数是“DH”参数。
另请参阅