なぜ今までのDNSでは問題があるのか
インターネット上の通信の多くは、ブラウザを利用したウェブによるものです。
セキュリティ向上のため、GoogleやFireFoxといった大手ブラウザベンダーが平文通信であるHTTPから暗号通信であるHTTPSへの移行を推奨し、盗聴・改竄・なりすましといった問題を解決することが出来ます。
しかしながら、そのHTTPS通信をする前のDNSによるドメイン解決は暗号化されておらず盗聴でアクセスするホスト名を把握される、なりすましで偽の応答を返されるといった可能性があります。
それを防ぐための方法の1つが、DNS over HTTPSです。
DNS over HTTPSとは
今までDNSサーバ(フルリゾルバ)の(主に)UDPポート53番に対して行われていたDNSによる名前解決を、TCPポート443番に対するHTTPS(HTTP/2 over TLS)通信上で行うプロトコルです。
RFC8484として標準化されました。
クライアント(スタブリゾルバ)からリクエストするときはGETメソッドもしくはPOSTメソッドを使用します。
リクエスト例を上記のRFCから引用します。
:method = GET
:scheme = https
:authority = dnsserver.example.net
:path = /dns-query?dns=AAABAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB
accept = application/dns-message
:method = POST
:scheme = https
:authority = dnsserver.example.net
:path = /dns-query
accept = application/dns-message
content-type = application/dns-message
content-length = 33
<33 bytes represented by the following hex encoding>
00 00 01 00 00 01 00 00 00 00 00 00 03 77 77 77
07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 01 00
01
POSTメソッドでのリクエストボディの中身はDNSメッセージのバイナリそのままです。
acceptヘッダーに見慣れないapplication/dns-messageというものが指定されていますね。
レスポンス例です。
:status = 200
content-type = application/dns-message
content-length = 61
cache-control = max-age=3709
<61 bytes represented by the following hex encoding>
00 00 81 80 00 01 00 01 00 00 00 00 03 77 77 77
07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 1c 00
01 c0 0c 00 1c 00 01 00 00 0e 7d 00 10 20 01 0d
b8 ab cd 00 12 00 01 00 02 00 03 00 04
content-typeにapplication/dns-messageが指定されています。
中身はPOSTでのリクエストと同じく返答のDNSメッセージのバイナリそのままです。
私はこの記事を書くために調べるまで、DNS over HTTPSはGETでリクエストパラメータで引きたいドメインを指定し、返答はJSONで返ってくるとものと思っていました。
これは2016年にGoogle Public DNSに実装された実験的な実装のもので、RFCで標準化されたものとは大きく異なる別物です。
参考 Google Public DNS over HTTPS を試す
{
"Status": 0,
"TC": false,
"RD": true,
"RA": true,
"AD": true,
"CD": false,
"Question": [{
"name": "www.example.com.",
"type": 1
}],
"Answer": [{
"name": "www.example.com.",
"type": 1,
"TTL": 19609,
"data": "93.184.216.34"
}]
}
DNS over TLSとの違いとは
初めに
それを防ぐための方法の1つが、DNS over HTTPSです。
と書きましたが、もう1つDNSを暗号化された経路で安全に問い合わせる方法がDNS over TLSでありRFC7858とRFC8310と標準化されています。
この2つで大きく異なるのが使用するポート番号です。DNS over HTTPSは通常のHTTPS通信と同じ443番を使いますが、DNS over TLSは853番がMUSTです。一見すると通常のHTTPS通信に紛れるDNS over HTTPSの方が良いと感じますが、逆に紛れてしまうことでネットワーク管理者から名前解決のトラフィックが見えなくなってしまうという反対意見があるとのことです。
例えば、組織内から外への接続でDNS over TLSが使用する853番への接続が急激に増えた時に管理者は「名前解決で何かトラブルがあったのではないか(どのドメインを問い合わせているかは分からない)」と把握することが出来ますが、DNS over HTTPSの場合は443番への接続なので「HTTPSのトラフィックが増えた」としか把握できないでしょう。
これをメリットと取るかデメリットと取るかは個々の利用者によって異なるでしょう。
参考 What is the difference between DNS over TLS & DNS over HTTPS?
DNSだけ暗号化しても足りないこと
さて、名前解決のためにDNS over HTTPSを使いWebサイトへアクセスするためにHTTPSを使えば盗聴・改竄・なりすましという問題を解決できるでしょうか?
現在、改竄となりすましについては対応できますがHTTPSの接続時のSNIという機能をもとに
- 盗聴してユーザーがどのドメインのWebサイトにアクセスしたかを把握する
- ユーザーがアクセスしようとするドメインを把握して強制的に切断する
ということができてしまいます。これはHTTPSのハンドシェイク時にどのドメインへ接続したいかというのをサーバーに対して「平文」で送るSNIという機能のためです。なぜ平文なのかというと、あるIPアドレスに対して複数のドメインが割り当てられ(バーチャルホストと呼ばれるものです)、それぞれ別々の証明書を用いる場合、ハンドシェイク中にどのドメインに対しての接続要求なのかをサーバーはクライアントから教えてもらわないと適切な証明書を選択できないためです。
タイムリーなことに韓国はこの平文のSNIフィールドを利用しアダルトサイトなどの政府が不法と認定したWebサイトをブロッキングしました。
アダルトサイトなど政府が不法と規定した有害サイトへの接続が11日から全面的に遮断された。
IT業界によると、KTなど韓国国内インターネットサービス事業者(ISP)は当局の要請を受け、11日から「サーバーネームインディケーション(SNI)フィールド遮断方式」を利用したウェブサイト遮断を始めた。
当局が従来使用した「URL遮断」はプロトコル「https」をアドレスバーに入力する方式で簡単に避けることができる。昨年10月に導入された「DNS(ドメインネームサーバー)遮断」方式もDNSアドレス変更などで迂回が可能だ。
今回導入したSNIはウェブサイト接続過程に適用される標準技術をいう。当局は接続過程でやり取りするサーバー名(ウェブサイトアドレス)が暗号化されずそのまま露出するという点を考慮して遮断を始めた。
https://headlines.yahoo.co.jp/hl?a=20190212-00000039-cnippou-kr
この接続したいドメインが盗聴できてしまうという問題に対しての解決策がTLS1.3拡張として提案されているEncrypted SNIです。
server_nameを送信するときにサーバーからの公開鍵をDNSで取得し、暗号化してからサーバに送信します。この時普通のDNSを使うと元の木阿弥です。DNS over HTTPSもしくはDNS over TLSを使います。
SNIの弱点に対して政府の検閲という分かりやすい攻撃がなされたため、このEncrypted SNI(とDNS over HTTPS)に対応するサーバーとクライアントが今後広まっていくのではないでしょうか。
参考
Encrypt it or lose it: how encrypted SNI works
Encrypted SNI / TLSハンドシェイクの暗号化