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-backendsni-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 使用其自己的优先级顺序,而不是客户端提供的顺序。

另请参阅

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”参数。

另请参阅