Πώς να προστατεύσετε τον δημόσιο ιστότοπο σας με το ESNI

Γεια σου Habr, με λένε Ilya, εργάζομαι στην ομάδα πλατφόρμας στην Exness. Αναπτύσσουμε και υλοποιούμε τα βασικά στοιχεία υποδομής που χρησιμοποιούν οι ομάδες ανάπτυξης προϊόντων μας.

Σε αυτό το άρθρο, θα ήθελα να μοιραστώ την εμπειρία μου από την εφαρμογή κρυπτογραφημένης τεχνολογίας SNI (ESNI) στην υποδομή δημόσιων ιστοσελίδων.

Πώς να προστατεύσετε τον δημόσιο ιστότοπο σας με το ESNI

Η χρήση αυτής της τεχνολογίας θα αυξήσει το επίπεδο ασφάλειας κατά την εργασία με έναν δημόσιο ιστότοπο και θα συμμορφώνεται με τα εσωτερικά πρότυπα ασφαλείας που έχουν υιοθετήσει η Εταιρεία.

Πρώτα απ 'όλα, θα ήθελα να επισημάνω ότι η τεχνολογία δεν είναι τυποποιημένη και είναι ακόμα στο προσχέδιο, αλλά το CloudFlare και η Mozilla την υποστηρίζουν ήδη (στο σχέδιο01). Αυτό μας παρακίνησε για ένα τέτοιο πείραμα.

Λίγο θεωρίας

ESNI είναι μια επέκταση του πρωτοκόλλου TLS 1.3 που επιτρέπει την κρυπτογράφηση SNI στο μήνυμα χειραψίας TLS "Client Hello". Δείτε πώς φαίνεται το Client Hello με την υποστήριξη ESNI (αντί για το συνηθισμένο SNI βλέπουμε το ESNI):

Πώς να προστατεύσετε τον δημόσιο ιστότοπο σας με το ESNI

 Για να χρησιμοποιήσετε το ESNI, χρειάζεστε τρία στοιχεία:

  • DNS; 
  • Υποστήριξη πελατών.
  • Υποστήριξη από την πλευρά του διακομιστή.

DNS

Πρέπει να προσθέσετε δύο εγγραφές DNS – AΚαι TXT (Η εγγραφή TXT περιέχει το δημόσιο κλειδί με το οποίο ο πελάτης μπορεί να κρυπτογραφήσει το SNI) - δείτε παρακάτω. Επιπλέον, πρέπει να υπάρχει υποστήριξη DoH (DNS μέσω HTTPS) επειδή οι διαθέσιμοι πελάτες (δείτε παρακάτω) δεν ενεργοποιούν την υποστήριξη ESNI χωρίς DoH. Αυτό είναι λογικό, καθώς το ESNI συνεπάγεται κρυπτογράφηση του ονόματος του πόρου στον οποίο έχουμε πρόσβαση, δηλαδή, δεν έχει νόημα η πρόσβαση στο DNS μέσω UDP. Επιπλέον, η χρήση DNSSEC σας επιτρέπει να προστατεύεστε από επιθέσεις δηλητηρίασης προσωρινής μνήμης σε αυτό το σενάριο.

Επί του παρόντος διαθέσιμο αρκετούς παρόχους DoH, ανάμεσα τους:

Cloudflare δηλώνει (Ελέγξτε το My Browser → Encrypted SNI → Learn More) ότι οι διακομιστές τους υποστηρίζουν ήδη ESNI, δηλαδή για διακομιστές CloudFlare στο DNS έχουμε τουλάχιστον δύο εγγραφές - 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. Εδώ Ακολουθούν οδηγίες σχετικά με τον τρόπο ενεργοποίησης της υποστήριξης ESNI και DoH στο FireFox. Αφού ρυθμιστεί το πρόγραμμα περιήγησης, θα πρέπει να δούμε κάτι σαν αυτό:

Πώς να προστατεύσετε τον δημόσιο ιστότοπο σας με το ESNI

Σύνδεσμος για να ελέγξετε το πρόγραμμα περιήγησης.

Φυσικά, το TLS 1.3 πρέπει να χρησιμοποιηθεί για την υποστήριξη του ESNI, αφού το ESNI είναι επέκταση του TLS 1.3.

Για τον σκοπό της δοκιμής του backend με υποστήριξη ESNI, εφαρμόσαμε τον πελάτη σε go, Αλλά περισσότερα για αυτό αργότερα.

Υποστήριξη από την πλευρά του διακομιστή

Προς το παρόν, το ESNI δεν υποστηρίζεται από διακομιστές ιστού όπως nginx/apache κ.λπ., καθώς λειτουργούν με TLS μέσω OpenSSL/BoringSSL, οι οποίοι δεν υποστηρίζουν επίσημα το ESNI.

Ως εκ τούτου, αποφασίσαμε να δημιουργήσουμε το δικό μας στοιχείο διεπαφής (ESNI reverse proxy), το οποίο θα υποστηρίζει τον τερματισμό TLS 1.3 με ESNI και την κυκλοφορία HTTP(S) διακομιστή μεσολάβησης προς την ανοδική ροή, η οποία δεν υποστηρίζει ESNI. Αυτό σας επιτρέπει να χρησιμοποιείτε την τεχνολογία σε μια ήδη υπάρχουσα υποδομή, χωρίς να αλλάξετε τα κύρια στοιχεία - δηλαδή, να χρησιμοποιείτε τρέχοντες διακομιστές ιστού που δεν υποστηρίζουν ESNI. 

Για λόγους σαφήνειας, εδώ είναι ένα διάγραμμα:

Πώς να προστατεύσετε τον δημόσιο ιστότοπο σας με το ESNI

Σημειώνω ότι ο διακομιστής μεσολάβησης σχεδιάστηκε με τη δυνατότητα τερματισμού μιας σύνδεσης TLS χωρίς ESNI, για υποστήριξη πελατών χωρίς ESNI. Επίσης, το πρωτόκολλο επικοινωνίας με upstream μπορεί να είναι είτε HTTP είτε HTTPS με έκδοση TLS μικρότερη από 1.3 (αν η upstream δεν υποστηρίζει την 1.3). Αυτό το σχήμα παρέχει μέγιστη ευελιξία.

Εφαρμογή της υποστήριξης ESNI στις go δανειστήκαμε από Cloudflare. Θα ήθελα να σημειώσω αμέσως ότι η ίδια η υλοποίηση είναι αρκετά μη τετριμμένη, καθώς περιλαμβάνει αλλαγές στην τυπική βιβλιοθήκη crypto/tls και επομένως απαιτεί «μπάλωμα» GOROOT πριν από τη συναρμολόγηση.

Για τη δημιουργία κλειδιών ESNI χρησιμοποιήσαμε esnitool (επίσης πνευματικό τέκνο του CloudFlare). Αυτά τα κλειδιά χρησιμοποιούνται για κρυπτογράφηση/αποκρυπτογράφηση SNI.
Δοκιμάσαμε την έκδοση χρησιμοποιώντας το go 1.13 σε Linux (Debian, Alpine) και MacOS. 

Λίγα λόγια για τα λειτουργικά χαρακτηριστικά

Ο αντίστροφος διακομιστής 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 και το διακομιστή μεσολάβησης σε ανάντη ροή από το HTTP, πήραμε περίπου ~550 rps από μία παρουσία, με τη μέση κατανάλωση CPU/RAM του αντίστροφου διακομιστή μεσολάβησης ESNI:

  • Χρήση CPU 80% (4 vCPU, 4 GB RAM κεντρικοί υπολογιστές, Linux)
  • 130 MB Mem RSS

Πώς να προστατεύσετε τον δημόσιο ιστότοπο σας με το ESNI

Για σύγκριση, το RPS για το ίδιο nginx upstream χωρίς τερματισμό TLS (πρωτόκολλο HTTP) είναι ~ 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 φαίνεται πολλά υποσχόμενη. Υπάρχουν ακόμα πολλά ανοιχτά ερωτήματα, για παράδειγμα, τα θέματα αποθήκευσης ενός δημόσιου κλειδιού ESNI στο DNS και η περιστροφή των κλειδιών ESNI - αυτά τα θέματα συζητούνται ενεργά και η τελευταία έκδοση του προσχέδιο ESNI (τη στιγμή που γράφονται αυτές οι γραμμές) είναι ήδη 7.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο