我有运行多个虚拟主机的 Web 服务器,我想阻止窃听者知道客户端正在访问哪个虚拟主机。已经有一个 TLS 扩展可以解决这个问题:加密 SNI。我看到 Cloudflare 在其服务器上支持它,并且 Firefox 有一个在客户端上启用它的设置。但我找不到任何关于如何在我自己的服务器上启用它的文档。我该怎么做?(我没有绑定到任何特定的服务器堆栈,除了“将其放在 Cloudflare 后面”之外,我将接受任何有效的设置/架构。)
答案1
加密服务器名称指示 (ESNI) 仍处于互联网草案阶段,您不会在任何主流服务器实现中找到它,因为它可能会发生变化。事实上,Firefox 实现的草案版本支持草案-IETF-TLS-ESNI-01这与更新草稿版本。
我发布了 2019 年 4 月观察到的生态系统状况这里:
- 最新版本是https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-03
- OpenSSL 正在等待草案完成。https://github.com/openssl/openssl/issues/7482
- Firefox+NSS 支持草案-01https://bugzilla.mozilla.org/show_bug.cgi?id=1495120 https://github.com/nss-dev/nss/blob/8a8b92f05d2d/lib/ssl/tls13esni.c
- Cloudflare 支持草稿 -01
- picotls 支持它https://github.com/h2o/picotls/pull/155
- 在 ESNI 被广泛部署之前,Go crypto/tls 不会支持它:https://github.com/golang/go/issues/9671#issuecomment-439561672
如您所见,Nginx 和 Apache 使用的 OpenSSL 不支持它。您可以尝试构建球童使用已修补的 Go crypto/tls 库(使用来自 tls-tris 的 PR),但随着时间的推移它可能不会起作用。
实验
为了实验或者出于教育目的,你可以使用 esnitool 和 tris-localserver三羟甲基氨基甲烷假设你已经在 Linux 或 macOS 上安装了适当的 Go 工具链,那么类似下面的操作应该可以工作:
# Get source code and build stuff
git clone https://github.com/cloudflare/tls-tris -b pwu/esni
cd tls-tris
make build-esnitool
(cd _dev/tris-localserver && ../go.sh build -v -i .)
# Generate ESNI key material, valid for 24 hours (one day)
_dev/esnitool/esnitool -validity=24h -esni-keys-file=esni.pub -esni-private-file=esni.key
它将创建两个文件:
- esni.pub - 您必须在 DNS 中配置的值
/wFsX6klACQA...AAAA=
。如果您想为 配置 ESNI ,请使用该值www.example.com
创建 TXT 记录。此格式符合 Firefox 和 Cloudflare 支持的 draft-ietf-tls-esni-01 规范。它确实_esni.www.example.com
/wFsX6klACQA<snip>AAAA=
不是使用最新的草案规范。 - esni.priv - 一个私钥文件,特定于测试实现。
测试服务器可以通过如下方式启动:
_dev/tris-localserver/tris-localserver -esni-keys=esni.pub -esni-private=esni.priv
然后配置 Firefox 以启用使用 ESNI,打开about:config
并设置network.security.esni.enabled
为 true。您还必须启用 DNS-over-HTTPS,Firefox 说明可在该页面上找到。有关每个首选项的更多详细信息,也可以在此处找到:https://bagder.github.io/TRRprefs/
这些说明现在可能有效,但将来会失效,因为 Firefox 可能会更新以支持较新的草稿版本。上面的 esnitool 还硬编码了允许的密码套件 (AES128-GCM) 和密钥交换算法 (X25519)。这反映了 Cloudflare 使用的参数。
评论
ESNI 意味着 TLS 1.3,因此证书及其嵌入的主机名将被加密。启用 ESNI 并使用安全 DNS 传输(例如 DNS-over-HTTPS (DoH) 或 DNS-over-TLS (DoT))后,服务器名称确实不会在网络上显示,这可以在 Wireshark 中使用过滤器(例如frame contains "wireshark"
访问 )进行验证wireshark.org
。
但是,如果单个 IP 仅托管几个域名,那么任何被动对手都可以猜到您正在访问其中一个域名。像 Cloudflare 这样的大型运营商拥有更多域名,因此这不是什么大问题。
由于 ESNI 使用半静态密钥,因此私钥泄露意味着任何窃听者都可以解密加密的服务器名称。这就是为什么 ESNI 密钥经常轮换,并且需要自动化。Cloudflare 已将其很好地集成在一起,DNS 和 HTTPS 服务中的 ESNI 密钥会定期更新。
总而言之,ESNI 前景光明,但需要客户端(Web 浏览器)、安全传输(DoH/DoT)上的 DNS 服务器和 Web 服务器的支持。它仍处于开发阶段,除非您密切关注其开发,否则将其用于实验以外的用途可能不是一个好主意。
答案2
先前非常详细的答案启发了重复使用三羟甲基氨基甲烷构建微型 esni 反向代理,它实际上可以使用 ESNI 终止 TLS 1.3 并将纯流量转发到您选择的后端。这允许轻松使用 ESNI,而无需对您正在使用的 Web 服务器进行任何修改。源代码和详细说明可以在这里找到:esni-rev-代理