Merhaba Habr, adım İlya, Exness'te platform ekibinde çalışıyorum. Ürün geliştirme ekiplerimizin kullandığı temel altyapı bileşenlerini geliştiriyor ve uyguluyoruz.
Bu yazıda, şifreli SNI (ESNI) teknolojisinin halka açık web sitelerinin altyapısında uygulanmasına ilişkin deneyimimi paylaşmak istiyorum.
Bu teknolojinin kullanılması, halka açık bir web sitesiyle çalışırken güvenlik düzeyini artıracak ve Şirket tarafından benimsenen iç güvenlik standartlarına uyum sağlayacaktır.
Öncelikle teknolojinin standartlaşmadığını ve henüz taslak aşamasında olduğunu ancak CloudFlare ve Mozilla'nın zaten desteklediğini belirtmek isterim (içinde
Biraz teori
ESNI TLS el sıkışma "İstemci Merhaba" mesajında SNI şifrelemesine izin veren TLS 1.3 protokolünün bir uzantısıdır. ESNI desteğiyle Client Hello şu şekilde görünüyor (her zamanki SNI yerine ESNI'yi görüyoruz):
ESNI'yi kullanmak için üç bileşene ihtiyacınız vardır:
- DNS'ler;
- Müşteri desteği;
- Sunucu tarafı desteği.
DNS
İki DNS kaydı eklemeniz gerekir – Ave TXT (TXT kaydı, istemcinin SNI'yı şifreleyebileceği ortak anahtarı içerir) - aşağıya bakın. Ayrıca destek de olmalı Sağlık Bakanlığı (HTTPS üzerinden DNS) çünkü mevcut istemciler (aşağıya bakın) DoH olmadan ESNI desteğini etkinleştirmez. ESNI, eriştiğimiz kaynağın adının şifrelenmesini gerektirdiğinden, bu mantıklıdır, yani DNS'ye UDP üzerinden erişmenin bir anlamı yoktur. Üstelik kullanım
Şu anda mevcut
CloudFlare
А kayıt:
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 kayıt, istek bir şablona göre oluşturulur _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."
}
Dolayısıyla, DNS açısından bakıldığında DoH kullanmalı (tercihen DNSSEC ile) ve iki giriş eklemeliyiz.
Müşteri desteği
Tarayıcılardan bahsediyorsak, şu anda
ESNI, TLS 1.3'ün bir uzantısı olduğundan, elbette ESNI'yi desteklemek için TLS 1.3 kullanılmalıdır.
Arka ucu ESNI desteğiyle test etmek amacıyla istemciyi şu adreste uyguladık: go, Ama daha sonra.
Sunucu tarafı desteği
Şu anda ESNI, resmi olarak ESNI'yi desteklemeyen nginx/Apache vb. web sunucuları tarafından OpenSSL/BoringSSL üzerinden TLS ile çalıştıkları için desteklenmemektedir.
Bu nedenle, ESNI ile TLS 1.3 sonlandırmayı ve ESNI'yi desteklemeyen yukarı akışa proxy HTTP(S) trafiğini destekleyecek kendi ön uç bileşenimizi (ESNI ters proxy) oluşturmaya karar verdik. Bu, teknolojinin ana bileşenleri değiştirmeden, yani ESNI'yi desteklemeyen mevcut web sunucularını kullanmadan, halihazırda mevcut bir altyapıda kullanılmasına olanak tanır.
Açıklık sağlamak için, burada bir diyagram var:
Proxy'nin, ESNI olmayan istemcileri desteklemek için ESNI olmadan TLS bağlantısını sonlandırabilecek şekilde tasarlandığını unutmayın. Ayrıca, yukarı akışlı iletişim protokolü HTTP veya TLS sürümü 1.3'ün altında olan HTTPS olabilir (yukarı akış 1.3'ü desteklemiyorsa). Bu şema maksimum esneklik sağlar.
ESNI desteğinin uygulanması go ödünç aldık
ESNI anahtarlarını oluşturmak için kullandık
Yapıyı Linux (Debian, Alpine) ve MacOS'ta go 1.13 kullanarak test ettik.
Operasyonel özellikler hakkında birkaç kelime
ESNI ters proxy, rps, yukarı akış gecikmesi ve yanıt kodları, başarısız/başarılı TLS anlaşmaları ve TLS anlaşması süresi gibi Prometheus formatında ölçümler sağlar. İlk bakışta bu, proxy'nin trafiği nasıl yönettiğini değerlendirmek için yeterli görünüyordu.
Kullanmadan önce yük testi de yaptık. Aşağıdaki sonuçlar:
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 ters proxy kullanan ve içermeyen şemayı karşılaştırmak için tamamen niteliksel yük testi gerçekleştirdik. Ara bileşenlerdeki "paraziti" ortadan kaldırmak için trafiği yerel olarak "döktük".
Dolayısıyla, ESNI desteği ve HTTP'den yukarı akışa proxy oluşturma sayesinde, ESNI ters proxy'nin ortalama CPU/RAM tüketimiyle bir örnekten yaklaşık ~550 rps elde ettik:
- %80 CPU Kullanımı (4 vCPU, 4 GB RAM ana bilgisayarları, Linux)
- 130 MB Hafıza RSS
Karşılaştırma için, TLS (HTTP protokolü) sonlandırması olmayan aynı nginx yukarı akışı için RPS ~ 1100'dür:
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
Zaman aşımlarının varlığı, kaynak eksikliği olduğunu gösterir (4 vCPU, 4 GB RAM ana bilgisayarı, Linux kullandık) ve aslında potansiyel RPS'nin daha yüksek olduğunu (daha güçlü kaynaklarda 2700 RPS'ye kadar rakamlar aldık).
Sonuç olarak şunu not ediyorum ESNI teknolojisi oldukça umut verici görünüyor. Hala pek çok açık soru var, örneğin, genel ESNI anahtarının DNS'de saklanması ve ESNI anahtarlarının döndürülmesi sorunları - bu konular aktif olarak tartışılıyor ve ESNI taslağının en son sürümü (yazıldığı sırada) zaten mevcut
Kaynak: habr.com