280blockerの暗号化DNSの詳細

最近公開した暗号化DNSサーバ(DoH)の運営や技術的な話です。
暗号化DNSサーバーはiOSの280blockerアプリ利用者だけに公開しています。最新版アプリの高度な設定から利用が可能でsafari以外の広告もブロックできます。サービスを利用するだけなら特に知らなくても良い話です。

DNSサーバ

DNSサーバーは端末から問い合わせのあったサイトのドメイン名をipアドレスへ変換して応答する作業をしています。端末はその情報を利用して、閲覧したいサイトのIPアドレス宛にデータを要求します。
DNSサーバーがドメインの問い合わせに対してそのサーバーは存在しない(NXDOMAIN)という応答にすると、端末はデータが要求できなくなり、そのドメインとの通信をブロックできます。これがDNSサーバを利用した広告ブロックです。
ちなみにDNSサーバへの問い合わせの中で、広告系ドメインの問い合わせの割合はざっくりと1割程度です。

暗号化DNS1(9/24)

当初作成した暗号化DNS1は端末からのすべてのドメイン問い合わせへの応答を行い、広告系にはNXDOMAINを応答する仕様でした。
この設定ではDNSサーバーにかかる負荷は大きく、またアメリカにサーバーを置いたこともあってかなり遅かったと思います。暗号化DNS2も同じ仕組みでした。
DNSサーバー側にはユーザーのアクセスするドメイン情報がすべて流れてきますので、プライバシー的にもよくないなあと思っていました。プライベートで使っていて知られたくないドメイン名もあるでしょうし。

暗号化DNS3・4(9/26)

iOS14のプロファイルで、特定のドメインのみ暗号化DNSを利用する設定ができる事が分かったりました。それを利用して広告系ドメインのみ暗号化DNSへ問い合わせるようにしたのが暗号化DNS3と暗号化DNS4です。
この変更でサーバー負荷がDNSサーバー1より低くなりました。プライバシー的に問題が減ったと考えてたのでユーザへお知らせをすることにしました。
告知によるユーザ数の増加は想像していましたが、9/29にアプリの通知機能を使ってユーザーの全端末に通知をした直後から急激に負荷が上昇しました。告知前の負荷がほぼ0に見えてしまうほどです。サーバーにはまだまだ余裕がありましたがこの勢いで増えていくと、いつまで耐えられる分からないため次の対策を始めました。

ロードバランサーの導入(9/30)

かなり試行錯誤して9/30に導入したのがロードバランサとなります。ロードバランサは、その裏で動作しているサーバーへ通信を振り分ける役割を果たします。
動作が停止しているDNSサーバーには通信が振り分けられない仕組みになっているため、動作するDNSサーバが1台でもあればサービスを継続できます。

もしも1台の暗号化DNSサーバーがエラーになったりメンテナンスで停止をしても、他の暗号化DNSサーバーが動作していればサービスは継続されるので安定した運営が可能です。
またロードバランサの裏に2台の暗号化DNSサーバーを置いていますので1台あたりの負荷はこれまでの半分になりました。
ロードバランサー自体はシンプルな動作のため、ロードバランサー自体がエラーになる事は少ないと思っています。それでも念のためユーザが切り替えらえるように2台のロードバランサ(DNS3とDNS4)を用意しました。

構成の変更(10/1)

9/30までは2つのロードバランサーの裏にそれぞれ2台のサーバーの構成でした。
10/1にロードバランサー2台とDNSサーバー4台をすべて組み合わせた構成に変更しました。これによりDNSサーバーが1台止まっても残り3台で支えられますのでトラブル時に負荷が上がりにくいと考えられます。
デメリットとして、これまで独立していたDNS3とDNS4に関係性が出てしまったので同時にすべてがダウンするリスクが高まったと考えています。

最後に

DoHならHTTPS通信なのでロードバランサーというものが使えはずと思ったのはいいけれども、初めて使用するためよくわからず、最初はエラーで動作しませんでした。DoHサーバーでのロードバランサの使用は情報もなく、何度も作りなおしてやっと安定的に動くようになりました。
障害検知には多少不安が残っています。ロードバランサがDoHサーバーの稼働状況をチェックして、エラーのサーバーには通信を振り分けないという機能です。試行錯誤した結果httpsでの稼働チェックはあきらめて、TCP port 443の稼働チェックとしています。

iOSで暗号化DNSのプロファイルを利用した広告ブロックは、他の広告ブロック(端末内のVPNプロファイルを利用した方法など)より安定してブロックしてくれるように思うので私自身も現在はこれを使用しています。現在のところブロックの甘さもそれほど気にならず、電力消費もほぼ0なので気に入って使っています。広告系ドメインの問い合わせの結果を3600秒、端末内でキャッシュするような応答をしていますので使用する事でむしろ電力消費は減るかもしれません。

継続的にそれなりにコストがかかる構成にはなってしまいましたが、この構成でしばらくはサービスを続けたいと思っています。このサーバーを使用する280blockerアプリユーザがさらに激増して、サーバー負荷が限界になるようならそれぞれのサーバーをよりスペックの良いもので契約しなおす予定です。いまのところ280blockerアプリから送っていただいたチップで十分コストはまかなえています。送っていただいてありがとうございました。


追記)NXDOMAINでの応答は一部の端末で想定外の無駄な通信が発生するようですので、検証してNull IPへ変更予定です。サーバー側の変更なのでユーザには特に何も変わりません。
参考)Consider using "REFUSED" or "Null IP" instead of NXDOMAIN by default · Issue #1914 · AdguardTeam/AdGuardHome · GitHub