fetburner.core

コアダンプ

どこのご家庭にもあるNASにPi-holeを導入して、ネットワーク側で広告を非表示にした話

 例えば死、戦争、飢餓、この世には無くなった方が幸せになれるものが沢山存在しているが、Web広告もその一つだろう。 流石に死だとか戦争だとかは厳しいかもしれないが、広告に関してはネットワーク技術の力で消し去ることができる。

 本記事では、我が家で常時稼働しているNASにPi-holeを導入し、ネットワーク側で広告ブロックを試みる。この手法はクライアント側で特別な対応を必要としないため、スマートフォンタブレットと言った非力な端末でのブラウジングでも体験を損なわない事が期待される。

Pi-holeとは

 Pi-holeとは、広告を配信するドメインへの名前解決要求に対して、本来とは異なるIPを返すことで広告の表示を妨げるDNSサーバである。要するに広告に特化したDNSシンクホールだ。

pi-hole.net

 実装としては、DNSサーバとしての機能はdnsmasqによって提供し、その設定を独自の気の利いたWeb UIから行えるようにする構成になっている。dnsmasqを使ったDNSシンクホールと言えばネットワークのオタクが良くやっていた印象だが、Pi-holeはそれを気軽に導入、運用できるようにしたものとも言えるだろう。

 その名が示す通り、Pi-holeはラズベリーパイ上でも動作するほど軽量*1な点を宣伝しているが、何もシングルボードコンピュータでしか動作しない訳ではなく、メジャーどころのLinuxディストリビューションが入ったamd64アーキテクチャの計算機であれば公式に動作が保証されている。

docs.pi-hole.net

NASへのPi-holeの導入

 Pi-holeはDNSサーバなので基本的には常時起動しておくものだが、だからこそ低消費電力かつ長時間の稼働に耐えるマシンでホストしたいものだ。ラズベリーパイは省電力ではあるものの、ストレージ周りの設定を詰めなければ比較的短期間でSDカードが天寿を全うしてしまうため、案外サーバ用途には敷居が高い。

 その点NASは常時稼働を前提として作られており、低消費電力のCPUを搭載していて電気代にも優しい。幸いにも我が家にあるSynology製のDS920+*2というNASは、組み込み向けに作られた低消費電力のCeleron*3を搭載し、OSはメーカ独自のLinuxディストリビューション、おまけにDockerコンテナのホストまで公式にサポートと、まさにPi-holeのホストにうってつけと言えよう。どうせファイルサーバとして電源を点けっぱなしにしているのだし、少しくらい計算機資源を分けて貰ってもバチは当たらない筈だ。

www.synology.com

 さて、Dockerを使ってPi-holeをNASに導入するにあたっては、公式のGitHubリポジトリにあるdocker-compose.ymlを以下のように若干改変して用いる。*4 変更点を解説しておくと、タイムゾーン日本標準時に設定し、Web UIの用いるポートを空いていた8080番に移動させたほか、DHCPサーバ周りの設定を削除している。

7c7
<     image: pihole/pihole:latest
---
>     image: pihole/pihole
12,13c12,13
<       - "67:67/udp" # Only required if you are using Pi-hole as your DHCP server
<       - "80:80/tcp"
---
> #     - "67:67/udp" # Only required if you are using Pi-hole as your DHCP server
>       - "8080:80/tcp"
15c15
<       TZ: 'America/Chicago'
---
>       TZ: "Asia/Tokyo"
22,23c22,23
<     cap_add:
<       - NET_ADMIN # Required if you are using Pi-hole as your DHCP server, else not needed
---
> #   cap_add:
> #     - NET_ADMIN # Required if you are using Pi-hole as your DHCP server, else not needed

github.com

公式の提供するdocker-compose.ymlはいかにも設定ファイルの入ってそうな/etc/pihole/etc/dnsmasq.dといったディレクトリをバインドマウントで上書きするため、それらの中身を用意せずに単純にdocker-compose up -dして大丈夫だろうかと心配になるのだが、全くの杞憂だった。どうやら初回起動時に勝手に設定ファイルが作られるようだ。

DHCPサーバによるPi-holeの通知

 Pi-holeを導入するのも良いが、それをDNSサーバとして用いるようにクライアントを設定しなければ効果を発揮しない。クライアント毎にDNSサーバの設定を変更するのは骨が折れるので、Pi-holeのIPアドレスを通知するようにDHCPサーバを設定するのが良いだろう。

 ネットワーク接続に必須の機器が物理的に複数存在すると混乱しそうなので、我が家ではDHCPサーバはルータ内蔵のものを使うことにしている*5が、幸い今使っているNEC製のUNIVERGE IX2215*6というルータはDHCPサーバの通知するDNSサーバ情報を管理者が適当に設定できるようだ。

このルータ内蔵のDHCPサーバからPi-holeのIPアドレスを通知するために、以下のようなコマンドで設定を行った。

ip dhcp profile dhcpv4-server
  dns-server 192.168.1.4 192.168.1.1
  fixed-assignment 192.168.1.4 XX:XX:XX:XX:XX:XX
!

ここではPi-holeが落ちていた時のために、セカンダリDNSとしてルータ自身の提供するDNSプロキシを指定しているほか、Pi-holeをホストするNASIPアドレスを192.168.1.4に固定している。

jpn.nec.com

Pi-holeの実運用

 ここまでの設定が済めば、自宅のLANに接続しているデバイス上でPi-holeによる広告ブロックが有効となる。Pi-holeのWeb UIを確認すると定期的に広告配信用のドメインが弾かれている様子が見られるし、実際タブレットでWebページを開いていても広告が存在していたであろう不自然な空白を見かけるようになった。*7

 Pi-hole導入時から入っている広告ドメインのリストは国外の開発者が作成しているため、国内の業者による広告が時々排除できていないのは個別に対応するとしても、YouTubeの動画広告は原理的に対処が困難なのがPi-holeの残念な所だ。これに関してはWebプロキシ等でコンテンツの中身を見てフィルタリングを行わせる必要があるだろう。

discourse.pi-hole.net

2022/12/14 追記

 実際にDockerで運用してみれば分かる通り、ポートフォワーディングを使ってPi-holeをLANに公開すると、アクセスログに記録されるクライアントIPアドレスがDocker内部ネットワークのデフォルトゲートウェイで埋め尽くされてしまう問題がある。

この問題に対する素朴な解決法としては、hostネットワークモードを使ってLANに直接DNSサーバを公開する事が挙げられるが、Web UIの用いる80番ポート*8を空けておく必要があるため、万人に勧められる方法と言う訳でもない。我が家のNASでも80番ポートは既に占有されていたため、以下のdocker-compose.ymlのようにmacvlanネットワークドライバを使って仮想的なNICを作成し、コンテナをNASとは別のIPアドレスでLANに接続する事で解決した。

version: "3.8"
services:
  pihole:
    image: pihole/pihole
    environment:
      TZ: "Asia/Tokyo"
    volumes:
      - './etc-pihole:/etc/pihole'
      - './etc-dnsmasq.d:/etc/dnsmasq.d'
    networks:
      default:
        ipv4_address: 192.168.1.254
    restart: always

networks:
  default:
    driver: macvlan
    driver_opts:
      parent: ovs_bond0
    ipam:
      config:
        - subnet: 192.168.1.0/24

まとめ

 本記事では、我が家で常時稼働しているNASにPi-holeを導入し、ネットワーク側で広告ブロックを試みた。この手法はクライアント側で特別な対応を必要としないため、スマートフォンタブレットと言った非力な端末でのブラウジングでも特に体験は損なわなかった。一方、YouTubeの動画広告は原理的に非表示にするのが難しいため、Webプロキシ等別の手段で対処する必要が生じた。

 冷戦の頃であれば宇宙開発に従事していたであろう理系の最上位層が広告をクリックさせるのに心血を注ぎ、インターネットが質の低いコンテンツで溢れる現代では、広告ブロックの導入は重要なライフハックと言える。ご家庭にサーバが余っていれば、DNSシンクホールを作ってみるのも良いのではないだろうか。

*1:単なるdnsmasqなので当然だが

*2:ここに公式の商品ページへのリンクも貼ろうとしたが、後継品が出たせいかページが消えていて困った

*3:このCeleronAtomから派生したマイクロアーキテクチャを採用しており、電力効率が良いのは勿論のこと、第一世代のCoreに近いIPCは出るのでサーバ用途には侮れない性能を発揮してくれる

*4:Synology製のNASはWeb UIからDocker Composeを使う手段を提供していないため、SSHで入って操作する必要がある点に注意

*5:従って、Pi-hole自身をDHCPサーバとする機能は使わない

*6:定価だと仰々しい値が付いているが、リース落ちの中古がダブついているのか、ヤフオク辺りでは業者が捨て値で大量出品している光景が見られる

*7:これに関しては何かと角が立ちそうなので、具体的なページで広告ブロックが行われている様子は出さない

*8:こんな銀座の一等地みたいなポート番号を軽率に使わないでほしい