DNS over HTTPSについて調べてみた

 Mozilla Foundation と Cloudflare が協力して DNS over HTTPS の開発をしているらしい.DNS over HTTPS を使うことで,中間者攻撃の脅威が減り,さらに,ユーザがオンライン上で監視されないようになるそうだ.

 従来の DNS クエリは,TCP や UDP を使って平文で送信されているため,訪問した Web サイトのサイト名や訪問日時などの情報を ISP などの第三者に知られてしまう.さらに,近年,フリー Wi-Fi スポットの数が増えており,盗聴されてしまう機会が以前よりも増えている.DNS over HTTPS では,HTTPS 経由で DNS クエリを送信するため,通信内容が暗号化されており,ISP に DNS クエリを盗聴される心配がなくなる.そのため,DNS over HTTPS と HTTPS 対応 Web サイトを利用すれば,盗聴に関しては,安心して通信を行うことが出来る.

 冒頭に書いたとおり,DNS over HTTPS を使うことで,中間者攻撃の脅威を減らすことが出来る.DNS over HTTPS は,HTTPS の仕組みを利用しているため,DNS クエリがエンドツーエンドで暗号化される.これにより,DNS クエリの盗聴を防ぐことが出来る.しかし,DNS over HTTPS だけでは,DNS 応答の改ざんを検知することは出来ないため,完全な対策にはならない.DNS 応答の改ざんを検知するためには,DNSSEC を併用する必要がある.DNSSEC とは,ドメイン登録情報に電子署名を付加することで,改ざんされていないかを確かめられるようにした,DNS の拡張仕様である.Linux では,ローカルに DNSSEC 対応の検証用キャッシュサーバを建てることで簡単に導入することが出来る.

 DNS over HTTPS は,既に使うことができ,Cloudflare と Google の提供する DNS サーバが対応している.実際に,Firefox Developer Edition (62.0beta) で DNS over HTTPS の機能を有効化し,従来の DNS を使わない設定にしてみたが,普段どおりにブラウジングすることが出来た.有名なサイトだけでなく,自分の公開Webサーバにもアクセスすることが出来た.

 実際に使えることは分かったが,速度面が気になったので,実際に DNS over HTTPS と DNS の名前解決にかかる時間を比較した.DNS サーバはどちらも,Cloudflare のサービスを利用した.また,使用したコマンドは,DiG 9.13.0 と tcpdump 4.9.1 である.実行結果を以下に示す.

DNS

$ dig @1.1.1.1 www.mie-u.ac.jp

; <<>> DiG 9.13.0 <<>> @1.1.1.1 www.mie-u.ac.jp
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33598
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1452
;; QUESTION SECTION:
;www.mie-u.ac.jp.       IN  A

;; ANSWER SECTION:
www.mie-u.ac.jp.    557 IN  A   160.16.232.195

;; Query time: 16 msec
;; SERVER: 1.1.1.1#53(1.1.1.1)
;; WHEN: Sun Jul 29 14:09:16 JST 2018
;; MSG SIZE  rcvd: 60

$ tcpdump -i enp6s0 -n port 53 or port 443
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp6s0, link-type EN10MB (Ethernet), capture size 262144 bytes
14:09:16.635420 IP 192.168.11.11.47677 > 1.1.1.1.53: 33598+ [1au] A? www.mie-u.ac.jp. (56)
14:09:16.651506 IP 1.1.1.1.53 > 192.168.11.11.47677: 33598 1/0/1 A 160.16.232.195 (60)

2 packets captured
2 packets received by filter
0 packets dropped by kernel

DNS over HTTPS

$ dig @127.0.0.1 www.mie-u.ac.jp

; <<>> DiG 9.13.0 <<>> @127.0.0.1 www.mie-u.ac.jp
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18804
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1452
;; QUESTION SECTION:
;www.mie-u.ac.jp.       IN  A

;; ANSWER SECTION:
www.mie-u.ac.jp.    599 IN  A   160.16.232.195

;; Query time: 33 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Jul 29 14:08:34 JST 2018
;; MSG SIZE  rcvd: 75

$ tcpdump -i enp6s0 -n port 53 or port 443
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp6s0, link-type EN10MB (Ethernet), capture size 262144 bytes
14:08:34.226774 IP 192.168.11.11.35710 > 1.0.0.1.443: Flags [P.], seq 3410192216:3410192284, ack 2478732938, win 319, length 68
14:08:34.226977 IP 192.168.11.11.35710 > 1.0.0.1.443: Flags [P.], seq 68:188, ack 1, win 319, length 120
14:08:34.243724 IP 1.0.0.1.443 > 192.168.11.11.35710: Flags [.], ack 188, win 31, length 0
14:08:34.243882 IP 1.0.0.1.443 > 192.168.11.11.35710: Flags [P.], seq 1:43, ack 188, win 31, length 42
14:08:34.259425 IP 1.0.0.1.443 > 192.168.11.11.35710: Flags [P.], seq 43:211, ack 188, win 31, length 168
14:08:34.259434 IP 1.0.0.1.443 > 192.168.11.11.35710: Flags [P.], seq 211:249, ack 188, win 31, length 38
14:08:34.259456 IP 192.168.11.11.35710 > 1.0.0.1.443: Flags [.], ack 249, win 341, length 0

7 packets captured
7 packets received by filter
0 packets dropped by kernel

 tcpdump の結果を見ると,DNS では 53 番ポートを使っており,DNS over HTTPS では 443 番ポートを使っているので,意図したとおりに通信できていることが分かる.また,Query time に注目すると,DNS を使った方が小さくなっていることが分かる.より正確に比較するために,名前解決を 1000 回行い,その平均値と中央値を求めた.

# Query timeのログを取る
$ for i in {1..1000}; do dig @1.1.1.1 www.mie-u.ac.jp | grep "Query time" | grep -Eo "[0-9]+" >> dig_dns; sleep 0.01; done;
$ for i in {1..1000}; do dig @127.0.0.1 www.mie-u.ac.jp | grep "Query time" | grep -Eo "[0-9]+" >> dig_hod; sleep 0.01; done;

# 平均値
$ awk '{ sum += $1 } END { print sum/NR }' dig_dns
16.301
$ awk '{ sum += $1 } END { print sum/NR }' dig_hod
21.001

# 中央値
$ sort -n dig_dns | awk '{ a[i++] = $1; } END { print (a[500]+a[501])/2; }'
16
$ sort -n dig_hod | awk '{ a[i++] = $1; } END { print (a[500]+a[501])/2; }'
19

 平均値と中央値のどちらを見ても,従来の DNS を使った手法の方が速いことが分かる.しかし,その差は 5ms 以下であり,大差ではない.このことから,DNS over HTTPS は,速度面でも既に実用的であることが分かった.

 次に,どのようにして,DNSクエリをHTTPSに載せているかを調べた.IETF の Internet-Draft によると,content-type = application/dns-message として,基本的に HTTP/2 のフォーマットを使って送られるそうだ.実際に,Wireshark を使って通信内容を見たところ,Handshake や鍵の交換を行った後,http2 の形式 で Application Data として送られてきていた.プロトコルは,TLSv1.2 であり,HTTPS 対応サイトを見るときと同様,通信内容を覗き見ることは出来なかった.

まとめ

 HTTPS 対応 Web サイトと DNS over HTTPS と DNSSEC を組み合わせることによって,今まで対策が難しいとされていた中間者攻撃から身を守ることが出来るということが分かった.そして,DNS over HTTPS を既に実際に使えることが分かった.また,調べていく中で,今回取り上げた DNS over HTTPS の他にも,Google が TCP の改善を目的として作っているプロトコルの QUIC(Quick UDP Internet Connections)を利用した DNS over QUIC など,DNS をセキュアにするための研究・開発が様々行われていることを知った.Android も,今年発表されたプレビュー版で DNS over TLS をサポートし始めたそうだ.今後,どのように発展していくかが楽しみである.

参考文献

Tweet