Ինչպես պաշտպանել ձեր հանրային կայքը ESNI-ի միջոցով

Բարև Հաբր, ես Իլյա եմ, ես աշխատում եմ Exness-ի հարթակի թիմում: Մենք մշակում և իրականացնում ենք ենթակառուցվածքի հիմնական բաղադրիչները, որոնք օգտագործում են մեր արտադրանքի մշակման թիմերը:

Այս հոդվածում ես կցանկանայի կիսվել հանրային կայքերի ենթակառուցվածքում կոդավորված SNI (ESNI) տեխնոլոգիայի ներդրման իմ փորձով:

Ինչպես պաշտպանել ձեր հանրային կայքը ESNI-ի միջոցով

Այս տեխնոլոգիայի օգտագործումը կբարձրացնի անվտանգության մակարդակը հանրային կայքի հետ աշխատելիս և կհամապատասխանի Ընկերության կողմից ընդունված ներքին անվտանգության չափանիշներին:

Նախ, ես կցանկանայի նշել, որ տեխնոլոգիան ստանդարտացված չէ և դեռևս նախագծային է, սակայն CloudFlare-ն ու Mozilla-ն արդեն աջակցում են այն ( նախագիծ01) Սա մեզ դրդեց նման փորձի:

Մի քիչ տեսություն

ԷՍՆԻ TLS 1.3 արձանագրության ընդլայնում է, որը թույլ է տալիս SNI կոդավորումը TLS ձեռքսեղմման «Client Hello» հաղորդագրության մեջ: Ահա, թե ինչպիսի տեսք ունի Client Hello-ն ESNI-ի աջակցությամբ (սովորական SNI-ի փոխարեն մենք տեսնում ենք ESNI).

Ինչպես պաշտպանել ձեր հանրային կայքը ESNI-ի միջոցով

 ESNI-ն օգտագործելու համար ձեզ հարկավոր է երեք բաղադրիչ.

  • DNS; 
  • Հաճախորդների աջակցություն;
  • Սերվերի կողմից աջակցություն:

DNS

Դուք պետք է ավելացնեք երկու DNS գրառում. AԻսկ Txt (TXT գրառումը պարունակում է հանրային բանալին, որով հաճախորդը կարող է գաղտնագրել SNI) - տես ստորև: Բացի այդ, պետք է լինի աջակցություն Դ (DNS HTTPS-ի միջոցով), քանի որ հասանելի հաճախորդները (տես ստորև) չեն միացնում ESNI-ի աջակցությունն առանց DoH-ի: Սա տրամաբանական է, քանի որ ESNI-ը ենթադրում է այն ռեսուրսի անվան կոդավորումը, որը մենք մուտք ենք գործում, այսինքն՝ անիմաստ է մուտք գործել DNS UDP-ի միջոցով: Ավելին, օգտագործումը DNSSEC- ը թույլ է տալիս պաշտպանվել քեշի թունավորման հարձակումներից այս սցենարում:

Ներկայումս հասանելի է DoH մի քանի մատակարարներ, նրանց մեջ:

CloudFlare հայտարարում է (Ստուգեք Իմ զննարկիչը → Կոդավորված SNI → Իմացեք ավելին), որ նրանց սերվերներն արդեն աջակցում են 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-ի ընդլայնումն է:

ESNI աջակցությամբ backend-ը փորձարկելու նպատակով մենք ներդրեցինք հաճախորդը go, Բայց դրա մասին ավելի ուշ:

Սերվերի կողմից աջակցություն

Ներկայումս ESNI-ն չի աջակցվում վեբ սերվերների կողմից, ինչպիսիք են nginx/apache-ը և այլն, քանի որ նրանք աշխատում են TLS-ի հետ OpenSSL/BoringSSL-ի միջոցով, որոնք պաշտոնապես չեն աջակցում ESNI-ին:

Հետևաբար, մենք որոշեցինք ստեղծել մեր սեփական առջևի բաղադրիչը (ESNI հակադարձ պրոքսի), որը կաջակցի TLS 1.3 դադարեցմանը ESNI-ով և պրոքսի HTTP(S) տրաֆիկով դեպի վերին հոսանքը, որը չի աջակցում ESNI-ին: Սա թույլ է տալիս տեխնոլոգիան օգտագործել արդեն գոյություն ունեցող ենթակառուցվածքում՝ առանց հիմնական բաղադրիչները փոխելու, այսինքն՝ օգտագործելով ընթացիկ վեբ սերվերները, որոնք չեն աջակցում ESNI-ին: 

Պարզության համար ահա դիագրամ.

Ինչպես պաշտպանել ձեր հանրային կայքը ESNI-ի միջոցով

Ես նշում եմ, որ վստահված անձը նախագծվել է առանց ESNI-ի TLS կապը դադարեցնելու, առանց ESNI-ի հաճախորդներին աջակցելու հնարավորությամբ: Բացի այդ, վերին հոսքի հետ կապի արձանագրությունը կարող է լինել կամ HTTP կամ HTTPS՝ 1.3-ից ցածր TLS տարբերակով (եթե վերին հոսքը չի աջակցում 1.3-ին): Այս սխեման տալիս է առավելագույն ճկունություն:

ESNI-ի աջակցության իրականացում go մենք պարտք ենք վերցրել CloudFlare. Անմիջապես ուզում եմ նշել, որ իրականացումն ինքնին բավականին աննշան է, քանի որ այն ներառում է փոփոխություններ ստանդարտ գրադարանում ծպտյալ/tls և հետևաբար պահանջում է «կարկատում» ԳՈՐՈՏ ժողովից առաջ:

ESNI ստեղները ստեղծելու համար մենք օգտագործել ենք esnitool (նաև CloudFlare-ի մտահղացումն է): Այս բանալիներն օգտագործվում են SNI կոդավորման/գաղտնագրման համար:
Մենք փորձարկեցինք կառուցվածքը՝ օգտագործելով go 1.13 Linux (Debian, Alpine) և MacOS-ի վրա: 

Մի քանի խոսք գործառնական հատկանիշների մասին

ESNI հակադարձ պրոքսի-ն ապահովում է չափումներ Պրոմեթևսի ձևաչափով, ինչպիսիք են 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 պտ/վ մեկ օրինակից՝ ESNI հակադարձ պրոքսիի միջին CPU/RAM սպառմամբ.

  • 80% CPU-ի օգտագործում (4 vCPU, 4 ԳԲ RAM հոսթ, Linux)
  • 130 ՄԲ Mem RSS

Ինչպես պաշտպանել ձեր հանրային կայքը ESNI-ի միջոցով

Համեմատության համար, RPS-ը նույն nginx-ի վերին հոսանքում առանց 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 ԳԲ RAM հոսթ, Linux), և իրականում պոտենցիալ RPS-ն ավելի բարձր է (ավելի հզոր ռեսուրսների վրա մենք ստացել ենք մինչև 2700 RPS թվեր):

Եզրափակելով՝ նշում եմ որ ESNI տեխնոլոգիան բավականին խոստումնալից տեսք ունի: Դեռևս կան շատ բաց հարցեր, օրինակ՝ DNS-ում հանրային ESNI բանալու պահպանման և ESNI ստեղների պտտման հարցերը. այս հարցերն ակտիվորեն քննարկվում են, և ESNI նախագծի վերջին տարբերակը (գրելու պահին) արդեն կա։ 7.

Source: www.habr.com

Добавить комментарий