本日のお題。
セキュリティの穴、DNSを何とかしましょう!
自宅用DNSサーバーを構築してからDNSがマイブームな今日この頃、プライベートDNSについての記事に出会いました。
以前から有効にはしていましたが、どんな動作をしているのか気になって調査してみました。
追記
先日Microsoft
さんが華麗な手のひらクルーを発揮してWindows 11
を公開しました。
さて、Windows 11
では標準でDoH
という暗号化DNSを利用可能です。
記事の最後に設定方法などを記しました。
プライベートDNSとは?
Android 9 (Pie)
以降のスマートフォンに実装されている機能で、以下のような感じでアクセスできると思います。
-
設定
→その他の接続
→プライベートDNS
-
設定
→ネットワークとインターネット
→プライベートDNS
-
設定
→ネットワークとインターネット
→詳細設定
→プライベートDNS
取り敢えずはプライベートDNSを設定
を選択してdns.google
やone.one.one.one
などと打ち込むと設定が完了します。
ほぼ同様の内容ですが、Google Public DNSに詳しい説明が記載されています。
なお、自動
に設定した場合は、設定中のDNSサーバーが本機能に対応している場合に有効となります。
どういう機能?
Android Developers Blogによりますと...
Like HTTPS, DNS over TLS uses the TLS protocol to establish a secure channel to the server. Once the secure channel is established, DNS queries and responses can't be read or modified by anyone else who might be monitoring the connection. (The secure channel only applies to DNS, so it can't protect users from other kinds of security and privacy violations.)
要するに、DNSの問い合わせを安全にしようってことらしいです。
「DNSってなーに?」
DNSとは、電話でいうところの104番です。104をダイヤルして「東京特許許可局の電話番号を教えてください。」と言えば「xxxx-xx-xxxxです。」と教えてくれるでしょう。
同様にDNSではドメイン名のIPアドレスを教えてくれます。 ドメイン名とは「qiita.com」のような人間が理解しやすい住所のこと。 対してIPアドレスは「123.456.789.xxx」というような機械が理解しやすい住所です。
例えば、「example.com」というWebサイトにアクセスしようとした場合、サーバーに到達するために必要なのは「123.456.789.xxx」というIPアドレスになりますから「example.com => 123.456.789.xxx」という変換をしなくてはなりません。 この変換を担うのがDNSというわけです。
今日、IPアドレスを直打ちするという機会はほぼありませんので、DNSは全ての通信の起点といっても過言ではない重要なシステムです。
DNSが策定された1980年当時、インターネットは今より小規模で単純だったのでDNSに機密性等は求められていなかったのですが、近年の著しい発達に伴い安心安全なプロトコルが必要になったため偉い人がRFC 7858で策定したのがDNS over TLS
(以下DoT
)で、そのDoT
を適用してDNSの問い合わせを行うのがプライベートDNS
の機能です。
DNSの危険性
DNSを保護することはプライバシー・セキュリティの両面から重要です。 DNSを監視していれば、その人がどんなサイトにアクセスしているのかが分かりますし、偽のIPアドレスを教えれば偽のサイトに誘導することも可能です DNSパケットの監視や偽の応答は比較的簡単に実行できますから、公衆無線LANなどで安全性が侵害されるハードルはとても低いです。絶対にしませんし、してはいけませんが、私が(誰でも)Macbookを持ってスタバに行けば、スタバのフリーWi-Fiに接続している人達の接続先ドメイン名を「専門的知識がなくても」監視することができ、それはすなわち、誰でも容易に監視されうることを意味します。 害は無いですが、「漫画村」や児童ポルノに対するフィルタリングもDNSの問い合わせに対して偽のIPアドレスを返すことで行われています。 このように、十分に悪用される可能性があるのできちんと対策する必要があります。
DNS over TLS
DoT
の仕組みはHTTPS
と似たような感じとなっており、DNSサーバーとクライアント間で確立したセキュアなチャンネルを用いてDNSの通信を行い、第三者が閲覧・改竄できないようにしています。
読んで字のごとく、TLS
というセキュアなトンネルを通るDNS
通信というわけです。
実際にどのような通信をしているかは、以下の検証を見てください。
詳しく知りたい方はJPNICさんで公開されている資料「DoH/DoT入門」が分かり易いのでおすすめです。
実際の通信を見てみよう
DNSがどのようにやり取りされているのかWiresharkというパケット監視ソフトで調査してみました。
Android
のパケット監視方法は色々あるようですが、今回は手軽に以下のような構成で通信を監視しました。
こうやってパケットを監視していると、公衆Wi-Fiなどが如何に危険かが身に沁みます。
一般人でも超手軽にパケットをのぞき見できるわけですから、平文通信なんて以ての外ですね。
未だにHTTP
しか対応していない企業HPなども見かけますが、早急に対応してほしいものです。
無知なユーザー(決して貶める意ではありません)を脅威から保護するために最善の努力を行うのは、私たちホスト側の責務だと思います。
今回は調査目的で自分の通信を覗いていますが、くれぐれも他人の通信を覗いたり悪用することのないようにお願いします。
プライベートDNSが無効
のとき
PCなどのDNSクエリストリームも同様の動作となっていると思います。
スマホ(192.168.137.149
)からGoogle Public DNS(8.8.8.8
)にquery
が投げられ、Google Public DNSからスマホにquery response
としてIPアドレス(黒塗り部分)が返ってきています。
どのサイトにアクセスしようとしたのかが、第三者からでも見えることが確認できます。
- クエリとレスポンスが平文でやり取りされており、第三者から丸見え
- 一回の問い合わせで発生する通信は上りと下りの一往復
問い合わせ(query
)と応答(response
)で一セットになる標準的なDNSのやり取りで、秘匿はされますがDoT
でも同様の通信が行われます。
Google Public DNS
をPCのDNSサーバーに設定しているので8.8.8.8
に問い合わせていますが、環境によってはISPのDNSサーバー等に投げていると思います。
DNSはスピード重視ですのでプロトコルにはUDP
が用いられています。
ステートレスなプロトコルですのでハンドシェイクなどは行われず、シンプルな通信が可能です。
仮にどこかでパケットが消えても再問合せすれば良いだけですので合理的だと思いますが、パケットが丸見えですので安全性もへったくれもありません。
特に無線通信ではプライバシーが侵害されたり、改竄されたりする可能性が高まります。
ちなみに、これらのDNSに関する通信の標準ポートは53
です。
dns.google
を設定したとき
Google Public DNS
でAndroid 9
以降向けに紹介されている方法です。
TSL
という暗号化方式を利用するにあたって、まずハンドシェイクという手順が行われます。
ハンドシェイク
パケットに付したコメントはさほど正確でないのであくまでイメージだと思ってください。
まず、プライベートDNS
に入力できるのはホスト名のみなので、dns.google
を解決する必要があります。
もともとGoogle Public DNS (8.8.8.8)
がDNSサーバーなので分かりにくいですが、グレー部分より上の8.8.8.8
はネットワークに設定されていたDNSサーバーで、下はスマホに設定されたdns.google
を解決した結果のDNSサーバーです。
この部分はセキュアではない、伝統的なDNSのやり取りです。
dns.google
が解決されたらTLS
のハンドシェイクが始まります。
詳しい説明は省きますが、DNSサーバーとクライアントの間で公開鍵や乱数をやり取りして共通鍵を作成し、以後はその共通鍵を用いて暗号化を行い通信します。
TCPとTLSに関する疑問点
`TCP`や`TLS`にそれほど詳しくないのですが、`TCP`は`3way ハンドシェイク`といって3回パケットをやり取りしなければ始まりません。 また、`TLS`は基本的に`Client Hello`というパケットが始まりの合図で、それは`TCP`の接続が確立した後に行われるはずです。 ここでは`3way ハンドシェイク`と`Client Hello`が同時に行われているように見えますが実際どうなっているのでしょうか。 他の場所では`3way ハンドシェイク`と`Client Hello`が分かれていたりと様々でした。 詳しい方がいましたらご教授下さい。DNSクエリストリーム
ハンドシェイクの後は以下のような通信が行われます。
通信内容は暗号化されているので付したコメントは想定ですが、仕組み上これで正しいと思われます。
通信の内容がTLSv1.2
で暗号化されているため、内容はApplication Data
と表示されています。
これで第三者はこれらの通信を傍受しても内容を確認することはできず、それぞれのパケットはハンドシェイク時の相手から送られてきていることが証明されていますので、一定の信頼性と機密性が保証されています。
問い合わせ(クエリ)と応答(レスポンス)がペアで行われている基本的な点は伝統的なDNSと変わりませんが、使用しているプロトコルが投げ捨てのUDP
から、確認付きのTCP
に代わったためACKパケット
が増えています。
このACKパケット
は必ず送られるものでもなく、効率化のためにバッファ分をまとめて送信することになっているので若干不規則な並びになっています。
TCP Keep-Alive
というパケットが目を引きますが、これはTCP
は一度接続が切れると再びハンドシェイクからやり直さなくてはならないため、一定期間通信が行われなかった時に切断されないよう送られるパケットです。
- 通信開始時にハンドシェイクという手続きが必要
- クエリとレスポンスが暗号化されており、第三者が確認できない
- 通信は、一回の問い合わせで発生する上りと下り +
TCP
のパケット
伝統的なDNSに比べて複雑になっているものの、TCP
やTLS
といった下層プロトコルに伝統的なDNSを載せているだけなので理解はし易いです。
一度ハンドシェイクが済んでしまえば、レイテンシーもそこまで増大せず安全に利用できるよくできた実装だと思います。
弱点
すこし話はずれますがDoT
の弱点にも触れておきたいと思います。
あたりまえですが、DoT
で保護されるのはDNSの通信のみで他の通信は暗号化されませんのでHTTP
なんかで接続すれば内容は丸見えになってしまいます。
加えて、DoT
が保証するのはクライアント⇔DNSサーバー間の信頼性と機密性のみです。
こちらが詳しいですが、接続先のDNSサーバー自体が不正な場合などの安全性や、ホップ先の機密性は担保されていません。
DoT
はHTTPS
と同様にデジタル証明書で管理されますが、デジタル証明書は偽でないことを証明するだけで接続先が安全であるか否かは関知しません。
利便性の面では、通信環境の悪いところなどではTCP
のコネクションが頻繁に切断され、ハンドシェイクが大量に行われ、それもなかなか上手くいかず…という感じでIPアドレスが取得できず接続エラーになってしまうことがあります。
自分も登山中に経験したことがあり、プライベートDNS
を無効
にすることで普通に接続できるようになりました。
また、個々の負荷増大は軽微でもDNSサーバーにとっては大きな負荷になるのかと思います。
基本的にACK
でパケットが1.5倍ですからネットワークトラフィックも増大しますし、暗号化と復号化の処理も負荷になりそうです。
それでも(無料で)安定したPublic DNS
を提供して下さっているのですから、関係各社様には頭が上がりません。
DoT
で保護されるのはDNSサーバーとクライアント間の通信のみであることは前述のとおりですが、ハンドシェイク前のホスト名解決が伝統的なDNSである点が気になりました。
dns.google
に対して偽のIPアドレスを解決すれば以後の通信が不正になるのではと思いましたが問題ないのでしょうか?
とはいえ、なりすましやスコープ外の危険性はDoT
に固有のものではありませんので、導入を否定する要因にはなりません。
いたちごっこなのはセキュリティの性ですが、適用しておくべきプロトコルだと思います。
自動を設定したとき
Google Public DNSによると、自動
に設定した場合は、まず853
ポートへの接続を試行し、成功したらDoT
で、失敗したら53
ポートへ伝統的なDNSで問い合わせを行うようです。
当方の環境ではdns.google
を明示した時と同じでした。
DNSサーバーが既定のままだったり、コネクションがうまくいかなかったりすると伝統的なDNSで問い合わせが行われると思われます。
一度、自動
に切り替えた後TCP
の接続に失敗して伝統的なDNSでやり取りしていた時がありました。
手動で再接続したらDoT
に切り替わりましたが、どうやらDoT
に執着するよりも接続性を優先する実装のようです。
one.one.one.one
を明示した時
自称最速DNSサーバー、Cloudflareの1.1.1.1
です。
前述の通り設定できるのはホスト名のみなのでone.one.one.one
と設定します。
こちらもDoT
で秘匿された通信ができています。
OpenDNS
を明示した場合
国内にサーバーがあり優秀な部類に入ると思われるOpenDNS
ですが、DoT
には対応してなさそうです。
ホスト名をnslookup
で検索してプライベートDNS
に明示してみましたが、853
ポートへアクセスできませんでした。
パケットを監視しているとエラーのパケットが返ってきているのが見えますが、スマホからはIPアドレスが取得できない状態(=通信不可)が見えるだけです。
対応していない(または存在していない)ホスト名を打ち込むと通信ができなくなるのでよく確認する必要がありますね。
おまけ(Windows)
WindowsではDNS over HTTPS
(以下DoH
)という技術でDNS通信を暗号化しようとしています。
これはHTTPS
の443
ポートを用いてDNSを行うもので、UDPパケット
とTCPパケット
の両方が用いられます。
2020年9月10日時点ではOSレベルの標準実装は行われていませんが、ChromeなどのブラウザはDoH
でDNSの問い合わせを行っています。
このように伝統的なDNSの問い合わせとDoH
が混在していて、ブラウザから投げられるDoH
はUDPプロトコル
を利用しています。
DoH
でもホスト名解決から始まるのは変わらないんですね。
ちなみにWindows insider Program (Dev Channel)
に登録していてBuild 19628
以降がインストールされていれば、レジストリを弄ることでOSレベルでもDoH
を適用することができます。
基本的に全ての通信がDoH
で行われているのが確認できます。
nslookup
はDNSサーバーを明示している扱いなのでDoH
の適用から外れているのだと思われます。
ブラウザレベルでの実装と違ってTCP
とTLSv1.2
が用いられているのが面白いですね。
Dev Channel
はだいぶ不安定になりますが気になる方は是非自己責任でどうぞ。
設定方法は公式ブログを参照してください。
Windows 11
Windows 11ではすべてのチャネル利用者にDoH
の機能が提供されています。
簡単にDNS通信を暗号化できるので是非皆様ご利用ください。
まずは以下のページに移動してください。
設定
->ネットワークとインターネット
->Wi-Fi
->ハードウェアのプロパティ
次に、DNSサーバーの割り当て
という項目がありますので、選択して手動
に変更します。
IPv4
とIPv6
をそれぞれオン
にして、優先DNS
と代替DNS
を設定します。
例としてGoogle Public DNS
を利用します。
IPv4
には8.8.8.8
と8.8.4.4
を入力したら、優先DNS暗号化
と代替DNS暗号化
を暗号化のみ(HTTPS経由のDNS)
に変更します。
IPv6
の方は、2001:4860:4860::8888
と2001:4860:4860::8844
を設定し同様に暗号化の設定を行います。
保存してDNSサーバー
に(暗号化されています)
と表示されれば完了です。
全てのWi-Fi
接続に適用されます。
所感
悪意ある第三者は虎視眈々と我々の通信を狙っています。
コロナ禍で社内だけだったビジネス関係の通信環境も多種多様になったことと思いますが、セキュリティ対策まで手が回りにくいのも実情かと思います。
Wi-Fiやファイアウォール、VPNなど、セキュリティは多角的にアプローチする必要がありますが、全ての通信の起点といっても過言ではないDNSを意識することはあまりありませんでした。
手軽に、どこでも使えるスマートフォンだからこそ、少しでも安全な通信ができるよう適用しておきたい「プライベートDNS」、皆様もこの機会に是非設定してみてはいかがでしょうか。