Erhöhen Sie Ihren DNS-over-HTTPS-Server

Verschiedene Aspekte des Betriebs von DNS wurden vom Autor in einer Reihe von Artikeln, die als Teil des Blogs veröffentlicht wurden, wiederholt angesprochen. Gleichzeitig lag das Hauptaugenmerk immer auf der Verbesserung der Sicherheit dieses Schlüsseldienstes für das gesamte Internet.


Doh


Trotz der offensichtlichen Verwundbarkeit des DNS-Verkehrs, der größtenteils immer noch im klaren übertragen wird, für böswillige Handlungen von Anbietern, die versuchen, ihr Einkommen durch die Einbettung von Werbung in Inhalte, staatliche Strafverfolgungsbehörden und Zensur zu steigern, bis vor kurzem Neben nur Kriminellen ist der Prozess der Verbesserung des Schutzes trotz des Vorhandenseins verschiedener Technologien wie DNSSEC / DANE, DNScrypt, DNS-over-TLS und DNS-over-HTTPS ins Stocken geraten. Und wenn Serverlösungen, von denen einige schon seit geraumer Zeit existieren, allgemein bekannt und verfügbar sind, lässt ihre Unterstützung durch Client-Software zu wünschen übrig.


Zum Glück ändert sich die Situation. Insbesondere die Entwickler des beliebten Firefox-Browsers kündigten Pläne an, in naher Zukunft den Standard-Support-Modus für DNS-over-HTTPS (DoH) zu aktivieren. Dies sollte dazu beitragen, den DNS-Verkehr des WWW-Benutzers vor den oben genannten Bedrohungen zu schützen, kann jedoch möglicherweise neue verursachen.



1. DNS-over-HTTPS-Probleme


Auf den ersten Blick löst der Beginn der massiven Einführung von DNS-over-HTTPS in im Internet laufende Software nur eine positive Reaktion aus. Der Teufel steckt jedoch im Detail.


Das erste Problem, das den Umfang der DoH-Massenverwendung einschränkt, ist der Fokus ausschließlich auf den Webverkehr. In der Tat bilden das HTTP-Protokoll und seine aktuelle Version von HTTP / 2, auf der DoH basiert, die Grundlage des WWW. Das Internet ist aber nicht nur das Web. Es gibt viele beliebte Dienste wie E-Mail, Messenger aller Art, Dateiübertragungssysteme, Multimedia-Streaming usw., die kein HTTP verwenden. Trotz der Wahrnehmung vieler DoH als Allheilmittel stellt sich heraus, dass es ohne zusätzliche (und unnötige) Anstrengungen für nichts anderes als die Browsertechnologie nicht anwendbar ist. Übrigens scheint DNS-over-TLS ein viel würdigerer Kandidat für diese Rolle zu sein, die die Kapselung des Standard-DNS-Verkehrs in ein sicheres Standard-TLS-Protokoll implementiert.


Das zweite Problem, das möglicherweise viel bedeutender ist als das erste, ist die tatsächliche Ablehnung des inhärenten dezentralen DNS durch das Design, um den in den Browsereinstellungen angegebenen einzelnen DoH-Server zu verwenden. Insbesondere bietet Mozilla an, den Dienst von Cloudflare zu nutzen. Ein ähnlicher Dienst wurde auch von anderen prominenten Persönlichkeiten des Internets, insbesondere Google, gestartet. Es stellt sich heraus, dass die Implementierung von DNS-over-HTTPS in der Form, in der es jetzt vorgeschlagen wird, nur die Abhängigkeit der Endbenutzer von den größten Diensten erhöht. Es ist kein Geheimnis, dass die Informationen, die die Analyse von DNS-Abfragen liefern kann, noch mehr Daten darüber sammeln und deren Genauigkeit und Relevanz erhöhen können.


In dieser Hinsicht war und ist der Autor ein Befürworter der Massenimplementierung von nicht DNS-over-HTTPS, sondern DNS-over-TLS zusammen mit DNSSEC / DANE als universelles, sicheres und nicht weiter förderndes Mittel zur Zentralisierung von Internetmitteln zur Gewährleistung der Sicherheit des DNS-Verkehrs. Leider gibt es keinen Grund, aus offensichtlichen Gründen mit der raschen Einführung der Massenunterstützung für DoH-Alternativen in Client-Software zu rechnen, und Enthusiasten sicherer Technologien bleiben ihr Schicksal.


Aber da wir jetzt DoH erhalten, können Sie es verwenden, nachdem Sie die potenzielle Überwachung durch Unternehmen über ihre Server auf Ihren eigenen DNS-over-HTTPS-Server eingestellt haben.


2. DNS-over-HTTPS


Wenn Sie sich den RFC8484- Standard ansehen , der das DNS-over-HTTPS-Protokoll beschreibt, sehen Sie, dass es sich tatsächlich um eine Web-API handelt, mit der Sie ein Standard-DNS-Paket in das HTTP / 2-Protokoll einkapseln können. Dies wird durch spezielle HTTP-Header implementiert und das Binärformat der übertragenen DNS-Daten (siehe RFC1035 und nachfolgende Dokumente) in ein Formular konvertiert , mit dem Sie sie senden und empfangen sowie mit den erforderlichen Metadaten arbeiten können.


Standardmäßig werden nur HTTP / 2 und eine sichere TLS-Verbindung unterstützt.


Eine DNS-Abfrage kann mit den Standardmethoden GET und POST gesendet werden. Im ersten Fall wird die Anforderung in eine base64URL-codierte Zeichenfolge und im zweiten Fall durch den Hauptteil der POST-Anforderung in binärer Form umgewandelt. In diesem Fall wird beim Abfragen und Beantworten von DNS eine spezielle MIME-Datentypanwendung / DNS -Nachricht verwendet .


root@eprove:~ # curl -H 'accept: application/dns-message' 'https://my.domain/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: <FILE>" to save to a file. * Failed writing body (0 != 45) * stopped the pause stream! * Connection #0 to host eprove.net left intact 

Beachten Sie auch den Cache-Control: Header in der Antwort vom Webserver. Der Parameter max-age enthält den TTL-Wert für den zurückgegebenen DNS-Eintrag (oder den Mindestwert, wenn der Satz zurückgegeben wird).


Basierend auf dem Vorstehenden besteht die Funktionsweise des DoH-Servers aus mehreren Stufen.


  • Empfangen Sie eine HTTP-Anfrage. Wenn es GET ist, dekodieren Sie das Paket aus der base64URL-Codierung.
  • Senden Sie dieses Paket an den DNS-Server.
  • Erhalten Sie eine Antwort vom DNS-Server
  • Suchen Sie den minimalen TTL-Wert in den empfangenen Datensätzen.
  • Rückgabe der HTTP-Antwort an den Client.

3. Eigener DNS-over-HTTPS-Server


Der einfachste, schnellste und effektivste Weg, einen eigenen DNS-over-HTTPS-Server zu starten, ist die Verwendung des HTTP / 2- H2O -Webservers, über den der Autor bereits kurz geschrieben hat (siehe " Hochleistungs-H2O-Webserver ").


Für diese Wahl spricht die Tatsache, dass der gesamte Code Ihres eigenen DoH-Servers mithilfe des im H2O selbst integrierten mruby- Interpreters vollständig implementiert werden kann . Zusätzlich zu den Standardbibliotheken benötigen Sie für die Kommunikation mit dem DNS-Server die Socket-Bibliothek (mrbgem), die glücklicherweise bereits in der aktuellen Entwicklungsversion von H2O 2.3.0-beta2 enthalten ist, die in den FreeBSD-Ports vorhanden ist. Es ist jedoch nicht schwierig, es zu einer früheren Version hinzuzufügen, indem das Socket-Bibliotheksrepository vor dem Kompilieren in das Verzeichnis / deps geklont wird .


 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 . 16:09 brotli/ drwxr-xr-x 2 root wheel 4 12 . 16:09 cloexec/ drwxr-xr-x 2 root wheel 5 12 . 16:09 golombset/ drwxr-xr-x 4 root wheel 35 12 . 16:09 klib/ drwxr-xr-x 2 root wheel 5 12 . 16:09 libgkc/ drwxr-xr-x 4 root wheel 26 12 . 16:09 libyrmcds/ drwxr-xr-x 13 root wheel 32 12 . 16:09 mruby/ drwxr-xr-x 5 root wheel 11 12 . 16:09 mruby-digest/ drwxr-xr-x 5 root wheel 10 12 . 16:09 mruby-dir/ drwxr-xr-x 5 root wheel 10 12 . 16:09 mruby-env/ drwxr-xr-x 4 root wheel 9 12 . 16:09 mruby-errno/ drwxr-xr-x 5 root wheel 14 12 . 16:09 mruby-file-stat/ drwxr-xr-x 5 root wheel 10 12 . 16:09 mruby-iijson/ drwxr-xr-x 5 root wheel 11 12 . 16:09 mruby-input-stream/ drwxr-xr-x 6 root wheel 11 12 . 16:09 mruby-io/ drwxr-xr-x 5 root wheel 10 12 . 16:09 mruby-onig-regexp/ drwxr-xr-x 4 root wheel 10 12 . 16:09 mruby-pack/ drwxr-xr-x 5 root wheel 10 12 . 16:09 mruby-require/ drwxr-xr-x 6 root wheel 10 12 . 16:10 mruby-socket/ drwxr-xr-x 2 root wheel 9 12 . 16:09 neverbleed/ drwxr-xr-x 2 root wheel 13 12 . 16:09 picohttpparser/ drwxr-xr-x 2 root wheel 4 12 . 16:09 picotest/ drwxr-xr-x 9 root wheel 16 12 . 16:09 picotls/ drwxr-xr-x 4 root wheel 8 12 . 16:09 ssl-conservatory/ drwxr-xr-x 8 root wheel 18 12 . 16:09 yaml/ drwxr-xr-x 2 root wheel 8 12 . 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 ... 

Die Webserverkonfiguration ist im Allgemeinen Standard.


 root@beta:/usr/ports/www/h2o # cd /usr/local/etc/h2o/ root@beta:/usr/local/etc/h2o # cat h2o.conf # this sample config gives you a feel for how h2o can be used # and a high-security configuration for TLS and HTTP headers # see https://h2o.examp1e.net/ for detailed documentation # and 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-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 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.rb 

Die einzige Ausnahme ist der URL / DNS -Abfrage- Handler, der tatsächlich für unseren h2odoh- DNS-over-HTTPS-Server verantwortlich ist, der in mruby geschrieben und über die Option mruby.handler-file handler aufgerufen wird.


 root@beta:/usr/local/etc/h2o # cat h2odoh.rb # H2O HTTP/2 web server as DNS-over-HTTP service # 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 decode 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' }, [ "Bad Request" ]] else # --- ask DNS server sock = UDPSocket.new sock.connect("localhost", 53) sock.send(req, 0) str = sock.recv(4096) sock.close # --- find lowest TTL in response nans = str[6, 2].unpack1('n') # number of answers if nans > 0 # no DNS failure shift = 12 ttl = 0 while nans > 0 # process domain name compression if str[shift].unpack1("C") < 192 shift = str.index("\x00", shift) + 5 if ttl == 0 # skip question section next end end shift += 6 curttl = str[shift, 4].unpack1('N') shift += str[shift + 4, 2].unpack1('n') + 6 # responce data size if ttl == 0 or ttl > 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' }, [ "Unsupported Media Type" ]] end } 

Bitte beachten Sie, dass der lokale Caching-Server für die Verarbeitung von DNS-Paketen verantwortlich ist, in diesem Fall Ungebunden von der Standard-FreeBSD-Distribution. Aus Sicherheitsgründen ist dies die beste Lösung. Nichts hindert jedoch daran, localhost durch die Adresse eines anderen DNS zu ersetzen, das Sie verwenden möchten.


 root@beta:/usr/local/etc/h2o # local-unbound verison usage: local-unbound [options] start unbound daemon DNS resolver. -h this help -c file config file to read instead of /var/unbound/unbound.conf file format is described in unbound.conf(5). -d do not fork into the background. -p do not create a pidfile. -v verbose (more times to increase verbosity) Version 1.8.1 linked libs: mini-event internal (it uses select), OpenSSL 1.1.1a-freebsd 20 Nov 2018 linked modules: dns64 respip validator iterator BSD licensed, see LICENSE in source package for details. Report bugs 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 *:* 

Es bleibt noch H2O neu zu starten und zu sehen, was daraus wurde.


 root@beta:/usr/local/etc/h2o # service h2o restart Stopping h2o. Waiting for PIDS: 69871. Starting h2o. start_server (pid:70532) starting now... 

4. Testen


Überprüfen Sie also die Ergebnisse, indem Sie erneut eine Testanforderung senden und den Netzwerkverkehr mit dem Dienstprogramm tcpdump anzeigen.


 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: <FILE>" 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 kernel 

Die Ausgabe zeigt, wie die Adressauflösungsanforderung von example.com vom DNS-Server empfangen und erfolgreich verarbeitet wurde.


Jetzt bleibt es, unseren Server im Firefox-Browser zu aktivieren. Dazu müssen Sie einige about: config- Einstellungen auf den Konfigurationsseiten ändern.


Firefox DNS-over-HTTPS-Konfiguration


Erstens ist dies die Adresse unserer API, unter der der Browser die DNS-Informationen in network.trr.uri abfragt . Es wird außerdem empfohlen, die Domänen-IP dieser URL für eine sichere IP-Auflösung mithilfe des Browsers selbst anzugeben, ohne auf DNS in network.trr.bootstrapAddress zuzugreifen. Und schließlich der Parameter network.trr.mode selbst, der die Verwendung von DoH umfasst. Wenn Sie den Wert auf "3" setzen, wird der Browser gezwungen, ausschließlich DNS-over-HTTPS zum Auflösen von Namen zu verwenden. Die zuverlässigere und sicherere "2" gibt DoH Priorität, wobei der Standard-DNS-Zugriff als Fallback verbleibt.


5. GEWINN!


War der Artikel hilfreich? Dann seien Sie bitte nicht schüchtern und unterstützen Sie das Geld durch das Spendenformular (unten).

Source: https://habr.com/ru/post/de467237/


All Articles