
我有運行多個虛擬主機的 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 庫(使用此 PR 來自 tls-tris),但隨著時間的推移,它可能不起作用。
實驗
為了實驗或出於教育目的,您可以使用 esnitool 和 tris-localservertls-tris。假設你在 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 - 一個值,例如
/wFsX6klACQA...AAAA=
您必須在 DNS 中配置的值。如果您想要設定 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 中的 ESNI 金鑰和 HTTPS 服務會定期更新。
總而言之,ESNI 前景廣闊,但需要用戶端(Web 瀏覽器)、安全傳輸上的 DNS 伺服器 (DoH/DoT) 和 Web 伺服器的支援。它仍在開發中,除非您密切注意其開發,否則將其設置用於實驗以外的其他用途可能不是一個好主意。
答案2
之前非常詳細的答案啟發了重用tls-tris建立微型 esni 反向代理,它實際上可以使用 ESNI 終止 TLS 1.3 並將普通流量轉送到您選擇的後端。這使得您可以輕鬆使用 ESNI,而無需對您正在使用的 Web 伺服器進行任何修改。原始碼和詳細說明可以在這裡找到:esni-rev-代理