はじめに
Webサイトには数々の広告が表示されます。そのため、本当に利用者が必要な情報だけではなく、広告サイトへの通信も発生してしまい、その分、時間やリソースを消費してしまいます。そこで広告サイトへの通信をなくす事により、時間やリソースの節約を図るというのが、この記事の主旨です。色々な方法がありますが、DNSブロッキングで対処する方法について説明します。
なお、元々はこのサイトを読んだのが始めた動機です。
[Internet] Ad DNSブロッキングおよび、kawango DNSブロッキングの実装をしてみたら、超快適だった
https://tomocha.net/diary/?20180818#201808182
DNSキャッシュサーバーのインストール
WebブラウザはDNSキャッシュサーバーに問い合わせてサイトのIPアドレスを取得します。色々な実装がありますが、この記事ではUnboundを使用する事にしました。UnboundはUNIX、UNIX like OSの他、MacやWindowsでも動作します。
Unboundのインストール
この記事ではMacとWindowsでインストールする方法について説明します。
Macの場合
Macではbrewでもunboundを載せる事は可能です。ですが、2018年12月16日現在のバージョンは次の通り、1.8.1で、第一フラグメント便乗攻撃が成功してしまう脆弱性のあるバージョンです。また、後述する理由で現状ではソースに手を入れて作る必要があります。というわけで、ここではソースからビルドしてインストールする方法を記述します。
$ brew info unbound
unbound: stable 1.8.1 (bottled), HEAD
Validating, recursive, caching DNS resolver
https://www.unbound.net
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/unbound.rb
==> Dependencies
Required: libevent ✔, openssl ✔
==> Options
--HEAD
Install HEAD version
==> Caveats
To have launchd start unbound now and restart at startup:
sudo brew services start unbound
==> Analytics
install: 462 (30 days), 1,801 (90 days), 7,328 (365 days)
install_on_request: 242 (30 days), 836 (90 days), 3,124 (365 days)
build_error: 0 (30 days)
$
なお、上記の情報からもわかりますが、unboundのインストールには次のパッケージが必要です。予め、インストールしておきましょう。
- libevent
- openssl
また、第一フラグメント便乗攻撃については次のサイトを御覧下さい。元の論文へのリンクも貼られています。
インターノット崩壊論者の独り言 - DNSSEC は危ない - これを NSEC/NSEC3 Replacement Attack と呼ぶのはどうだろう? <http://www.e-ontap.com/blog/20181031.html>
ソースからビルド
と言うわけで、ソースからビルドする方法を記述します。
ソースの取得
まず次のページからunboundのソースをとって来ます。
Unboundのダウンロードサイト <https://nlnetlabs.nl/projects/unbound/download/>
tarballの展開
次にとって来たtarballを展開します。2018年12月11日時点での最新版は1.8.3ですので、そのバージョンを展開する場合は次の通りになります。
$ tar xvf unbound-1.8.3.tar.gz
unbound-1.8.3 というディレクトリができていることをlsコマンドで確認しましょう。
$ ls -CF
unbound-1.8.3/
unbound-1.8.3 というディレクトリができていたら、ディレクトリに移ります。
$ cd unbound-1.8.3
(2018年12月24日、ここから追記)
第一フラグメント便乗攻撃対策
インターノット崩壊論者の独り言 - DNSSEC は危ない (その2) - Unbound を安全にしよう <http://www.e-ontap.com/blog/20181104.html>
によれば、第一フラグメント便乗攻撃対策を行なうため、最低限、次の設定が必要です。ただし、これで十分かどうかはまだ調査が必要かもしれません。
- DO bit を off (DNSSECを使わない場合)
- validatorモジュールを無効にする
- harden-referral-pathをyesに設定
- EDNSのバッファサイズを512に設定
このうち、現状では2以降の設定については設定ファイルの指定で可能です。それについては後述します。1については設定ファイルで指定ができないので、ソースを変更する必要があります。ここでは、その方法について説明します。
DO bit を off にする(DNSSECを使わない場合)
Unbound 1.8.1 以前では、defaultだとDO bitがonになっており、DNSSEC 署名ドメインとの通信が TCP になる頻度が高くなる可能性があります。ですが、現状では、設定ファイルでこれを変更する手段がありません。ソースにパッチを当てるしか手が無いのが実情です。ということはMacは対応する余地がありますが、Windowsの場合はこの対応が不可能です。
この件について、中京大学の鈴木常彦先生が改善提案をNLnet Labsにしたそうですが、NLnet Labsは頑として、この設定の切り替えを可能にすることには応じなかったそうです。下記が該当箇所です。
$ grep Dnssec ./util/net_help.h
#define EDNS_DO 0x8000 /* Dnssec Ok */
$
そこで、次のコマンドを実行し、DO bit を off にします。
$ sed -i '' -e 's/EDNS_DO 0x8000 \/\* Dnssec Ok \*\//EDNS_DO 0x0000 \/\* Dnssec NO \*\//' ./util/net_help.h
grepコマンドで変更が成功しているかどうかを確認します。
$ grep Dnssec ./util/net_help.h
#define EDNS_DO 0x0000 /* Dnssec NO */
$
(2018年12月24日、ここまで追記)
configure実行
次に configure ファイルを実行して Makefile を作ります。
$ ./configure
Makefile が出来ていたら、makeコマンドを引数なしで実行します。
$ make
ビルドが終了したらインストールします。root権限が必要になるのでsudoコマンドを使ってmakeコマンドを実行します。
$ sudo make install
以上で、unboundのインストールは終了です。
デーモンとしての設定(plistの作成)
デーモンとして起動されるようにするために、/Library/LaunchDaemons/ に plist ファイルを配置します。下記にplistファイルの例を載せますが、これはbrewでインストールした時に付属していたものを改造していることを先にお断りしておきます。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>homebrew.mxcl.unbound</string>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>/usr/local/sbin/unbound</string>
<string>-d</string>
<string>-c</string>
<string>/usr/local/etc/unbound/unbound.conf</string>
</array>
<key>StandardErrorPath</key>
<string>/dev/null</string>
<key>StandardOutPath</key>
<string>/dev/null</string>
</dict>
</plist>
上記の設定を行なうことにより、
$ sudo unbound -d -c /usr/local/etc/unbound/unbound.conf
をマシン起動時に実行してくれます。
Windowsの場合
次のページからunboundのインストーラーをとってきて実行するだけです。32-bit版も64-bit版もバイナリの配置とサービスの設定まで行ってくれます。
Unboundのダウンロードサイト <https://nlnetlabs.nl/projects/unbound/download/>
ただ、バイナリなので第一フラグメント便乗攻撃対策は一部しか行なえません。
Unboundの設定ファイルの修正
Unboundのインストールが終わったら、設定ファイルを修正したり、作成したりします。OSによってパスが変わりますが、作業の内容自体は全て同じです。なお、以下の記述は全てdefaultの場合です。
設定ファイルのパス
Macの場合
Macの場合、次のファイルがUnboundの設定ファイルになります。
- /usr/local/etc/unbound/unbound.conf
Windowsの場合
Windowsの場合、次のファイルがUnboundの設定ファイルになります。
- C:\Program Files\Unbound\blocking.conf
広告サイトのincludeの設定
広告サイトのリストをincludeするように設定します。こうする事によって、広告サイトの設定だけを切り出すことができます。なお、設定ファイルがMacとWindowsで違っているので、必然的にincludeの設定内容が変わります。
Macの場合
Macの場合、設定ファイルに次の内容を書き込みます。
include: "/usr/local/etc/unbound/blocking.conf”
Windowsの場合
Windowsの場合、設定ファイルに次の内容を書き込みます。
include: "C:\Program Files\Unbound\blocking.conf”
(2018年12月24日、ここから修正)
第一フラグメント便乗攻撃対策
インターノット崩壊論者の独り言 - DNSSEC は危ない (その2) - Unbound を安全にしよう <http://www.e-ontap.com/blog/20181104.html>
によれば、第一フラグメント便乗攻撃対策を行なうため、最低限、次の設定が必要です。ただし、これで十分かどうかはまだ調査が必要かもしれません。
- DO bit を off (DNSSECを使わない場合)
- validatorモジュールを無効化
- harden-referral-pathをyesに設定
- EDNSのバッファサイズを512に設定
このうち、1については、Macでは上記の通りに作業を行えば対応可能です。ですが、残念ながらWindowsではバイナリでインストールしているため、現状では対応が不可能です。
ただ現状では2以降の設定については設定ファイルの指定で可能です。ここでは、その方法について説明します。
validatorモジュールを無効化
DLVも含め他のドメインの検証も無効にします。
module-config: "iterator"
harden-referral-pathをyesに設定
DNSSECでゾーンが署名されていたら、応答を検証するため、この設定を行ないます。
harden-referral-path: yes
EDNSのバッファサイズを512に設定
これまた第一フラグメント便乗攻撃対策のため、EDNSのバッファサイズを512バイトに設定します。フラグメントを避けるために 512 バイトを越える応答は TCP にフォールバックさせるためです。
edns-buffer-size: 512
(2018年12月24日、ここまで修正)
ブロックする広告サイトのリストの作成(および修正)
広告サイトのリストの入手
広告サイトのリストを個人的に作成している方がおり、次のサイトからとって来られます。定期的に更新もなさっています。
280blocker <https://280blocker.net/download/>
ただし、このリストには使用制限があります。上記サイトから引用します。
注意事項
・個人用途で使用する場合は基本的に自由に利用ください。
・再配布は個人用途、改変なし、引用元( https://280blocker.net )を明示の3つを満たす場合のみ可です。
・営利目的での使用・再配布は禁止です。アプリへの組み込みも禁止です。
ブロックする設定の書き方
ブロックするサイトについては、上記の設定ファイルで指定したファイルに次の行を付け足していきます。
local-zone: “ブロックするサイト.” static
このように指定する事により、指定したサイトへの問い合わせはローカル データで定義していない問い合わせになるのでunboundはnodataあるいはnxdomainを回答します。つまり、そういうサイトはない、と回答した事になるので、そのサイトへの通信も発生しないというわけです。なお、厳密には、unbound.conf(5)の次の記述に基づいています。
ローカル データに一致したら、クエリーに回答します。一致しないときには、クエリーに対してnodataあるいはnxdomainを回答します。ゾーン頂点ドメインのlocal-dataとして存在するときには、否定回答として回答にSOAが含まれます。
下の図が指定例になります。
# Homepage: https://280blocker.net
# Licence: CC BY-NC-ND 4.0 (https://creativecommons.org/licenses/by-nc-nd/4.0/)
#
# It's created for Japanese user of DNSCloak, AdguardPro(iOS), Adguard Home, or Adhell.
# Subdomain is not described.
# Please use it in a system that can block subdomains.
#
# Lastupdate: 2018-12-12
#
local-zone: "googleadservices.com." static
local-zone: "pagead2.googlesyndication.com." static
local-zone: "exosrv.com." static
local-zone: "omtrdc.net." static
local-zone: "coremetrics.com." static
local-zone: "100651.advision-adnw.jp." static
local-zone: "2.chmato.me." static
設定の反映
設定の反映はサービスを再起動するだけです。
Macの場合
$ sudo pkill -HUP unbound
Windowsの場合
下図のようにUnbound DNS validatorサービスを再起動します。
DNSサーバの動作確認
広告サイトブロックの確認
まず、広告サイトのブロックが成功しているかどうかを確認してみましょう。
例えば、googleadservices.comが引けなくなっていることを確認する場合は次のようにします。
$ dig @localhost googleadservices.com a
; <<>> DiG 9.10.6 <<>> @localhost googleadservices.com a
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 16605
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;googleadservices.com. IN A
;; Query time: 0 msec
;; SERVER: ::1#53(::1)
;; WHEN: Sun Dec 16 19:34:49 JST 2018
;; MSG SIZE rcvd: 49
$
なお、Google Public DNSの場合は次の結果が返ってきます。
$ dig @8.8.8.8 googleadservices.com a
; <<>> DiG 9.10.6 <<>> @8.8.8.8 googleadservices.com a
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37538
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;googleadservices.com. IN A
;; ANSWER SECTION:
googleadservices.com. 299 IN A 172.217.161.66
;; Query time: 52 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sun Dec 16 19:36:59 JST 2018
;; MSG SIZE rcvd: 65
$
第一フラグメント便乗攻撃対策の確認
(2018年12月24日、ここから修正)
現状では、Windowsについては「DO bit」の設定切り替えが事実上不可能なので残念ながら不完全な対応になってしまいますが、対応した設定が反映されているかを確認します。
DNSSECが無効になっている事の確認(Macのみ)
Unbound 1.8.3の場合、DNSSECの無効化はMacでしか行なえません。
その検証をするため、次の2つの処理を行ないます。
- LDNSのインストール(インストールされていない場合)
- DNSSECが無効になっている事の確認
LDNSのインストール
下記の公式サイトによれば、LDNSの現在のバージョンは1.7.0です。
LDNS
https://nlnetlabs.nl/projects/ldns/about/
そして次の通り、brewでの現在のバージョンも1.7.0です。
$ brew info ldns
ldns: stable 1.7.0 (bottled)
DNS library written in C
https://nlnetlabs.nl/projects/ldns/
/usr/local/Cellar/ldns/1.7.0_1 (570 files, 5.6MB) *
Poured from bottle on 2018-10-19 at 05:59:36
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/ldns.rb
==> Dependencies
Build: swig ✘
Required: openssl ✔
==> Analytics
install: 139 (30 days), 520 (90 days), 3,506 (365 days)
install_on_request: 108 (30 days), 390 (90 days), 1,776 (365 days)
build_error: 0 (30 days)
$
よって、LDNSのインストールはbrewでも最新版をインストールできます。
$ brew install ldns
DNSSECが無効になっている事の確認
DNSSECが無効になっているかどうかは drill コマンドで確認できます。
$ drill -D TXT test.dnssec-or-not.net @127.0.0.1
;; ->>HEADER<<- opcode: QUERY, rcode: NXDOMAIN, id: 50856
;; flags: qr rd ra ; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0
;; QUESTION SECTION:
;; test.dnssec-or-not.net. IN TXT
;; ANSWER SECTION:
;; AUTHORITY SECTION:
dnssec-or-not.net. 1808 IN SOA ns.packet-pushers.com. root.packet-pushers.com. 1545066962 3600 300 604800 3600
;; ADDITIONAL SECTION:
;; Query time: 0 msec
;; EDNS: version 0; flags: ; udp: 512
;; SERVER: 127.0.0.1
;; WHEN: Mon Dec 24 22:10:03 2018
;; MSG SIZE rcvd: 113
$
DNSSECが有効になっている場合は次のように署名も出力されます。
$ drill -D TXT test.dnssec-or-not.net @127.0.0.1
;; ->>HEADER<<- opcode: QUERY, rcode: NXDOMAIN, id: 52038
;; flags: qr rd ra ad ; QUERY: 1, ANSWER: 0, AUTHORITY: 8, ADDITIONAL: 0
;; QUESTION SECTION:
;; test.dnssec-or-not.net. IN TXT
;; ANSWER SECTION:
;; AUTHORITY SECTION:
dnssec-or-not.net. 1000 IN SOA ns.packet-pushers.com. root.packet-pushers.com. 1545066962 3600 300 604800 3600
dnssec-or-not.net. 1000 IN RRSIG SOA 8 2 3600 20190116161602 20181217161602 19233 dnssec-or-not.net. qPYc6Sz+Iv6XMuuyj+SkMN+bNlY5qsn5Eje141bBhqkHEulWAsWU3d7cU15kdT8vG5YE//9fsvp1tBbe/+vO7/qHwDpWojL2sIjtJi5fZYwLjRP8sPxGzDvcGvBPPAJPCYOpMjqU1sxRQlxug0Asfq9G9n1XXb1GEzgSuZojm7UhSltjYA2JTyJOWh+pFpJkEPVMWmOX6uJgIuqjU2SJS4Dgjxvl+4ovVu4ZS4cRvuAtttskpIZbLdH5JW7DM4IA/S+lH7f+AyYU/++ssT4FHmOyw58BMT2mBlt8OT7LYjGP/fhTKBp7PIirbtFrTM8+SF36f7m6cu9mvYUiqiyr4w==
JO39JI4L4B8RT0DL1VE1NNSODHGT9IHC.dnssec-or-not.net. 1000 IN NSEC3 1 0 13 0fadedbabe q0q19eso55ngo03e6ivhp2bp6pe6kagq A NS SOA TXT AAAA RRSIG DNSKEY NSEC3PARAM
JO39JI4L4B8RT0DL1VE1NNSODHGT9IHC.dnssec-or-not.net. 1000 IN RRSIG NSEC3 8 3 3600 20190116161602 20181217161602 19233 dnssec-or-not.net. PxK13EhzPLdQ8S+tbirqcC4suFh70H12GuBFOuj/YpBGpNyf1qUZgU9ETWi7n8jMQnpvK77xunWCs/U7dzCxBl67M1V6LDIYYpP/zqWNWIgxPkUbT6XRxeyTarBOFGytGzhld79haTs/7cwla9mevrUn08nczI0Ao5BPwg2JY02WxyQA/ZkSP6WQDVx3Ty0ZdmdVSAoMOvX5LNclJqtdkhspqK8fyWIb6qHYJDo9RzI6EujjNzxNj53C5Mrp99lTbN7wW/pyedSR1fk/z07Q6IRZWokigTzN3zE5xYdqiIclxMw/A+e2BeAkrRb9FE0PiGrpMRDQvsls1FWoKIBXgA==
Q0Q19ESO55NGO03E6IVHP2BP6PE6KAGQ.dnssec-or-not.net. 1000 IN NSEC3 1 0 13 0fadedbabe 2su4en54li5941scrru827esoiij4uak A AAAA RRSIG
Q0Q19ESO55NGO03E6IVHP2BP6PE6KAGQ.dnssec-or-not.net. 1000 IN RRSIG NSEC3 8 3 3600 20190116161602 20181217161602 19233 dnssec-or-not.net. Tv7enDjzxq8AIhWevZjhEUv9S4U1iM+DTnOrQQ066xBtlP6CqoH5zPHlxPI24XJb4lts4x+Y4f3YMlOgdEhtyw4E9EwbkOD2nvPw/PNf8MAWnSh9sQk/iTAvHoMh8mRavQpnPzjpaCj3oxzRXNBhLosVxxvm1PaA08RMkGT9wWcwfAVfjZpGTMOJ+oZop1lpVxhiip6cvin432tbB6i/KxruxzNGHs0xtJ7Dz46otnJ3xWv9JabF09jkxrkdDjRb2jO91G1kOfybftjzoxJgCJqzL9AyXQxj6WAyfuI33GbjFNahMOVGhFWOOTvf9NtHDenCt2WEsU0idHtlDhalVg==
D0UM4ALLIO1D7SND14VCRJA8NT98IEEJ.dnssec-or-not.net. 1000 IN NSEC3 1 0 13 0fadedbabe jo39ji4l4b8rt0dl1ve1nnsodhgt9ihc A AAAA RRSIG
D0UM4ALLIO1D7SND14VCRJA8NT98IEEJ.dnssec-or-not.net. 1000 IN RRSIG NSEC3 8 3 3600 20190116161602 20181217161602 19233 dnssec-or-not.net. TRrsAF/t8dN0WiBXPvVt6MiEc1LEFjdG/HpHgb/rHPWSzHXz8z0sIVS33w1HUxbfboasJPayRCjdNZRPY9hqSwIQDs4qSw5ML/Gvtd645WZJclLqpzC1Cap02sPZscugzjQQJWc//B9QU7VWUwaZDvxGuCjsVDtPyR6v3t8gxfXl0rGroJOnBLvA3Em3DEOxkWcolFciNwuoKI/JnoH0hl/eQsQypiT4KSTyrsaxsKAqfJeYtWWqiIU664xhyzpaM1bnVBZfxQy7Vw3kjTw1eFAe/Aoo4zc8hpt0ISilrQh8su+QH9kRulcs5CtZrhR/SP/fhd7rLlVyl+RUoCmGQA==
;; ADDITIONAL SECTION:
;; Query time: 1 msec
;; EDNS: version 0; flags: do ; udp: 4096
;; SERVER: 127.0.0.1
;; WHEN: Mon Dec 24 22:34:32 2018
;; MSG SIZE rcvd: 1586
$
(2018年12月24日、ここまで修正)
(DNSSECの無効化以外の)第一フラグメント便乗攻撃対策の確認
インターノット崩壊論者の独り言 - DNSSEC は危ない - これを NSEC/NSEC3 Replacement Attack と呼ぶのはどうだろう? <http://www.e-ontap.com/blog/20181031.html>
に次の記述があります。
検証用のゾーンを作成したのでご利用ください。
dig hoge.sub.mufj.jp txt ; dig fuga.sub.mufj.jp txt
などと二度 (負荷分散されている環境では多数回) 繰り返して
"Your_cache_server_is_vulnerable."
と出たら使用中のキャッシュサーバは第一フラグメント便乗攻撃への耐性が低いと考えられます。ただし EDNS0 への対応等は別途検査が必要です。
(Unbound で検証済/harden-referral-path:yes にしないと危険 (追記: 1.8.2 で対策されました))
というわけで、まず次のコマンドを打ってみます。
$ dig @localhost hoge.sub.mufj.jp txt ; dig @localhost fuga.sub.mufj.jp txt
これで
"Your_cache_server_is_vulnerable."
と出力されなければ、とりあえず大丈夫です。
次にEDNSのバッファサイズを確認してみましょう。これは次の通りの入出力になれば問題がないです。
$ dig @localhost rs.dns-oarc.net txt | awk '/EDNS/'
; EDNS: version: 0, flags:; udp: 512
rst.x466.x461.x487.rs.dns-oarc.net. 57 IN TXT "XXX.XXX.XXX.XXX sent EDNS buffer size 512"
$
出力メッセージにより、EDNSのバッファサイズが512であることがわかります。なお、上記の XXX.XXX.XXX.XXX は実際にはテストしたマシンのIPアドレスが表示されます。
テストが終わったら、DNSの問い合わせ先をlocalhostである127.0.0.1に切り替えましょう。
おわりに
この記事ではDNSブロッキングで広告をブロックする方法を紹介しました。私のMacBook Proでも快適に動いています。広告サイトのリストは時々更新されていますので、適宜行なうようにしましょう。また、Unboundがバージョンアップした場合は、サービスを一旦停止してから行なうようにしましょう。