Vyos 1.1.8 で dnsmasqを使用した広告除去を行う

## はじめに
今までVyosに搭載されるsquidを用いて透過型プロキシでの広告除去を行っていたのですが、
HTTPSが主流になりつつある中で、透過型プロキシでの除去が難しくなってきました。
次の手段としてvyosに搭載されるDNSフォワーダーとして使われているdnsmasqを利用し、
広告を除去してみようと思います。 理屈としては端末の hostsファイルを書き換えることと同じ原理です。

ただし、Vyosに搭載されるdnsmasqに脆弱性があるみたいな記事もあるので、
NAT配下の端末に対してのみリクエストを受け付けることとします。

## 大まかな手順

1. Vyosにてdnsmasqのサービスを有効化します。
2. 広告ブロックリストから、dnsmasqの名前解決リストを生成します
3. dnsmasqに作成した名前解決リストを読み込ませます。
4. DHCPで配布するDNSサーバをvyosのIPに向けます。  
    *もちろん固定IPでもDNSサーバをvyosのIPにすることで広告除去は可能です。

### 環境概要
|       項目 |    値    |
|:------------------|:------------------:|
|ローカルインターフェイス| eth0|
|IPアドレス|192.168.0.1|

### 1. vyosでdnsmasqのサービスを有効化
受付はローカルインターフェイス `eth0` のみにします。 

```console
vyos@vyos# set service dns forwarding listen-on eth0  

```
次にフォワード先を指定します。

```console
vyos@vyos# set service dns forwarding name-server 8.8.4.4
```

設定はこんな感じ

```console
vyos@vyos:~$ show dns forwarding nameservers
-----------------------------------------------
   Nameservers configured for DNS forwarding
-----------------------------------------------
8.8.4.4 available via 'statically configured'

vyos@vyos:~$ show dns forwarding statistics
----------------
Cache statistics
----------------
Cache size: 150
Queries forwarded: 1352
Queries answered locally: 1973
Total DNS entries inserted into cache: 2555
DNS entries removed from cache before expiry: 320

---------------------
Nameserver statistics
---------------------
Server: 8.8.4.4
Queries sent: 1352
Queries retried or failed: 0
```

この状態でこのルータに対して名前解決できるかどうかをNAT配下にあるサーバからチェックしてみます。

```console
[root@Server]~# dig +short @192.168.0.1 qiita.com
176.34.46.0
54.248.118.230
```

問題なく解決できることを確認

### 2. 広告ブロックリストを作成

インターネット上で公開されているブロックリスト(https://warui.intaa.net/adhosts/) から生成します。

こちらで公開されているファイルからワンライナーでdnsmasqでの形式に生成可能です。
vyosに入っている`OpenSSL`のバージョンが古いため、curlでそのままHTTPS通信ができませんでしたので、httpにURLを変更しています。

```console
vyos@vyos:~$ curl -s 'http://warui.intaa.net/adhosts/hosts_lb.txt' | tail -n +2 | awk '{print "address=/"$2"/"$1}' > adblock.conf

vyos@vyos# head adblock.conf
address=/___id___.c.mystat-in.net/127.0.0.1
address=/_thums.ero-advertising.com/127.0.0.1
address=/0.r.msn.com/127.0.0.1
address=/00-lawyer.com/127.0.0.1
address=/0001.2waky.com/127.0.0.1
address=/000143owaweboutlookappweb.myfreesites.net/127.0.0.1
address=/000hhjq.rxportalhosting.com/127.0.0.1
address=/005.free-counter.co.uk/127.0.0.1
address=/006.free-adult-counters.x-xtra.com/127.0.0.1
address=/006.free-counter.co.uk/127.0.0.1
[edit]
vyos@vyos#
```

内容は随時更新されているようなので、全く同じにならない可能性もありますが、
`address=/ドメイン名/127.0.0.1` になるようにアドレスを追加していけばOKです。

### 3. 広告ブロック設定の読み込み

前項で作成したファイルを、dnsmasqの設定ファイルディレクトリにコピーし、
サービスを再起動します。

```console
vyos@vyos# sudo cp adblock.conf /etc/dnsmasq.d/
vyos@vyos# sudo /etc/init.d/dnsmasq restart
Restarting DNS forwarder and DHCP server: dnsmasq.
[edit]
vyos@vyos#
```

エラーが出なければこれで読み込みは完了です。
エラーが出た場合は、作成したファイルが壊れている可能性が高いので内容を確認してみてください。

きちんとブロック対象のIPアドレスが127.0.0.1に向いているかどうかをdigでチェックしてみます。

```console
[root@Server]~# dig +short @192.168.0.1 0735sh.com
127.0.0.1
[root@Server]~# dig +short @8.8.4.4 0735sh.com
104.164.92.246
```

今回構築したvyosのIP(192.168.0.1)に対して登録しているドメイン`0735sh.com`を問い合わせをすると`127.0.0.1`が
帰ってきますが、GoogleのDNSに問い合わせると`104.164.92.246` が帰ってきています。

```console
[root@Server]~# dig +short @192.168.0.1 microsoft.com
23.100.122.175
23.96.52.53
191.239.213.197
104.40.211.35
104.43.195.251
```

もちろん、登録されていないドメインはフォワーディングされてきちんと解決されています。
これで広告ブロックができるDNSキャッシュサーバの完成です。わーい


### 4. 既にDHCPサービスが有効になっている場合のDNS変更

dnsmasq自体もDHCPサーバ機能を持っているようですが、VyOSではDHCPはdhcpdが担っており、
dnsmasqはDNSフォワーディングとして使うことを想定しているようなのでdhcpdの設定を変更します。

```console
 set service dhcp-server shared-network-name dhcp1 subnet 192.168.0.0/24 dns-server 192.168.0.1
```

もちろんDHCPを使っていない場合や、DNSを配布していない場合はこの設定は不要です。手動でDNSをvyosに向けてください。

これでバッチリ広告ブロックすることができました。
ホントは127.0.0.1じゃなくて存在するWebサーバに向けたほうが速いのかなぁ……


#### 追記
こんなややこしいことしなくても設定ファイルに参照するhostsファイルを追加することで、
広告ブロック用に使われているhostsファイルをそのまま使うことができまました。

```
addn-hosts=/etc/dnsmasq.hosts.d
```

`addn-hosts` の項目は、ディレクトリを指定することでその以下のファイルを読み込み、
ファイルを指定することでファイルを単体で読み込むことが可能なようです。

私の場合はディレクトリを掘って、`adblock.hosts` という名称でブロック用hostsファイルを設置しました。

```console
sudo curl http://warui.intaa.net/adhosts/hosts.txt -o /etc/dnsmasq.hosts.d/adblock.hosts
```