Posted at

VPS+VPN+Pi-holeで広告ブロックする


はじめに


動機


  • スマホだと広告が鬱陶しく感じるなあ

  • ローカルプロキシ系はそのプロセスが落ちると全断だから嫌だな

  • VPSで広告ブロックプロキシ立てて使おう

  • オープンプロキシはありえないから認証は必須だな

  • Androidだとプロキシで認証できないじゃん


    • 設定できるアプリもあるけど「特定のWi-Fiにつないだときプロキシ設定」だから、常にプロキシしたい今回のユースケースにはマッチしないな



  • VPSまでVPN張るか

  • Androidでは「VPNにつないだときだけプロキシを設定」ってのはできないのか……


    • iOSだと可能らしい



  • DNSレベルで広告ブロックするPi-holeというのがあるのか

  • 「VPNにつないだときだけDNSサーバを設定」はできる!

という感じです。


環境


  • サーバ Ubuntu xenial

  • クライアント Android Pie


手順


VPNを張る


サーバ側

OpenVPNを使いました。なぜならUbuntu設定ガイドがあるからです。

基本的にはこれに従ってやっていけばいいのですが、デフォルトの暗号(BF-CBC)は脆弱性を抱えているようなので、AES-128-CBCを使いましょう。

cipher AES-128-CBC

これをserver.confに書いておいてください。

ちなみに設定中のIPフォワーディング設定(net.ipv4.ip_forward=1)は今回のVPN用途では使わないのですが、Pi-holeが必要とするようなのでやっておきましょう。


クライアント側

OpenVPNはいわゆるSSL-VPNを使います。そしてAndroid標準のVPN機能はSSL-VPNには対応していません。

したがって対応したクライアントソフトが必要です。OpenVPNはAndroid版があるのでそれを使えばいいのですが、Google Playで検索するとOpenVPN Connectが先にヒットすると思います。これは商用サービスのOpenVPNのクライアントなので違います。

OpenVPN for Androidを使います。各種設定をし、特に暗号をAES-128-CBCにするのを忘れないようにします。

また注意点として、Androidではクライアント証明書と秘密鍵を扱うときに、証明書と秘密鍵が別々のファイルではダメで、PKCS#12なるフォーマットで1つになっていなければならないようです。

こちらの記事を参照しpkcs#12ファイルを事前に生成しておいてください。

うまくいけばサーバ側からpingが当たるはずです。


Pi-holeを立てる

Pi-holeはざっくり言うと、ブラックリストにマッチしたドメイン名を無効なIPアドレスに解決させてはたき落とすDNSキャッシュサーバです。そのブラックリストを有志がメンテナンスしているわけですね。公式サイトはこちら

とりあえずdockerで上げてみます。こちらgit cloneし、READMEに従いながらdocker_run.shを編集します。TZと2つ目の--dnsをいじればいいのですが、このまま起動してしまうと全てのポートが::にバインドされてしまい、オープンリゾルバになってしまいます。-pオプションの引数に${VPNのIP}:等を前置し、グローバルに開放しないようにしましょう。

起動するとWeb UIのパスワードが出力されるので控えておきます。Web UIから入ってSettings > DNS > Upstream DNS Serversをお好みで調整しましょう。

VPNに接続したときPi-holeをDNSサーバとして利用するには2つの方法があります。server.confにpush "dhcp-option DNS ..."を書いて設定させるか、クライアント側で設定するかです。僕はクライアント側で設定しました。

うまくいけば腹立たしい広告が出なくなるようになるはずです。Pi-holeのデフォルトブラックリスト(正確にはGravity)でも十分な効果を感じました。


まとめ

VPS上でPi-holeを立て、VPN経由で利用することでスマホで広告ブロックすることができました。

Pi-holeのログを見ているとひどいときには半分以上がブロックされていて、広告ありすぎなのかPi-holeがやりすぎなのかはわかりませんが、今のところ問題は感じていません。