A DNS üzemeltetésének különböző aspektusait már többször is említette a szerző több, az általa írt blogbejegyzésben. Ennek ellenére a fő hangsúly mindig a biztonság növelésére irányult, mivel ez a kulcsfontosságú Internet szolgáltatás elengedhetetlen a teljes online ökoszisztémához.

Mindeddig, annak ellenére, hogy egyértelműen léteznek sebezhetőségek a DNS forgalomban, amely nagyrészt nyílt formában továbbra is átjárható, ezzel a folyamatot hátráltatták a rosszindulatú szolgáltatók, akik a reklámok beágyazásával próbálnak jövedelmet növelni, állami hatóságok és cenzúra, valamint egyszerű bűnözők. , annak ellenére, hogy számos technológia létezik, mint például a DNSSEC/DANE, DNScrypt, DNS-over-TLS és DNS-over-HTTPS, akadozott. Ha a szerveroldali megoldások, amiből egyesek már régóta elérhetőek és ismertek, akkor a kliensek oldali szoftverek támogatása sajnos még mindig hagy kívánnivalót maga után.
Szerencsére a helyzet változik. Különösen a népszerű Firefox böngésző fejlesztői törekvéseikről beszélnek a közeljövőben a DoH (DNS-over-HTTPS) alapértelmezett támogatásának bevezetésével kapcsolatban. Ez segíthet megvédeni a WWW felhasználók DNS forgalmát a fent említett fenyegetésektől, de potenciálisan újakat is okozhat.
1. DNS-over-HTTPS problémák
Első ránézésre a DNS-over-HTTPS tömeges elterjedése a webes szoftverekben csak pozitív reakciót vált ki. Ám, ahogy mondani szokták, a részletekben rejlik a sátán.
Az első probléma, amely korlátozza a DoH széleskörű alkalmazást, hogy kizárólag a webes forgalomra összpontosít. Valóban, a HTTP protokoll, és annak legfrissebb kiadása, a DoH alapja, a WWW alapja. De az Internet nem csupán a web. Számos népszerű szolgáltatás létezik, mint például az elektronikus levelezés, különféle üzenetküldő alkalmazások, fájlátviteli rendszerek, multimédiás streamelés stb., amelyek nem használják a HTTP-t. Így, annak ellenére, hogy sokan a DoH-t csodagyógyszernek tekintik, valójában csak a böngésző alapú technológiákon kívüli alkalmazásához szükséges plusz (és felesleges) erőfeszítésekkel nem alkalmazható. Érdekes módon a DNS-over-TLS sokkal alkalmasabb lenne erre, mivel a szabványos DNS forgalmat a biztonságos TLS protokollba ágyazza.
A második probléma, amely potenciálisan sokkal jelentősebb, mint az első, a DNS by design decentralizációjának tényleges feladása a böngészőbeállításokban megadott egyetlen DoH-szerver használata érdekében. Különösen a Mozilla ajánlja a Cloudflare szolgáltatását. Hasonló szolgáltatást indították el más jelentős internetes szereplők is, például a Google. Így a DNS-over-HTTPS bevezetése abban a formában, ahogyan most javasolják, csupán növeli a végfelhasználók függőségét a legnagyobb szolgáltatóktól. Nem titok, hogy a DNS-kérések elemzése révén gyűjtött információk még több adatot tudnak összegyűjteni, és növelhetik ezek pontosságát és aktualitását.
Ebben a vonatkozásban a szerző a DNS-over-HTTPS tömeges bevezetése helyett a DNS-over-TLS és DNSSEC/DANE kombinációjának támogatója maradt, mint általános, biztonságos és a további internetes központosítást nem támogató eszköz a DNS-trafik biztonságának biztosítására. Sajnos gyorsan bevezetni a DoH alternatívái általános támogatását a kliensprogramokban, érthető okokból, nem várható, és annak sorsa egyelőre a biztonságos technológiák lelkes támogatóira hárul.
De ha már DoH-t kapunk, akkor miért ne használjuk, miután elkerüljük a vállalatok potenciális megfigyelését az ő szervereiken keresztül, a saját DNS-over-HTTPS szerverünk révén?
2. A DNS-over-HTTPS protokoll
Ha megnézzük a szabványt amely a DNS-over-HTTPS protokollt írja le, láthatjuk, hogy ez lényegében egy web API, amely lehetővé teszi a standard DNS csomag HTTP/2 protokollba való becsomagolását. Ez speciális HTTP-fejlécekkel, valamint a továbbított DNS adatok bináris formátumának átalakításával (lásd és a következő dokumentumok) valósul meg, lehetővé téve azok továbbítását és fogadását, valamint szükséges metaadatokkal való munkát.
A szabvány csak HTTP/2-t és védett TLS kapcsolatot támogat.
A DNS-kérés küldése történhet a standard GET és POST módszerekkel. Az előbbi esetén a kérés egy base64URL-kódolt stringgé van átalakítva, míg az utóbbi esetében a POST-kérés törzsén keresztül bináris formában. Ebben az esetben a kérés és a DNS válasz során egy speciális MIME-típust használunk application/dns-message.
root@eprove:~ # curl -H 'accept: application/dns-message' 'https://my.domaint/dns-query?dns=q80BAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE' -v
* Trying 2001:100:200:300::400:443...
* TCP_NODELAY set
* Connected to eprove.net (2001:100:200:300::400) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /usr/local/share/certs/ca-root-nss.crt
CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=my.domain
* start date: Jul 22 00:07:13 2019 GMT
* expire date: Oct 20 00:07:13 2019 GMT
* subjectAltName: host "my.domain" matched cert's "my.domain"
* issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x801441000)
> GET /dns-query?dns=q80BAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE HTTP/2
> Host: eprove.net
> User-Agent: curl/7.65.3
> accept: application/dns-message
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
< HTTP/2 200
< server: h2o/2.3.0-beta2
< content-type: application/dns-message
< cache-control: max-age=86274
< date: Thu, 12 Sep 2019 13:07:25 GMT
< strict-transport-security: max-age=15768000; includeSubDomains; preload
< content-length: 45
<
Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: " to save to a file.
* Failed writing body (0 != 45)
* stopped the pause stream!
* Connection #0 to host eprove.net left intactFelhívjuk figyelmét a fejlécre is cache-control: a webkiszolgáló válaszában. A paraméterben max-age az visszatért DNS rekordhoz tartozó TTL értékét (vagy a minimális értéket, ha több is van).
A fenti információk alapján a DoH szerver működése több lépésből áll.
- HTTP kérést fogad. Ha az GET, akkor dekódolja a csomagot base64URL kódolásról.
- Elküldi ezt a csomagot a DNS szervernek.
- Megkapja a választ a DNS szervertől
- Megkeresi a minimális TTL értéket a kapott rekordokban.
- Válaszol a kliensnek HTTP-n keresztül.
3. Saját DNS-over-HTTPS szerver
A legegyszerűbb, leggyorsabb és leghatékonyabb módja a saját DNS-over-HTTPS szerver indításának egy HTTP/2 webkiszolgáló használata , amiről a szerző már korábban is írt (lásd: „«).
Ez a választás mellett szól, hogy a DoH szerver összes kódja teljes mértékben megvalósítható a H2O-ba integrált értelmező eszközökkel. . A szabványos könyvtárakon kívül a DNS szerverrel való adatcsere érdekében szükséges egy Socket (mrbgem) könyvtár, amely, szerencsére, már be van építve a H2O 2.3.0-beta2 aktuális fejlesztői verziójába. a FreeBSD portokban. Nem nehéz azonban hozzáadni azt bármely korábbi verzióhoz is a repozitórium klónozásával. a mappába /deps a fordítás előtt.
root@beta:~ # uname -v
FreeBSD 12.0-RELEASE-p10 GENERIC
root@beta:~ # cd /usr/ports/www/h2o
root@beta:/usr/ports/www/h2o # make extract
===> A felhasználó elfogadta az MIT BSD2CLAUSE licencet
===> h2o-2.2.6 függ a fájltól: /usr/local/sbin/pkg - megtalálva
===> Az összes disztároló file letöltése szükséges a h2o-2.2.6 építéséhez
===> Kicsomagolás a h2o-2.2.6-hoz.
=> SHA256 ellenőrző összeg OK a h2o-h2o-v2.2.6_GH0.tar.gz.-ra.
===> h2o-2.2.6 függ a fájltól: /usr/local/bin/ruby26 - megtalálva
root@beta:/usr/ports/www/h2o # cd work/h2o-2.2.6/deps/
root@beta:/usr/ports/www/h2o/work/h2o-2.2.6/deps # git clone https://github.com/iij/mruby-socket.git
Klónozás a „mruby-socket”...
remote: Objektumok enumerálása: 385, kész.
remote: Összesen 385 (delta 0), újrahasznosított 0 (delta 0), pack-reused 385
Objektumok lekérése: 100% (385/385), 98.02 KiB | 647.00 KiB/s, kész.
Változások meghatározása: 100% (208/208), kész.
root@beta:/usr/ports/www/h2o/work/h2o-2.2.6/deps # ll
total 181
drwxr-xr-x 9 root wheel 18 12 aug. 16:09 brotli/
drwxr-xr-x 2 root wheel 4 12 aug. 16:09 cloexec/
drwxr-xr-x 2 root wheel 5 12 aug. 16:09 golombset/
drwxr-xr-x 4 root wheel 35 12 aug. 16:09 klib/
drwxr-xr-x 2 root wheel 5 12 aug. 16:09 libgkc/
drwxr-xr-x 4 root wheel 26 12 aug. 16:09 libyrmcds/
drwxr-xr-x 13 root wheel 32 12 aug. 16:09 mruby/
drwxr-xr-x 5 root wheel 11 12 aug. 16:09 mruby-digest/
drwxr-xr-x 5 root wheel 10 12 aug. 16:09 mruby-dir/
drwxr-xr-x 5 root wheel 10 12 aug. 16:09 mruby-env/
drwxr-xr-x 4 root wheel 9 12 aug. 16:09 mruby-errno/
drwxr-xr-x 5 root wheel 14 12 aug. 16:09 mruby-file-stat/
drwxr-xr-x 5 root wheel 10 12 aug. 16:09 mruby-iijson/
drwxr-xr-x 5 root wheel 11 12 aug. 16:09 mruby-input-stream/
drwxr-xr-x 6 root wheel 11 12 aug. 16:09 mruby-io/
drwxr-xr-x 5 root wheel 10 12 aug. 16:09 mruby-onig-regexp/
drwxr-xr-x 4 root wheel 10 12 aug. 16:09 mruby-pack/
drwxr-xr-x 5 root wheel 10 12 aug. 16:09 mruby-require/
drwxr-xr-x 6 root wheel 10 12 szept. 16:10 mruby-socket/
drwxr-xr-x 2 root wheel 9 12 aug. 16:09 neverbleed/
drwxr-xr-x 2 root wheel 13 12 aug. 16:09 picohttpparser/
drwxr-xr-x 2 root wheel 4 12 aug. 16:09 picotest/
drwxr-xr-x 9 root wheel 16 12 aug. 16:09 picotls/
drwxr-xr-x 4 root wheel 8 12 aug. 16:09 ssl-conservatory/
drwxr-xr-x 8 root wheel 18 12 aug. 16:09 yaml/
drwxr-xr-x 2 root wheel 8 12 aug. 16:09 yoml/
root@beta:/usr/ports/www/h2o/work/h2o-2.2.6/deps # cd ../../../
root@beta:/usr/ports/www/h2o # make install clean
...A webszerver konfigurációja alapvetően standard.
root@beta:\/usr\/ports\/www\/h2o # cd \/usr\/local\/etc\/h2o\/
root@beta:\/usr\/local\/etc\/h2o # cat h2o.conf
# Ez a példa konfiguráció érzékelteti, hogyan használható az h2o
# és egy magas biztonságú konfigurációt a TLS és HTTP fejlécekhez
# részletes dokumentációért lásd: https:\/\/h2o.examp1e.net\/
# és h2o --help a parancssori lehetőségekért és beállításokért
# v.20180207 (c)2018 Max Kostikov http:\/\/kostikov.co e-mail: max@kostikov.co
user: www
pid-file: \/var\/run\/h2o.pid
access-log:
path: \/var\/log\/h2o\/h2o-access.log
format: "%h %v %l %u %t "%r" %s %b "%{Referer}i" "%{User-agent}i""
error-log: \/var\/log\/h2o\/h2o-error.log
expires: off
compress: on
file.dirlisting: off
file.send-compressed: on
file.index: [ 'index.html', 'index.php' ]
listen:
port: 80
listen:
port: 443
ssl:
cipher-suite: ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS
cipher-preference: server
dh-file: \/etc\/ssl\/dhparams.pem
certificate-file: \/usr\/local\/etc\/letsencrypt\/live\/eprove.net\/fullchain.pem
key-file: \/usr\/local\/etc\/letsencrypt\/live\/my.domain\/privkey.pem
hosts:
"*.my.domain":
paths: &go_tls
"\/":
redirect:
status: 301
url: https:\/\/my.domain\/
"my.domain:80":
paths: *go_tls
"my.domain:443":
header.add: "Strict-Transport-Security: max-age=15768000; includeSubDomains; preload"
paths:
"\/dns-query":
mruby.handler-file: \/usr\/local\/etc\/h2o\/h2odoh.rbKivételt képez az URL-kezelő /dns-query amelyért felelős a DNS-over-HTTPS szerverünk, amely mruby nyelven íródott és a kezelő opcióval hívható meg mruby.handler-file.
root@beta: /usr/local/etc/h2o # cat h2odoh.rb
# H2O HTTP/2 webserver mint DNS-over-HTTP szolgáltatásként
# v.20190908 (c)2018-2019 Max Kostikov https://kostikov.co e-mail: max@kostikov.co
proc {|env|
if env['HTTP_ACCEPT'] == "application/dns-message"
case env['REQUEST_METHOD']
when "GET"
req = env['QUERY_STRING'].gsub(/^dns=/'', '')
# base64URL dekód
req = req.tr("-_", "+/")
if !req.end_with?("=") && req.length % 4 != 0
req = req.ljust((req.length + 3) & ~3, "=")
end
req = req.unpack1("m")
when "POST"
req = env['rack.input'].read
else
req = ""
end
if req.empty?
[400, { 'content-type' => 'text/plain' }, [ "Hibás kérés" ]]
else
# --- kérdezze meg a DNS szervert
sock = UDPSocket.new
sock.connect("localhost", 53)
sock.send(req, 0)
str = sock.recv(4096)
sock.close
# --- találja meg a legalacsonyabb TTL-t a válaszban
nans = str[6, 2].unpack1('n') # válaszok száma
if nans > 0 # nincs DNS hiba
shift = 12
ttl = 0
while nans > 0
# dolgozza fel a domain név tömörítést
if str[shift].unpack1("C") curttl
ttl = curttl
end
nans -= 1
end
cc = 'max-age=' + ttl.to_s
else
cc = 'no-cache'
end
[200, { 'content-type' => 'application/dns-message', 'content-length' => str.size, 'cache-control' => cc }, [ str ] ]
end
else
[415, { 'content-type' => 'text/plain' }, [ "Támogatott média típus" ]]
end
}Kérjük, vegye figyelembe, hogy a DNS-csomagok kezeléséért a helyi gyorsítótárazó szerver felelős, jelen esetben a FreeBSD standard szállításából. Biztonsági szempontból ez az optimális megoldás. azonban semmi nem akadályozza meg, hogy helyette localhost másik DNS-címre váltson, amelyet használni kíván.
root@beta: /usr/local/etc/h2o # local-unbound verison
usage: local-unbound [options]
start unbound daemon DNS resolver.
-h ez a segítség
-c file beállítási fájl, amit a /var/unbound/unbound.conf helyett olvasunk
a fájlformátum az unbound.conf(5)-ben van leírva.
-d ne fork-olj a háttérbe.
-p ne hozzon létre pidfájlt.
-v részletes (több alkalommal a részletesség növeléséhez)
Version 1.8.1
linked libs: mini-event internal (select-t használ), OpenSSL 1.1.1a-freebsd 2018. november 20
linked modules: dns64 respip validator iterator
BSD licensz, lásd a LICENSE-t a forrás csomagban a részletekért.
Bugs can be reported to unbound-bugs@nlnetlabs.nl
root@eprove: /usr/local/etc/h2o # sockstat -46 | grep unbound
unbound local-unbo 69749 3 udp6 ::1:53 *:*
unbound local-unbo 69749 4 tcp6 ::1:53 *:*
unbound local-unbo 69749 5 udp4 127.0.0.1:53 *:*
unbound local-unbo 69749 6 tcp4 127.0.0.1:53 *:*Most indítsa újra a H2O-t, és nézze meg, mi sikerült ebből.
root@beta:/usr/local/etc/h2o # service h2o restart
H2o leállítása.
PID-ek várakozása: 69871.
H2o indítása.
start_server (pid:70532) most indítja el...4. Tesztelés
Tehát ellenőrizzük az eredményeket egy újabb tesztkérés elküldésével és a hálózati forgalom megfigyelésével egy segédprogram segítségével tcpdump.
root@beta/usr/local/etc/h2o # curl -H 'accept: application/dns-message' 'https://my.domain/dns-query?dns=q80BAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE'
Figyelmeztetés: A bináris kimenet megzavarhatja a terminálját. Használja a "--output -" opciót, hogy megmondja
Figyelmeztetés: a curl-nek, hogy a terminálra küldje a kimenetet, vagy fontolja meg a "--output
Figyelmeztetés: " fájlba mentését.
...
root@beta:~ # tcpdump -n -i lo0 udp port 53 -xx -XX -vv
tcpdump: figyelés a lo0-n, linktípus NULL (BSD loopback), rögzítési méret 262144 byte
16:32:40.420831 IP (tos 0x0, ttl 64, id 37575, offset 0, flags [none], proto UDP (17), hossz 57, hibás cksum 0 (->e9ea)!)
127.0.0.1.21070 > 127.0.0.1.53: [hibás udp cksum 0xfe38 -> 0x33e3!] 43981+ A? example.com. (29)
0x0000: 0200 0000 4500 0039 92c7 0000 4011 0000 ....E..9....@...
0x0010: 7f00 0001 7f00 0001 524e 0035 0025 fe38 ........RN.5.%.8
0x0020: abcd 0100 0001 0000 0000 0000 0765 7861 .............exa
0x0030: 6d70 6c65 0363 6f6d 0000 0100 01 mple.com.....
16:32:40.796507 IP (tos 0x0, ttl 64, id 37590, offset 0, flags [none], proto UDP (17), hossz 73, hibás cksum 0 (->e9cb)!)
127.0.0.1.53 > 127.0.0.1.21070: [hibás udp cksum 0xfe48 -> 0x43fa!] 43981 q: A? example.com. 1/0/0 example.com. A 93.184.216.34 (45)
0x0000: 0200 0000 4500 0049 92d6 0000 4011 0000 ....E..I....@...
0x0010: 7f00 0001 7f00 0001 0035 524e 0035 fe48 .........5RN.5.H
0x0020: abcd 8180 0001 0001 0000 0000 0765 7861 .............exa
0x0030: 6d70 6c65 0363 6f6d 0000 0100 01c0 0c00 mple.com........
0x0040: 0100 0100 0151 8000 045d b8d8 22 .....Q...].."
^C
2 csomag elfogva
23 csomag érkezett a szűrőhöz
0 csomag bukott el a kernelnélA kimenetből látható, hogy a címfeloldási kérelem example.com megérkezett és sikeresen feldolgozta a DNS szerver.
Most aktiválni kell a szerverünket a Firefox böngészőben. Ehhez a konfigurációs oldalon néhány beállítást módosítani kell about:config.

Először is, ez a mi API címünk, ahonnan a böngésző DNS információt fog kérni a network.trr.uri. Azt is javasoljuk, hogy a URL-ből megadott domain IP címét adja meg a böngésző számára, hogy biztonsosan le tudja kérni az IP-t a DNS törlése nélkül network.trr.bootstrapAddress. És végül, itt van a paraméter, network.trr.mode amely bekapcsolja a DoH használatát. Ha az értékét "3"-ra állítja, a böngésző kizárólag a DNS-over-HTTPS-t fogja használni a nevek feloldásához, míg a megbízhatóbb és biztonságosabb "2" priorizálja a DoH-t, míg a standard DNS hívást tartja megoldásként.
5. NYERESÉG!
Hasznos volt a cikk? Akkor kérlek, ne habozz támogatni minket pénzadomány formájában (lent).
Forrás: habr.com
