rixycf blog

書けたら書く

ラズパイとdockerでアドブロック用コンテナ(dnsmasq)を立てる

目的

LAN内に内向けDNSサーバ(dnsmasq)を立てて,アドブロックを行います. 今回はラズパイにdockerを入れてDNSサーバをコンテナとして運用します. そのための,dockerfileを書いていきます. アドブロックの仕組みは広告のドメインの名前解決の際に,0.0.0.0を返すようにするという単純なものです. これはDNSサーバの設定ファイルを書けば実現できます.

内向けDNSサーバによるアドブロックの長所,短所

長所

LAN内に接続する端末であれば,アドブロック用のアプリがなくてもアドブロックができる.

短所

DNSサーバの設定ファイルにない広告のドメインはブロックができない. LAN内のラズパイ死んだら,名前解決できなくなる.

用語のざっくりとした説明

DNS(Domain name system)サーバというのは,ドメイン名に対応するIPアドレスを返してくれるサーバです.その逆もできます. ブラウザ(chromeとか)にURLを入力し,相手のサーバとやりとりする前に,問い合わせるサーバです.

IIJのサイトがわかりやすいです.
DNSサーバとは

以下の動画がわかりやすいです.英語あまりわからなくても,なんとなく雰囲気で掴めるのではないでしょうか.
How a DNS Server (Domain Name System) works. - YouTube

今回はこのDNSサーバを利用します.
広告のドメインに対して,無関係のIPアドレス(0.0.0.0)をラズパイ上のDNSサーバが返すことによって,ブラウザで広告を表示させなくします.そのために,設定ファイルを書いていきます.

サーバ構築の手順

以下の手順でラズパイのOSの書き込みからDNSサーバのテストまで行いました.

  1. micro SD にraspbian-strech-lite jessieを書き込む
  2. ラズパイ初期設定(IPアドレスを固定)
  3. docker をインストール
  4. dnsmasqが入ったdocker image を作成する.
  5. ラズパイ上でコンテナを動かす.
  6. テスト

1 - 3については詳細は割愛します.

1 の参考サイト

https://hirazakura.hatenablog.com/entry/raspberrypi/setup/first

2 の参考サイト

https://qiita.com/MarieKawasuji/items/b088ffb252a92eee8f5d

3 の参考サイト

https://www.raspberrypi.org/blog/docker-comes-to-raspberry-pi/

上記のサイトを参考にして環境を構築しました.
環境は以下の通りです.
Raspberry Pi 3 Model B

raspberry pi version

$ uname -a
Linux raspberrypi 4.14.62-v7+ #1134 SMP Tue Aug 14 17:10:10 BST 2018 armv7l GNU/Linux

docker version

Docker version 18.06.1-ce, build e68fc7a
4. dnsmasqが入ったdocker image のビルド

今回は,DNSサーバにdnsmasqを選択しました.dnsmasqは小規模ネットワーク向けのDNSサーバです. DNSサーバを運用したことがなかったのでとりあえず,ざっと調べて良さげだったので選びました.

dnsmasqは,特定のドメインに対して,どのIPアドレスを返すのかをaddressオプションにて指定できます. 以下はdnsmasqのmanページのaddressオプションの引用です
Man page of DNSMASQ

-A, --address=/<domain>[/<domain>...]/[<ipaddr>]
Specify an IP address to return for any host in the given domains. Queries in the domains are never forwarded and always replied to with the specified IP address which may be IPv4 or IPv6. To give both IPv4 and IPv6 addresses for a domain, use repeated -A flags.

このオプションを使って,広告のドメインと0.0.0.0というIPアドレスを対応付けてやれば,アドブロックができます.

広告のドメインは以下のサイトで公開されているものを引用しました.
参考(https://warui.intaa.net/adhosts/hosts.txt)
ドメインは現在およそ77000個ほどあるので,これだけのサイトをブロックすることができます. このファイルをdnsmasq用に加工したあと,設定ファイルに読み込ませるようにします. ちなみに,hosts.txtは以下のようなフォーマットなのでaddressオプションに使用できる形式にします

hotst.txtの形式

IPアドレス ドメイン名

addressオプションで使う形式

address=/ドメイン名/IPアドレス

自分はcurlで引っ張ってきたものをawkを使って整形しました. この出力結果を/etc/dnsmasq.confとは別のファイルに記述し,/etc/dnsmasq.confがそれを読み込むようにします.

試しにコマンドで確認します

curl -sL "https://warui.intaa.net/adhosts/hosts.txt" | head -n 4 | \
awk 'NR > 1 {print "address=/"$2"/"$1}'

出力結果

address=/___id___.c.mystat-in.net/0.0.0.0
address=/_thums.ero-advertising.com/0.0.0.0
address=/0.r.msn.com/0.0.0.0

以上を踏まえてDockerfileを書きました.

echo でdnsmasq.confに設定を追加していきます.
curlで引っ張ってきたものは/etc/dnsmasq.adblock.confに書いて,/etc/dnsmasq.confには,conf-fileの設定を記述し,/etc/dnsmasq.adblock.confを読み込むようにします.
設定の詳細については詳しくはmanのページにのってます. http://www.thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html

dockerfile

# @rixycf dnsmasq container for adblock

FROM arm32v6/alpine

LABEL maintainer="rixycf kasnake1013@gmail.com"

RUN apk add --no-cache dnsmasq curl && \
    curl -sL "https://warui.intaa.net/adhosts/hosts.txt" | \
    awk 'NR > 1 {print "address=/"$2"/"$1}' >> /etc/dnsmasq.adblock.conf && \
    echo "domain-needed" >> /etc/dnsmasq.conf && \
    echo "bogus-priv" >> /etc/dnsmasq.conf && \
    echo "no-resolv" >> /etc/dnsmasq.conf && \
    echo "no-poll" >> /etc/dnsmasq.conf && \
    echo "server=8.8.8.8" >> /etc/dnsmasq.conf && \
    echo "server=8.8.4.4" >> /etc/dnsmasq.conf && \
    echo "conf-file=/etc/dnsmasq.adblock.conf" >> /etc/dnsmasq.conf
    
CMD ["dnsmasq", "--no-daemon"]

このdockerfileをビルドします. イメージのビルドは手元のmacで行いました. イメージはビルドした後,自分のdocker hubにアップロードして,ラズパイから持ってこれるようにしました.
docker hubのリンク https://hub.docker.com/r/rixycf/dnsmasq_adblock_alpine/

5. ラズパイ上でコンテナを動かす.

以下のコマンドをラズパイ上で実行します.

docker container run --cap-add=NET_ADMIN -d -p 53:53/udp -p 53:53/tcp \
--name adblock_dns rixycf/dnsmasq_adblock_alpine:0.1

--cap-add=NET_ADMINオプションはコンテナ内でdnsmasqを動かすために必要です. これをつけないと,コンテナ内のdnsmasqがエラーを吐いてました.悲しい.

6. テスト

テストをする前に,LAN内に接続する端末が参照するDNSサーバをラズベリーパイのIPアドレスにしておきます.

テストは,digコマンドやnslookupなどでできます. ドメイン名に対するIPアドレスが0.0.0.0になっていれば正しく動作してます.

実行したコマンド

nslookup 0.r.msn.com

出力結果

Server:      192.168.1.250
Address:    192.168.1.250#53

Name:   0.r.msn.com
Address: 0.0.0.0

良さげですね. これで一通りの環境を構築できました.

まとめ

今回は,dnsmasqを使用して,DNSサーバをコンテナとして動かしてみました. とりあえず手元のiPhone 5sで試してみたんですが,上から降ってくるとかデカイ広告は一部を除いて見えなくなりました.ブラウザのレンダリングの結果がだいぶすっきりしました. 今回の手法ですと,広告のドメイン一覧が,更新されないので,何らかの方法で更新してやる必要があります.そこは次?の課題でしょうか.

ちなみにですが,dockerfileなどはgithubにあげときました.
GitHub - rixycf/raspi_adblock_DNS: ラズパイ上で動かすアドブロック用dnsmasqのコンテナ

その他参考

Raspberry Pi 3の WiFiを広告ブロック機能付きの無線LANアクセスポイント化 hostapd + dnsmasq編
http://www.neko.ne.jp/~freewing/raspberry_pi/raspberry_pi_3_wifi_wireless_access_point_dnsmasq/

Dnsmasq を広告ブロックツールとして使う https://scientre.hateblo.jp/entry/20150521/ad_block_with_dnsmasq