Cara melindungi tapak web awam anda dengan ESNI

Hello Habr, nama saya Ilya, saya bekerja dalam pasukan platform di Exness. Kami membangunkan dan melaksanakan komponen infrastruktur teras yang digunakan oleh pasukan pembangunan produk kami.

Dalam artikel ini, saya ingin berkongsi pengalaman saya melaksanakan teknologi SNI (ESNI) yang disulitkan dalam infrastruktur laman web awam.

Cara melindungi tapak web awam anda dengan ESNI

Penggunaan teknologi ini akan meningkatkan tahap keselamatan apabila bekerja dengan laman web awam dan mematuhi piawaian keselamatan dalaman yang diterima pakai oleh Syarikat.

Pertama sekali, saya ingin menyatakan bahawa teknologi itu tidak diseragamkan dan masih dalam draf, tetapi CloudFlare dan Mozilla sudah menyokongnya (dalam draf01). Ini mendorong kami untuk eksperimen sedemikian.

Sedikit teori

ESNI ialah sambungan kepada protokol TLS 1.3 yang membenarkan penyulitan SNI dalam mesej "Helo Pelanggan" TLS jabat tangan. Inilah rupa Client Hello dengan sokongan ESNI (bukan SNI biasa yang kita lihat ESNI):

Cara melindungi tapak web awam anda dengan ESNI

 Untuk menggunakan ESNI, anda memerlukan tiga komponen:

  • DNS; 
  • Sokongan pelanggan;
  • Sokongan sisi pelayan.

DNS

Anda perlu menambah dua rekod DNS - Adan TXT (Rekod TXT mengandungi kunci awam yang digunakan oleh pelanggan untuk menyulitkan SNI) - lihat di bawah. Selain itu, mesti ada sokongan DoH (DNS melalui HTTPS) kerana pelanggan yang tersedia (lihat di bawah) tidak mendayakan sokongan ESNI tanpa DoH. Ini adalah logik, kerana ESNI membayangkan penyulitan nama sumber yang kami akses, iaitu, tidak masuk akal untuk mengakses DNS melalui UDP. Lebih-lebih lagi, penggunaan DNSSEC membolehkan anda melindungi daripada serangan keracunan cache dalam senario ini.

Tersedia pada masa ini beberapa pembekal DoH, antaranya:

CloudFlare mengisytiharkan (Semak Penyemak Imbas Saya β†’ SNI Disulitkan β†’ Ketahui Lebih Lanjut) bahawa pelayan mereka sudah menyokong ESNI, iaitu, untuk pelayan CloudFlare dalam DNS kami mempunyai sekurang-kurangnya dua rekod - A dan TXT. Dalam contoh di bawah kami menanyakan Google DNS (melalui HTTPS): 

А entri:

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 rekod, permintaan dijana mengikut templat _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."
}

Jadi, dari perspektif DNS, kita harus menggunakan DoH (sebaik-baiknya dengan DNSSEC) dan menambah dua entri. 

Sokongan pengguna

Jika kita bercakap tentang pelayar, maka pada masa ini sokongan hanya dilaksanakan dalam FireFox. ia adalah Berikut ialah arahan tentang cara mengaktifkan sokongan ESNI dan DoH dalam FireFox. Selepas penyemak imbas dikonfigurasikan, kita akan melihat sesuatu seperti ini:

Cara melindungi tapak web awam anda dengan ESNI

Link untuk menyemak pelayar.

Sudah tentu, TLS 1.3 mesti digunakan untuk menyokong ESNI, kerana ESNI ialah lanjutan kepada TLS 1.3.

Untuk tujuan menguji bahagian belakang dengan sokongan ESNI, kami melaksanakan klien pada go, Tetapi lebih lanjut mengenai itu kemudian.

Sokongan sisi pelayan

Pada masa ini, ESNI tidak disokong oleh pelayan web seperti nginx/apache, dsb., kerana ia berfungsi dengan TLS melalui OpenSSL/BoringSSL, yang tidak menyokong ESNI secara rasmi.

Oleh itu, kami memutuskan untuk mencipta komponen bahagian hadapan kami sendiri (proksi terbalik ESNI), yang akan menyokong penamatan TLS 1.3 dengan trafik ESNI dan HTTP(S) proksi ke huluan, yang tidak menyokong ESNI. Ini membolehkan teknologi digunakan dalam infrastruktur yang sedia ada, tanpa mengubah komponen utama - iaitu, menggunakan pelayan web semasa yang tidak menyokong ESNI. 

Untuk kejelasan, berikut adalah gambar rajah:

Cara melindungi tapak web awam anda dengan ESNI

Saya perhatikan bahawa proksi telah direka bentuk dengan keupayaan untuk menamatkan sambungan TLS tanpa ESNI, untuk menyokong pelanggan tanpa ESNI. Selain itu, protokol komunikasi dengan huluan boleh sama ada HTTP atau HTTPS dengan versi TLS lebih rendah daripada 1.3 (jika huluan tidak menyokong 1.3). Skim ini memberikan fleksibiliti maksimum.

Pelaksanaan sokongan ESNI pada go kami meminjam daripada CloudFlare. Saya ingin ambil perhatian segera bahawa pelaksanaan itu sendiri agak tidak penting, kerana ia melibatkan perubahan dalam perpustakaan standard crypto/tls dan oleh itu memerlukan "tampalan" GOROOT sebelum perhimpunan.

Untuk menjana kunci ESNI yang kami gunakan esnitool (juga cetusan idea CloudFlare). Kekunci ini digunakan untuk penyulitan/penyahsulitan SNI.
Kami menguji binaan menggunakan go 1.13 pada Linux (Debian, Alpine) dan MacOS. 

Beberapa perkataan tentang ciri operasi

Proksi terbalik ESNI menyediakan metrik dalam format Prometheus, seperti rps, kependaman huluan & kod tindak balas, jabat tangan TLS yang gagal/berjaya & tempoh jabat tangan TLS. Pada pandangan pertama, ini nampaknya mencukupi untuk menilai cara proksi mengendalikan trafik. 

Kami juga melakukan ujian beban sebelum digunakan. Keputusan di bawah:

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 

Kami menjalankan ujian beban kualitatif semata-mata untuk membandingkan skim menggunakan proksi terbalik ESNI dan tanpa. Kami "menuangkan" trafik secara tempatan untuk menghapuskan "gangguan" dalam komponen perantaraan.

Jadi, dengan sokongan ESNI dan proksi ke huluan daripada HTTP, kami menerima kira-kira ~550 rps daripada satu contoh, dengan purata penggunaan CPU/RAM proksi terbalik ESNI:

  • 80% Penggunaan CPU (4 vCPU, hos RAM 4 GB, Linux)
  • 130 MB Mem RSS

Cara melindungi tapak web awam anda dengan ESNI

Sebagai perbandingan, RPS untuk hulu nginx yang sama tanpa penamatan TLS (HTTP protocol) ialah ~ 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 

Kehadiran tamat masa menunjukkan bahawa terdapat kekurangan sumber (kami menggunakan 4 vCPU, hos 4 GB RAM, Linux), dan sebenarnya potensi RPS lebih tinggi (kami menerima angka sehingga 2700 RPS pada sumber yang lebih berkuasa).

Kesimpulannya, saya perhatikan bahawa teknologi ESNI kelihatan cukup menjanjikan. Masih terdapat banyak soalan terbuka, contohnya, isu penyimpanan kunci ESNI awam dalam DNS dan kunci ESNI berputar - isu ini sedang dibincangkan secara aktif, dan versi terkini draf ESNI (pada masa penulisan) sudah pun 7.

Sumber: www.habr.com

Tambah komen