如何使用 ESNI 保護您的公共網站

你好 Habr,我叫 Ilya,在 Exness 的平台團隊工作。 我們開發並實施產品開發團隊使用的核心基礎設施組件。

在這篇文章中,我想分享我在公共網站基礎設施中實施加密SNI(ESNI)技術的經驗。

如何使用 ESNI 保護您的公共網站

使用該技術將提高使用公共網站時的安全級別,並符合公司採用的內部安全標準。

首先,我想指出該技術尚未標準化,仍處於草案階段,但 CloudFlare 和 Mozilla 已經支援它(在 草稿01)。 這激勵我們進行這樣的實驗。

一點理論

ESNI 是 TLS 1.3 協定的擴展,允許在 TLS 握手「Client Hello」訊息中進行 SNI 加密。 這是支援 ESNI 的 Client Hello 的樣子(我們看到的是 ESNI,而不是通常的 SNI):

如何使用 ESNI 保護您的公共網站

 要使用 ESNI,您需要三個組件:

  • 域名系統; 
  • 客戶支援;
  • 伺服器端支援。

DNS

您需要新增兩個 DNS 記錄 – A的TXT (TXT 記錄包含客戶端可以用來加密 SNI 的公鑰) - 請參閱下文。 此外,還必須有支持 衛生部 (DNS over HTTPS),因為可用的客戶端(見下文)在沒有 DoH 的情況下無法啟用 ESNI 支援。 這是合乎邏輯的,因為 ESNI 意味著對我們正在存取的資源名稱進行加密,也就是說,透過 UDP 存取 DNS 是沒有意義的。 此外,使用 DNSSEC 允許您在這種情況下防範緩存中毒攻擊。

目前可用 多家衛生部提供者, 他們之中:

CloudFlare的 美國 (檢查我的瀏覽器→加密的SNI→了解更多)他們的伺服器已經支援ESNI,也就是說,對於DNS中的CloudFlare伺服器我們至少有兩筆記錄 - A和TXT。 在下面的範例中,我們查詢 Google DNS(透過 HTTPS): 

А 入口:

curl 'https://dns.google.com/resolve?name=www.cloudflare.com&type=A' 
-s -H 'accept: application/dns+json'
{
  "Status": 0,
  "TC": false,
  "RD": true,
  "RA": true,
  "AD": true,
  "CD": false,
  "Question": [
    {
      "name": "www.cloudflare.com.",
      "type": 1
    }
  ],
  "Answer": [
    {
      "name": "www.cloudflare.com.",
      "type": 1,
      "TTL": 257,
      "data": "104.17.210.9"
    },
    {
      "name": "www.cloudflare.com.",
      "type": 1,
      "TTL": 257,
      "data": "104.17.209.9"
    }
  ]
}

的TXT 記錄,根據範本產生請求 _esni.FQDN:

curl 'https://dns.google.com/resolve?name=_esni.www.cloudflare.com&type=TXT' 
-s -H 'accept: application/dns+json'
{
  "Status": 0,
  "TC": false,
  "RD": true,
  "RA": true,
  "AD": true,
  "CD": false,
  "Question": [
    {
    "name": "_esni.www.cloudflare.com.",
    "type": 16
    }
  ],
  "Answer": [
    {
    "name": "_esni.www.cloudflare.com.",
    "type": 16,
    "TTL": 1799,
    "data": ""/wEUgUKlACQAHQAg9SiAYQ9aUseUZr47HYHvF5jkt3aZ5802eAMJPhRz1QgAAhMBAQQAAAAAXtUmAAAAAABe3Q8AAAA=""
    }
  ],
  "Comment": "Response from 2400:cb00:2049:1::a29f:209."
}

因此,從 DNS 角度來看,我們應該使用 DoH(最好使用 DNSSEC)並新增兩個項目。 

客戶支援

如果我們談論瀏覽器,那麼現在 僅在 FireFox 中實現支持. 這裡 以下是有關如何在 FireFox 中啟動 ESNI 和 DoH 支援的說明。 配置瀏覽器後,我們應該會看到如下內容:

如何使用 ESNI 保護您的公共網站

鏈接 檢查瀏覽器。

當然,必須使用 TLS 1.3 來支援 ESNI,因為 ESNI 是 TLS 1.3 的擴充。

為了測試具有 ESNI 支援的後端,我們在 go, 但稍後會詳細介紹。

伺服器端支援

目前,nginx/apache 等 Web 伺服器不支援 ESNI,因為它們透過 OpenSSL/BoringSSL 使用 TLS,而 OpenSSL/BoringSSL 並不正式支援 ESNI。

因此,我們決定建立自己的前端元件(ESNI 反向代理),該元件將支援 ESNI 的 TLS 1.3 終止,並將 HTTP(S) 流量代理到不支援 ESNI 的上游。 這使得該技術可以在現有的基礎設施中使用,而無需更改主要元件 - 即使用不支援 ESNI 的當前 Web 伺服器。 

為了清楚起見,這裡有一個圖表:

如何使用 ESNI 保護您的公共網站

我注意到代理程式被設計為能夠在沒有 ESNI 的情況下終止 TLS 連接,以支援沒有 ESNI 的客戶端。 此外,與上游的通訊協定可以是 HTTP 或 HTTPS,且 TLS 版本低於 1.3(如果上游不支援 1.3)。 此方案提供了最大的靈活性。

ESNI 支援的實施 go 我們借用了 CloudFlare的。 我想立即指出,實現本身非常重要,因為它涉及標準庫的更改 加密/TLS 因此需要“打補丁” 組裝前。

為了產生 ESNI 金鑰,我們使用了 埃斯尼圖爾 (也是 CloudFlare 的創意)。 這些密鑰用於 SNI 加密/解密。
我們在 Linux(Debian、Alpine)和 MacOS 上使用 go 1.13 測試了建置。 

關於操作功能的一些說明

ESNI 反向代理提供 Prometheus 格式的指標,例如 rps、上游延遲和回應程式碼、失敗/成功的 TLS 握手和 TLS 握手持續時間。 乍一看,這似乎足以評估代理商如何處理流量。 

我們還在使用前進行了負載測試。 結果如下:

wrk -t50 -c1000 -d360s 'https://esni-rev-proxy.npw:443' --timeout 15s
Running 6m test @ https://esni-rev-proxy.npw:443
  50 threads and 1000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.77s     1.21s    7.20s    65.43%
    Req/Sec    13.78      8.84   140.00     83.70%
  206357 requests in 6.00m, 6.08GB read
Requests/sec:    573.07
Transfer/sec:     17.28MB 

我們進行了純粹的定性負載測試,以比較使用 ESNI 反向代理和不使用 ESNI 反向代理的方案。 我們在本地「倒」流量,是為了消除中間組件的「幹擾」。

因此,借助 ESNI 支援和來自 HTTP 的上游代理,我們從一個實例獲得了大約 550 rps,其中 ESNI 反向代理的平均 CPU/RAM 消耗如下:

  • 80% CPU 使用率(4 個 vCPU、4 GB RAM 主機、Linux)
  • 130 MB 記憶體 RSS

如何使用 ESNI 保護您的公共網站

作為比較,沒有 TLS(HTTP 協定)終止的相同 nginx 上游的 RPS 約為 1100:

wrk -t50 -c1000 -d360s 'http://lb.npw:80' –-timeout 15s
Running 6m test @ http://lb.npw:80
  50 threads and 1000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.11s     2.30s   15.00s    90.94%
    Req/Sec    23.25     13.55   282.00     79.25%
  393093 requests in 6.00m, 11.35GB read
  Socket errors: connect 0, read 0, write 0, timeout 9555
  Non-2xx or 3xx responses: 8111
Requests/sec:   1091.62
Transfer/sec:     32.27MB 

逾時的存在表明資源不足(我們使用了 4 個 vCPU、4 GB RAM 主機、Linux),而且實際上潛在的 RPS 更高(我們在更強大的資源上收到了高達 2700 RPS 的資料)。

總之,我注意到 ESNI 技術看起來很有前景。 仍然有許多懸而未決的問題,例如,在 DNS 中存儲公共 ESNI 密鑰和輪換 ESNI 密鑰的問題 - 這些問題正在積極討論,最新版本的 ESNI 草案(在撰寫本文時)已經發布 7.

來源: www.habr.com

添加評論