去年の暮れからのpublic DNS界隈の盛りあがりに合わせて社内キャッシュサーバまわりを確認してみます。まずはECSをみてみました。DNS over TLSは後半に実際にUnboundで設定してみました。
8.8.8.8といえば元祖(2009年)サルでも覚えられるIPv4アドレスですが、2014年より昔にresolv.confに書いたまま放置してる方でECSに気付いていない方はいませんか。
業者が設定していったPCに勝手に8.8.8.8と書いてあるとかいうのはNAPTで全通しの個人事業中小企業さんとかで見たことありますが… Google Public DNSはRRSIGを渡してくれてAAAAフィルタもされないという点においてISPのキャッシュサーバより利用価値がありました。その後Google Public DNSのバックエンドの構成とCDNの相性の悪さを解消するためにClient Subnet(EDNS Client Subnet, ECS)なるオプションが策定され、Google Public DNSに問い合わせると、権威サーバへの問い合わせに実際についてくるようになったそうです。CDN側も続々ECSに対応したようです。ホップ数がクリティカルなCDNなら元々PoP増やしやたりpeeringしたり、ホスト名が変わるのが困らない場合は安上がりに経路が短くなりそうなノードにリダイレクトして誘導するなどなどロードバランスとも合わせて様々な手法がとられていることと思いますが、スピード至上主義ではとにかく名前を問い合わせした人を教える、以上、となるようです。そのまま接続に行くのだから何が困るの?名前解決で必ず接続に行く場合は原則としてそうですが、その場合でもECSが無ければ名前解決ログと接続ログの関連は時間やASで紐づく程度です。プロキシやVPN使っている場合では公開キャッシュサーバ使っているから安心と思っていても実はECSがX-Forwarded-For的な役割を果たしているというケースもあるんじゃないでしょうか。ECSとは直接関係しないものもありますがDNS Privacy – The Problemなどもご参照ください。パケット飛んだ場合の警告リストの更新などで、接続のためではなく定期的に逆引き表引きを問い合わせているような場合、権威サーバ側はECSに応じて悪意を持ってアドレスを返すように設定することがよりピンポイントで可能になるので、任意の複数リゾルバを指定できるプログラムを利用したり、別途キャッシュサーバを用途に応じて複数運用したりする必要があります。世の常ですが一概に良い悪いとは言い切れません。
権威サーバは大分前に自営ではなくなってしまっているので手元に具体的な歴史はありませんが、しょっちゅうポートスキャンされるドメインの権威サーバを一時的に自営のテストサーバに向けると、次のようなログが残ります。公開していない、さっきアプリに投入しただけのドメインに対するANYでの時間差queryなんかもへーというような国からくるのがわかります。AWSでGoogle Public DNSを使うというパターンが多いですがなんかのテンプレートでしょうか。
1 2 |
client 172.217.47.12#48719 (example.com): view ext_known_google: query: example.com IN A -E(0)DC [ECS 13.250.29.0/24/0] client 173.194.171.8#45364 (example.com): view ext_known_google: query: example.com IN A -E(0)DC [ECS 2001:db8:392:500::/56/0] |
数箇所から試しただけですがこちらに届くのはIPv4ならば/24、IPv6ならば/56です。このcidrlenが大きいのか小さいのかも一概には言えませんが、とにかくそれを、ここではexample.comの権威サーバに渡してくれます。
端末203.0.113.123
=> 8.8.8.8 Googleのanycast frontend
=> Googleのbackend
= 「203.0.113.0/24さんから」問い合わせ => 権威サーバ
現在一般的なECSを付けないISPのキャッシュサーバの場合
端末203.0.113.123
=> ISP/VNEのフォワーダ
=> ISP/VNEほか契約されたbackend(多くの場合日本)
= 問い合わせっす => 権威サーバ
というように、そのキャッシュサーバを使うように指示されている人はみな似たようなqueryになります。
なおGoogle Public DNSにECSを付けて問い合わせしても、こちらでいくつか試したケースでは全て無視されて問い合わせ元のアドレスに差し替えられました(追記あり)。パケットキャプチャしてないので送ったときにそもそも送り方を間違えているのかもしれませんし、昔はそのまま送っていたとか良く知りませんが興味がある方は詳細にテストしてみてください。
(2019-06-28追記) すぐに試せるサブドメインだけですが渡したECSがそのまま(IPv4で/24を超える場合は最大/24に切り詰め、IPv6は/56に切り詰め。各種の特殊なアドレスはECS無しに。(2020-01-19追記 この挙動は変更予定の模様です。))権威サーバに届くことを確認しました。/0を渡した場合はECSが付きませんでした。こちらが正しく送れるようになったのかキャッシュサーバ側が変わったのか、特定の条件でそうなるのかはわからないので、ぜひ皆さんも試してみてください。サーバ証明書と同じく定期観察してれば面白かったかもです。今のところこの件を知っている人、かつECSのアドレスサイズを構成できるという限られた人向けの機能なのでクライアントのリゾルバ含めて一般的な設定値になると良いかと思います。HTTPのDNTと同じような扱い(キャッシュサーバがECSを知らない場合は権威サーバに伝わらないだけなのでよいですが、ECS付けて送っても単に無視されちゃうかもという意味で)になるとはいえ。
ここまで適当ないまさらECS情報ですが、ユーザとしては誰がその名前解決を要求したかを知ることができる場所が増えていることに気をつけておけばよいと思います。なんでISPのキャッシュサーバ使ってないんだっけとか一度思い出してみるのも良いかもしれません。覚えられる数字だからなのか、オンラインゲームなのか映像配信なのか、果ては世の中の無駄なトラフィックを減らしたいのか、スピードで統計とったとしてもそこまで本当に必要なのかとか、国内法で守られないデメリットとか、トレードオフは何なのかとか。なんかx.x.x.xにすると早くてセキュリティ的にも良くなるというとかいうあちこちにある記事を見たから使っているだけという人はBGP hijackとか検索してみると良いかもしれません。何使っていようがフィルタがあろうがダメな時はダメというくらいインターネットは脆弱です。わけの分からない業者によく用途もわかっていないCA証明書インストールさせちゃだめとか、証明書のエラーを無視して続行しちゃいけないという当たり前の話の方がよほど重要です。それでも秘密鍵盗まれたり漏洩したり間違えて公開しちゃったのに気付いていないとかあって万全ではないくらいです。
参考
- EDNS-client-subnetってどうよ? 改めRFC7871ってどうよ
- EDNS Client Subnet (ECS) Guidelines | Google Public DNS
- BIND 9 Security Configurations
- The privacy risk of edns-subnet-client (ECS) or why using a public DNS server might not improve your privacy.
- お漏らしテスト
- お漏らしテスト
- お漏らしテスト(おまけ)
他のPublic DNSも見てみます。8.8.8.8 = 9.9.9.9 – 1.1.1.1 でサル🐵3強でしょうか。(なんかCloudflareの逆引きが one.one.one.one ワン ワン ワン 🐕 になりました。そのうちDoTの証明書のSANにも追加されるでしょうか。)プロトコル別のWikipediaの表で見てみます。
DNS over TLS RFC7858(+RFC8310)
https://en.wikipedia.org/wiki/DNS_over_TLS
DNS over HTTPS RFC8484
https://en.wikipedia.org/wiki/DNS_over_HTTPS
DoHは専用のリゾルバライブラリを使うか、今は亡きDNSCrypt-Proxyに代わってDNSCrypt-Proxy2で実際に動作します。前者のDoTですが、良いニュースがありました。ほげさんが発見しほげほげさんにわれわれが伝えて調整してうんぬんで頻繁に登場する証明書検証の不備ですが、長い年月を経てついに Unbound 1.7.1でOpenSSL 1.1系を使えば証明書を検証するようになりました。
(2019-06-28追記) 1.8.1よりOpenSSL 1.0.2でも検証するようになっています。あれ、SAN見てなかったの?
pinによる検証ではないので、設定の持続性も高いです。DoHやDNSCryptと違って現状でも動作中のUnbound単体の設定だけですむので、一気にDoTに気が傾きます。
DNS Privacy Public Resolvers
DNS Privacy Test Servers
いろいろなポリシーの公開サーバがありますが各社のポリシーはよく読んで、ほかに提供しているサービスとの関連、例えばCloudflareはDDoS対策のリバースプロキシサービスのミニマム版(とはいえ十分な機能)を無料で提供して大きくなった会社なので、ログは1時間で捨てるのを守ったとしても、サービスされているwebサーバの名前を引いたホストとアクセスを紐づけて利用するのは即可能とか、アメリカといえばとかそういう想像も、ひねくれてると思われちゃうとか気にせずにしておいた方が無難かもしれません。ここではログは気にせず他の部分で見ると、ほとんどはフィルタの話になります。フィルタされて一番困るのは、前述しましたが自前のリストに載っているドメインもブロックされている場合が多々あって、警告用のIPリストが作成できないということになります。フィルタがあるキャッシュサーバは個々のモバイル端末で使うとか、家でルータに設定してフィッシングにかからないとかが一番の使い道でしょうか。ここでの用途には不向きなので除外します。なにかと微妙なのがQuad9で
9.9.9.9, 149.112.112.112, 2620:fe::fe
Provides: Security blocklist, DNSSEC, No EDNS Client-Subnet sent.
9.9.9.10, 149.112.112.10, 2620:fe::10
Provides: No security blocklist, DNSSEC, sends EDNS Client-Subnet.
(2019-06-28追記) ご参照頂きました通り、ECS送らないという記述に変わっていました。2620:fe::9が増えてますね。この記述もあるので必要な方は常に最新の情報を追いかけた方がよさそうです。
となり、フィルタ無しだとECSを送るそうです。そういえば去年もここを見てわざわざ使わないかなと思ったのでした。しかしながら今も実験してみましたが、権威サーバで見ていてもECS付いてきません。詳細はドキュメンテーションが見つからないので分かりませんがOpenDNSのようにECS送付先のホワイトリストがあるかもしれません。レスポンスが気持ち遅いでしょうか。いずれにせよECS送るといってるのでCDNへのホップ数がとても重要という場合には使えるのかもしれません。いずれ仕様が出てきたら読んでみてください。
実験環境で実際に使っているUnboundを使い、その前にいるDNSCrypt-Proxy2をさくっと消してから(消さんでもいいですが)設定していきます。せっかくなのでDNS over TLSキャッシュサーバ(フォワーダ)にもしてしまいます。
1 2 3 4 5 6 7 8 9 10 11 12 |
server: # DNSSEC auto-trust-anchor-file: "/root-auto.key" # DNS over TLS server(forwarder) interface: 0.0.0.0@853 interface: ::@853 tls-port: 853 tls-service-key: /xxx/letsencrypt/live/example.com/privkey.pem tls-service-pem: /xxx/letsencrypt/live/example.com/fullchain_param.pem # DNS over TLS server(forwarder)/client(resolver) # MPL20 tls-cert-bundle: /usr/local/share/certs/ca-root-nss.crt |
このサーバを利用する場合は、ここで指定したサーバ証明書のCNか、SANどちらかで検証可能な通常FQDNで証明書検証をするように指定します。Cloudfalreのドキュメントに書いてある通りKnot DNSのkdigを-dで使えば簡単に確認できます。
1 |
kdig -d -p 853 @127.1 +tls-host=wairudo.example.com +tls-ca +dnssec www.freebsd.org |
リゾルバを設定していきます。いきなりのおまけですがECSを送って遊びたい方は次のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
server: module-config: "subnetcache validator iterator" client-subnet-always-forward: no max-client-subnet-ipv6: 32 max-client-subnet-ipv4: 16 # check whether servers ignore/overwrite ECS we send send-client-subnet: 8.8.8.8 send-client-subnet: 8.8.4.4 send-client-subnet: 2001:4860:4860::8888 send-client-subnet: 2001:4860:4860::8844 send-client-subnet: 9.9.9.10 send-client-subnet: 149.112.112.10 send-client-subnet: 2620:fe::10 #exclusive client-subnet-zone: . |
kdigや新しいdigならばpatch不要でこんな感じです。
1 2 3 4 |
dig @権威サーバ +norecurse +subnet=13.250.29.0/24 CDNとかクラウドとか kdig @権威サーバ +norecurse +subnet=13.250.29.0/24 CDNとかクラウドとか dig @キャッシュサーバ +subnet=13.250.29.0/24 CDNとかクラウドとか kdig @キャッシュサーバ +subnet=13.250.29.0/24 CDNとかクラウドとか |
本題です。
1 2 3 4 5 6 7 |
forward-zone: name: "." forward-tls-upstream: yes forward-addr: 2606:4700:4700::1111@853#cloudflare-dns.com forward-addr: 2606:4700:4700::1001@853#cloudflare-dns.com # NG NG NG forward-host: 1dot1dot1dot1.cloudflare-dns.com@853#cloudflare-dns.com NG NG NG # NG NG NG forward-host: one.one.one.one@853#cloudflare-dns.com NG NG NG |
はいおしまい。簡単ですね。とはならないようでございます。体感で分かるくらい名前解決がのろくなります。キャッシュされてる場合が多いホスト名ならば良いですが、そうでないほとんどの場合涙目になります。普通クラスですがメモリも大量に積んだサーバでございます。接続時のネゴの時間だそうなのでコネクションプールなどの今後に期待です。ここで証明書の検証を外してしまうとMITMの干渉を防げないので、そういう中途半端な設定をするくらいならば素のDNSで十分です。
実験環境では何の問題もないのでこのまま使うことにします。ただし逆引きは53/udp,tcp かつDNSSEC無効にしておきます。
1 2 3 4 5 6 |
server: domain-insecure: "arpa" forward-zone: name: "arpa" forward-addr: 2606:4700:4700::1111 forward-addr: 2606:4700:4700::1001 |
ところでここで利用させていただいたCloudflareのanycast public DNSですが、強力なセンター数ノード数をお持ちのCloudflareなので、日本にも当然のように多数のノードがあって実際にフロントエンド、そしてGoogle Public DNSと異なりバックエンドとしても使われていて(フロントエンドはtraceroute、バックエンドは上のリストのdnsleaktest.comなどを使うと分かりやすいです)、フロントエンド寄りのキャッシュも分離されているようなので、日本からの利用の場合権威サーバには日本からの問い合わせがほとんどになるはずです。ECSほど狭くないのでISP別国内地域別とかでは厳しいでしょうからpeeringの効果が少なくなるもしれませんが、そこまで調整しているような規模のサービスはそんなに多くない(サービス数は利用者数ではないので暴論です)でしょうから、むちゃくちゃ困る人はオンラインゲームにいるかいないかくらいかと想像されます。実際の利用者がいらっしゃったらどんなもんか教えてもらってください。
CDN用にISPのキャッシュサーバを使い、名前解決部分は自分とフォワーダまでの間で覗かれるのはいやだけどDNSSECは不要、後はロンドン支店のキャッシュサーバに問い合わせてRRSIGでvalidationしてよねとかいう謎環境の場合は、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
forward-zone: name: "cdn.example.com" forward-addr: ISPのキャッシュサーバ forward-addr: ISPのキャッシュサーバ server: domain-insecure: "dokomitenno.example.com" forward-zone: name: "dokomitenno.example.com" forward-tls-upstream: yes forward-addr: DNS over TLS server@853#CN-or-SAN forward-addr: DNS over TLS server@853#CN-or-SAN forward-zone: name: "." forward-addr: 10.1.1.1 # ロンドン支店 forward-addr: 10.1.1.2 # ロンドン支店 |
こんな感じでしょうか。
せっかくなので上のDNS Privacy Test Serversに掲載されているテストサーバでもテストさせていただきました。結果、証明書が期限切れで失効しているサーバがありました。Stubbyをpinで設定している人が多数派?表のFQDNがCNにもSANにも無いサーバもあるので、やはりpin設定の方が多数なのかもしれません。他にRRSIGを渡してくれないサーバもありました。こちらのテスト権威サーバに向かってECSをつけるサーバやNXDOMAINに自前のサーバを返すところはこの時点ではありませんでした。
結局実験環境以外はISPのキャッシュサーバ利用のまま変わらずということで終わりました。AAAAフィルタがなくなってRRSIG付けてくれるようになってISPのキャッシュサーバ利用に戻ったのもついこの間な気がしますがようやくインターネットの根幹のDNSがQNAME minimizationなども含めて具体的に変化しているということで、また何かの機会に見直すのは良さそうだと思いました。今回だけでもISPがDNS over TLSを実装してもDNS Privacy – The Problemは解決しないよなとか、でも日本ならば今ちょうど別方面で話題のようですが通信の秘密があるからISPがさっさと提供してくれた方が良いかなとか、いろいろ思いを馳せさせてくれました。DoTやDoH、主要な実装がそろったら一気に主流になりそうなDNS over DTLSの行方も楽しみです。
あとこういうの
End to Bandaids for Broken EDNS, dnsflagday
も結構好きです。拡張性もシンプルが良いですね。