EdgeRouter Xで広告をブロックする

# TL;DR
- EdgeRouterに搭載されるdnsmasqを利用して広告をブロックします．
    - 直接ファイルを弄るとシステムに上書きされるので，EdgeOS用のコマンドでのやり方をご紹介します．
    - hostsファイルを利用して広告のドメインを本来とは別のIPアドレスで解決します．

# 手順
EdgeOSにおける設定は，sshしたあとに専用コマンドを実行するか，GUIのConfig Treeより行います．
Linuxなので設定ファイルを直接弄ることも可能ですが，ファームウェアアップデートなどシステム側に上書きされる可能性があります．
主な手順は以下のとおりになります．

1. dnsmasqの設定をします．
- 広告ブロックリストを生成します
- ブロックリストの定期更新設定をします．

また本稿におけるEdgeRouterのインターフェース等は以下の設定になっています．
eth0をWANポートとしてPPPoE接続をしています．switch0はeth1〜4までを束ねたスイッチとして機能しています．

| インターフェース    | IPアドレス         |
|:-----------------|------------------:|
| eth0             |                   | 
| pppoe            | グローバルIP        |
| switch0          | 192.168.1.1/24    |

EdgeOSのコンソールでは，以下の`configure`コマンドでコンフィグレーションモードに切り替え，`exit`で終了します．本稿では通常の操作モードを`$`で，コンフィグレーションモードを`#`で表現します．詳細は[公式マニュアル](https://help.ubnt.com/hc/en-us/articles/204960094-EdgeRouter-Configuration-and-Operational-Mode)を参照してください．

```
$ configure
# commit
# save
# exit
```

## dnsmasqの設定

EdgeOSのdnsmasqを有効化します．使い方によっては初期設定時に既に同じような設定になっているかもしれません．ご自身の環境に合わせてインターフェースとネームサーバの設定をしてください．

```
# set service dns forwarding listen-on eth0
# set service dns forwarding listen-on pppoe0
# set service dns forwarding listen-on switch0
# set service dns forwarding system

# set system name-server 192.168.1.1
# set system name-server 8.8.8.8
```

次に広告ブロック用ブラックリストの配置先ディレクトリを指定します．
以下の設定で，dnsmasq起動時に`/etc/dnsmasq.hosts.d/`下へ配置したhostsファイルを読み込みます．
 
```
# set service dns forwarding options addn-hosts=/etc/dnsmasq.hosts.d
```

## 広告ブロックリストの作成

広告ブロックリストを作成します．
上記で指定したディレクトリに以下のようなフォーマットのホストファイルを配置します．広告ブロックしたいドメインを全て`0.0.0.0`に紐づかせます．

```adblock.hosts
0.0.0.0 googleadservices.com
0.0.0.0 ad.dmm.com
```

当然，手動で広告ドメインを記述するとキリがないので，既にまとめてくださっている方のファイルを参照します．ファイルを配置した後にdnsmasqを再起動します．

```{bash}
$ sudo mkdir /etc/dnsmasq.hosts.d
$ sudo curl https://warui.intaa.net/adhosts/hosts.txt -o /etc/dnsmasq.hosts.d/adblock.hosts
$ /etc/init.d/dnsmasq restart
```

お使いの端末からブロック対象のドメインが`0.0.0.0`になっているか確認します．

```
$ dig +short 0.r.msn.com
0.0.0.0
```

## スクリプトにまとめる

広告ブロックのリストを定期的に更新するために一連の動作をスクリプト化します．ファームウェアアップデートなどで作成したディレクトリ等も消されてしまう可能性もあるため，ディレクトリ作成もスクリプト内で実行しています．作成したスクリプトは`/config/scripts/update_adblock.sh`に配置します（EdgeOSでは`/config`下に配置するとファームウェアアップデートの影響を受けずにファイルを保存できます）．

```update_adblock.sh
#!/bin/sh

DIR=/etc/dnsmasq.hosts.d
OUTPUT=$DIR/adblock.hosts

mkdir -p $DIR
curl https://warui.intaa.net/adhosts/hosts.txt -o $OUTPUT
curl https://280blocker.net/files/280blocker_domain.txt | sed "s/^[a-zA-Z0-9]/0.0.0.0 /g" | dos2unix >> $OUTPUT

sed -i "/localhost/d" $OUTPUT
sed -i "s/127.0.0.1/0.0.0.0/g" $OUTPUT
sed -i "/^$/d" $OUTPUT
sed -i "/^#/d" $OUTPUT

/etc/init.d/dnsmasq restart
```

スクリプトでは，以下を行っています．

- `/etc/dnsmasq.hosts.d/`ディレクトリの作成
- インターネット上のホストファイルを取得（必要であれば，適切な形式にフォーマットする）
- 不要な記述の削除（コメントアウトや改行など）
- dnsmasqの再起動

参考文献にその他ブロックリストのURLを載せておくので必要があれば追加してください．

## スクリプトの定期実行

最後にスクリプトの定期実行を設定します．以下のコマンドは内部的にcronの設定を行っています．

```
# set system task-scheduler task update-adblock crontab-spec '0 9 * * * 3'
# set system task-scheduler task update-adblock executable path /config/scripts/update_adblock.sh
```

2行目のコマンドで`File /config/scripts/update_adblock.sh does not exist or is not executable`のように怒られる場合はスクリプトの実行権限を確認してください．

# 追記

上記の設定を行っても広告がブロックされない場合があります．その場合，以下の原因が考えられます．

### 別のDNSサーバで解決している

DHCPサーバや無線APなどで別途DNSを指定している可能性があります．`8.8.8.8`などを個別に設定していると，そちらで解決される可能性があるためEdgeRouterのアドレスだけを指定しましょう（Android端末でセカンダリに設定されていた`8.8.8.8`が優先されているのを確認しました）．

### IPv6アドレスで解決している

EdgeRouterでIPv6ネットワークに対応していると，IPv6に対応する広告が表示されてしまいます．IPv6も解決できないようにしましょう．
以下のコマンドをスクリプトに追加します．これでIPv6アドレスは`::`で解決されます（IPv4の`0.0.0.0`に相当します）．

```{bash}
cat /etc/dnsmasq.hosts.d/adblock.hosts | sed -e 's/0.0.0.0/::/g' > /etc/dnsmasq.hosts.d/adblock.v6.hosts
```

確認すると以下のとおりになります．

```
$ nslookup tpc.googlesyndication.com                                                                                                                                       master-  [2:54:55]
Server:		192.168.1.1
Address:	192.168.1.1#53

Name:	tpc.googlesyndication.com
Address: 0.0.0.0
Name:	tpc.googlesyndication.com
Address: ::
```

# 参考
- [Vyos 1.1.8 で dnsmasqを使用した広告除去を行う](https://qiita.com/crowz/items/b4b8a9e5d025a8ad6cae)
- [EdgeRouter - Backing Up the Config Directory](https://help.ubnt.com/hc/en-us/articles/360044753453-EdgeRouter-Backing-Up-the-Config-Directory)
- [EdgeRouter - Configuration and Operational Mode](https://help.ubnt.com/hc/en-us/articles/204960094-EdgeRouter-Configuration-and-Operational-Mode)

### 広告ブロックリスト
- https://warui.intaa.net/adhosts/hosts.txt
- https://280blocker.net/files/280blocker_domain.txt
- https://logroid.github.io/adaway-hosts/hosts_no_white.txt
- http://winhelp2002.mvps.org/hosts.txt
- https://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&showintro=0&mimetype=plaintext
- https://hosts-file.net/ad_servers.txt
- https://raw.githubusercontent.com/multiverse2011/adawaylist-jp/master/hosts
- https://adaway.org/hosts.txt