DNSi erinevate aspektide kasutamise üle on autor rääkinud korduvalt mitmes blogis avaldatud. Sellega kaasnevalt on keskendutud alati selle võtmetähtsusega internetiteenuse turvalisuse tõstmisele.

Kuni viimase ajani, vaatamata DNSi liikluse haavatavuse ilmsele iseloomule, mis enamikul juhtudel edastatakse endiselt avatud kujul, on üritustes, mis on suunatud teenusepakkujate kasumite suurendamisele reklaamiga sisu integreerimise kaudu, riiklike jõustruktuuride ja tsensuuri, samuti lihtsalt kurjategijate poolt, kaitse , vaatamata erinevate tehnoloogiate olemasolule, nagu DNSSEC/DANE, DNScrypt, DNS-over-TLS ja DNS-over-HTTPS, on takerdunud. Ja kuigi serverilahendused, millest mõned on juba pikka aega olemas, on laialdaselt tuntud ja saadaval, jätab nende toetamine klienditarkvaras palju soovida.
Õnneks on olukord muutumas. Eriti on populaarse brauseri Firefox arendajad teatanud kavatsusest lisada vaikimisi toetuse režiimi (DoH) lähitulevikus. See peaks aitama kaitsta WWW kasutaja DNSi liiklust eespool mainitud ohtude eest, kuid võib potentsiaalselt tekitada uusi.
1. DNS-over-HTTPS probleemid
Esmapilgul kutsub internetis töötavate programmide laienev DNS-over-HTTPS kasutuselevõtt esile ainult positiivset vastukaja. Kuid nagu öeldakse, peitub kurat detailides.
Esimene probleem, mis piirab DoH-i ulatuslikku rakendamist, on selle fookus ainult veebiliiklusele. Tõepoolest, HTTP-protokoll ja selle praegune versioon HTTP/2, millel DoH põhineb, on WWW aluseks. Kuid Internet ei ole ainult veeb. On palju populaarseid teenuseid, nagu e-post, erinevad sõnumirakendused, failide edastamise süsteemid, meedia voogedastus ja nii edasi, mis ei kasuta HTTP-d. Seega, hoolimata paljude nägemisest DoH-i kui imevahendit, osutub see rakendamatuks ilma täiendavate (ja niikuinii mitte vajalikud) pingutusteta, mitte millegi muu jaoks kui brauseritehnoloogiate jaoks. Juhul, kui DNS-over-TLS, mis pakub standardse DNS-i liikluse kapseldamist kaitstud standardprotokolli TLS-i, on sellel rollil palju sobivam kandidaat.
Teine probleem, mis on potentsiaalselt palju olulisem kui esimene, on tegelik loobumine DNS-i sisemisest detsentraliseeritusest, et kasutada brauseri seadetes määratud ühte DoH-serverit. Eelkõige pakub Mozilla kasutamiseks Cloudflare'i teenust. Sellise teenuse on käivitanud ka teised tuntud Interneti tegelased, sealhulgas Google. Tulemuseks on, et DNS-over-HTTPS rakendamine sellisel kujul, nagu seda praegu pakutakse, suurendab lõppkasutajate sõltuvust suurimatest teenustest. Pole saladus, et DNS-päringute analüüsi kaudu saadud teave suudab koguda veelgi rohkem andmeid isiku kohta ning suurendada nende täpsust ja asjakohasust.
Seetõttu on autor olnud ja jääb massilise rakendamise toetajaks mitte DNS-over-HTTPS-i, vaid DNS-over-TLS-i koos DNSSEC/DANE-ga kui universaalset, ohutut ja mitte edasist Interneti keskset struktuuri soosivat vahendit DNS-i liikluse turvalisuse tagamiseks. Kahjuks ei saa oodata kiiret massilist toetust DoH-i alternatiivide rakendamiseks kliendi tarkvaras, arvestades arusaadavaid põhjuseid, ja selle saatuseks jäävad seni entusiaste turvatehnoloogiate seas.
Kuid kuna me nüüd saame DoH-i, siis miks mitte seda kasutada, liikudes samal ajal potentsiaalse jälgimise vältimiseks korporatsioonide serverite käest omaenda DNS-over-HTTPS serverisse?
2. Protokoll DNS-over-HTTPS
Kui vaadata standardit Kirjeldades DNS-over-HTTPS protokolli, saab näha, et see on sisuliselt veeb API, mis võimaldab kapseldada standardset DNS-paketti HTTP/2 protokolli. See saavutatakse spetsiaalsete HTTP-peade ja edastatavate DNS-andmete binaarformaadi konversiooni abil (vt. ja järgnevad dokumendid) kujule, mis võimaldab neid edastada ja vastu võtta ning töötada vajalike metaandmetega.
Standardi kohaselt toetatakse ainult HTTP/2 ja turvalist TLS-ühendust.
DNS-päringu saatmine võib toimuda standardsete GET ja POST meetoditega. Esimesel juhul muudetakse päring base64URL-koodeeritud stringiks, teisel juhul — POST-päringu kehas binaarses vormis. Samuti, päringu ja vastuse puhul kasutatakse DNS-i spetsiaalset MIME-type andmeid. application/dns-message.
root@eprove:~ # curl -H 'accept: application/dns-message' 'https://my.domaint/dns-query?dns=q80BAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE' -v
* Ühendamine 2001:100:200:300::400:443...
* TCP_NODELAY seadistatud
* Ühendatud eprove.net (2001:100:200:300::400) port 443 (#0)
* ALPN, pakub h2
* ALPN, pakub http/1.1
* sertifikaadi kontrollimise asukoht on edukalt seadistatud:
* CAfile: /usr/local/share/certs/ca-root-nss.crt
CApath: puudu
* TLSv1.3 (VÄLJAS), TLS käteadagamine, Klient teretulek (1):
* TLSv1.3 (SISSE), TLS käteadagamine, Serveri teretulek (2):
* TLSv1.3 (SISSE), TLS käteadagamine, Krüpteeritud laiendused (8):
* TLSv1.3 (SISSE), TLS käteadagamine, Sertifikaadi (11):
* TLSv1.3 (SISSE), TLS käteadagamine, Sertifikaadi kontrollimine (15):
* TLSv1.3 (SISSE), TLS käteadagamine, Lõpetatud (20):
* TLSv1.3 (VÄLJAS), TLS vaheta krüptimist, Krüptimise spetsifikatsioon (1):
* TLSv1.3 (VÄLJAS), TLS käteadagamine, Lõpetatud (20):
* SSL-ühendus, kasutades TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server nõustus kasutama h2
* Serveri sertifikaat:
* teema: CN=my.domain
* alguskuupäev: Juuli 22 00:07:13 2019 GMT
* aegumiskuupäev: Oktoober 20 00:07:13 2019 GMT
* subjectAltName: host "my.domain" vastab sertifikaadi "my.domain"
* väljaandja: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
* SSL sertifikaadi kontrollimine õnnestus.
* Kasutades HTTP2, server toetab mitmikulisi kasutusi
* Ühenduse olek muutus (HTTP/2 kinnitatud)
* Kopeerides HTTP/2 andmeid voolupuhvrisse pärast uuendamist: len=0
* Kasutades Voogu ID: 1 (lihtne käitleja 0x801441000)
> GET /dns-query?dns=q80BAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE HTTP/2
> Host: eprove.net
> User-Agent: curl/7.65.3
> accept: application/dns-message
>
* TLSv1.3 (SISSE), TLS käteadagamine, Uus sessiooni pilet (4):
* Ühenduse olek muutus (MAX_CONCURRENT_STREAMS == 100)!
< HTTP/2 200
< server: h2o/2.3.0-beta2
< content-type: application/dns-message
< cache-control: max-age=86274
< date: Neljapäev, 12 Sept 2019 13:07:25 GMT
< strict-transport-security: max-age=15768000; includeSubDomains; preload
< content-length: 45
<
Hoiatus: Binaarne väljund võib häirida teie terminali. Kasutage "--output -" et öelda
Hoiatus: curl, et väljund seda teie terminalile anyway, või kaaluge "--output
Hoiatus: " salvestada faili.
* Keha kirjutamine ebaõnnestus (0 != 45)
* peatatud paus voog!
* Ühendus #0 hostiga eprove.net jääb puutumatuks.Pöörake tähelepanu ka päisele cache-control: veebiserveri vastuses. Parameetris max-age on TTL väärtus tagastatud DNS-kirje jaoks (või minimaalne väärtus, kui tagastatakse nende kogum).
Nagu eespool mainitud, koosneb DoH serveri töö mitmest etapist.
- Saada HTTP päring. Kui see on GET, siis dekodeeri pakett base64URL kodeeringust.
- Saada see pakett DNS serverile.
- Saada vastus DNS serverilt.
- Leida saadud kirjetes minimaalne TTL väärtus.
- Tagastada klientidele vastus HTTP kaudu.
3. Oma DNS-over-HTTPS server
Kõige lihtsam, kiirem ja tõhusam viis oma DNS-over-HTTPS serveri käivitamiseks tundub olevat HTTP/2 veebiserveri kasutamine. , millest autor on juba lühidalt rääkinud (vt '«).
See valik on soodne, kuna kogu oma DoH serveri kood saab täielikult teostada H2O-sse integreeritud tõlgiga. . Lisaks standardsetele raamatukogudele, on andmevahetuseks DNS serveriga vajalik raamatukogu (mrbgem) Socket, mis on õnneks juba kaasatud H2O 2.3.0-beta2 praeguses arenduses. FreeBSD portides. Siiski pole seda raske lisada ka igas varasemas versioonis, kloonides reposi. kausta /deps enne kompileerimist.
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
===> License MIT BSD2CLAUSE accepted by the user
===> h2o-2.2.6 depends on file: /usr/local/sbin/pkg - found
===> Fetching all distfiles required by h2o-2.2.6 for building
===> Extracting for h2o-2.2.6.
=> SHA256 Checksum OK for h2o-h2o-v2.2.6_GH0.tar.gz.
===> h2o-2.2.6 depends on file: /usr/local/bin/ruby26 - found
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
Клонирование в «mruby-socket»…
remote: Enumerating objects: 385, done.
remote: Total 385 (delta 0), reused 0 (delta 0), pack-reused 385
Получение объектов: 100% (385/385), 98.02 KiB | 647.00 KiB/s, готово.
Определение изменений: 100% (208/208), готово.
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 sep 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
...Veebiserveri konfiguratsioon on üheselt öeldes standardne.
root@beta: /usr/ports/www/h2o # cd /usr/local/etc/h2o/
root@beta: /usr/local/etc/h2o # cat h2o.conf
# see this configuration as a sample for how H2O can be utilized
# providing a high-security setup for TLS and HTTP headers
# for detailed documentation visit https://h2o.examp1e.net/
# and use h2o --help for command-line options and settings
# v.20180207 (c)2018 by 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.rbAinus on URL töötlemise käitleja /dns-query mille eest vastutab meie DNS-over-HTTPS server, mis on kirjutatud mruby keeles ja mida kutsutakse käsu käitleja kaudu mruby.handler-file.
root@beta:/usr/local/etc/h2o # cat h2odoh.rb
# H2O HTTP/2 veebiserver DNS-over-HTTP teenusena
# 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 dekodeerimine
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' }, [ "Vale päring" ]]
else
# --- küsi DNS serverilt
sock = UDPSocket.new
sock.connect("localhost", 53)
sock.send(req, 0)
str = sock.recv(4096)
sock.close
# --- leia madalaim TTL vastuses
nans = str[6, 2].unpack1('n') # vastuste arv
if nans > 0 # pole DNS viga
shift = 12
ttl = 0
while nans > 0
# töötle domeeninime kokkusurumine
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' }, [ "Toetamata meedia tüüp" ]]
end
}Märkus, et DNS pakettide töötlemise eest vastutab kohalik vahemälu server, antud juhul FreeBSD tavapakettidest. Turvalisuse seisukohalt on see optimaalne lahendus. Siiski ei takista miski vahetada localhost teise DNS aadressi vastu, mida plaanite kasutada.
root@beta:/usr/local/etc/h2o # local-unbound versioon
kasutus: local-unbound [valikud]
alustab unbound daemon DNS lahendajat.
-h see abi
-c fail konfiguratsioonifail, mida lugeda selle asemel /var/unbound/unbound.conf
faili formaat on kirjeldatud unbound.conf(5).
-d ärge taanduge taustale.
-p ärge looge pidfaili.
-v üksikasjalik (rohkem kordi, et suurendada üksikasjalikkust)
Versioon 1.8.1
Lingitud teegid: mini-event sisemine (kasutab select), OpenSSL 1.1.1a-freebsd 20 Nov 2018
Lingitud moodulid: dns64 respip validator iterator
BSD litsentsiga, vt LICENSE allika paketi üksikasjade jaoks.
Teata vigadest 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 *:*Peab H2O uuesti käivitama ja vaatama, mis sellest sai.
root@beta: /usr/local/etc/h2o # service h2o restart
Stopping h2o.
Waiting for PIDS: 69871.
Starting h2o.
start_server (pid:70532) starting now...4. Testimine
Nüüd kontrollime tulemusi, saates uuesti proovipäringu ja jälgides võrgu liiklust tööriista abil tcpdump.
root@beta/usr/local/etc/h2o # curl -H 'accept: application/dns-message' 'https://my.domain/dns-query?dns=q80BAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE'
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.
...
root@beta:~ # tcpdump -n -i lo0 udp port 53 -xx -XX -vv
tcpdump: listening on lo0, link-type NULL (BSD loopback), capture size 262144 bytes
16:32:40.420831 IP (tos 0x0, ttl 64, id 37575, offset 0, flags [none], proto UDP (17), length 57, bad cksum 0 (->e9ea)!)
127.0.0.1.21070 > 127.0.0.1.53: [bad 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), length 73, bad cksum 0 (->e9cb)!)
127.0.0.1.53 > 127.0.0.1.21070: [bad 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 packets captured
23 packets received by filter
0 packets dropped by kernelVäljastus näitab, kuidas päring aadressi lahendamiseks example.com oli vastu võetud ja edukalt töödeldud DNS-serveri poolt.
Nüüd peab meie server Firefoxi brauseris aktiveerima. Selleks tuleb konfiguratsioonilehel teha mõned seadistused about:config.

Esiteks, see on meie API aadress, mille kaudu brauser küsib DNS-i teavet network.trr.uri. Soovitatav on samuti määrata selle URL-i domeeni IP, et tagada IP-lahendamine otse brauseri kaudu ilma DNS-i poole pöördumata network.trr.bootstrapAddress. Ja lõpuks, tegelikult see parameeter network.trr.mode seal, mis lubab DoH-i kasutamist. Kui seadistate väärtuse "3", sunnib see brauserit kasutama ainult DNS-over-HTTPS nime lahendamiseks, samas kui usaldusväärsem ja turvalisem "2" eelistab DoH-i, jättes standardse DNS-i pöördumise varuvariandina.
5. KASUM!
Kas artikkel oli kasulik? Siis palun ärge piinake end ja toetage rahaga annetusvormi kaudu (allpool).
Allikas: habr.com
