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サーバのIPアドレスを管理者が適当に設定できるようだ。

このルータ内蔵の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

まとめ

 本記事では、我が家で常時稼働している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:これに関しては何かと角が立ちそうなので、具体的なページで広告ブロックが行われている様子は出さない

Synology DS920+を使って外付け光学ドライブをネットワークに共有する

 光学ディスクの重要性が低下し、巷で売られているPCに読み取り用のドライブが標準搭載されなくなって久しくなりましたが、それでもCDの類を読み込みたくなる機会は度々訪れます。今ほどダウンロード販売が盛んではなかった頃に買ったソフトウェアのインストーラ、PCに付属のリカバリーディスク、昔ハマったアニメのBDなど、日常的に使う訳ではないけど一応読み込みの手段は残しておきたい光学ディスクも多いでしょう。

 内蔵式のドライブをめっきり見なくなった今、光学ディスクの読み出し手段を確保しようと思えばUSB等で接続される外付けドライブに頼る事になると思うのですが、PCを複数持っている場合は接続を切り替えるのが面倒だし、この光学ドライブと言う奴は結構電力を食うせいで接続できるポートが限られるので困ったものです。適当なポートに外付けドライブを接続しておいて、ネットワークからアクセスできれば良いのにと思うのは自然な発想でしょう。

 Windowsにはネットワーク経由でファイルを共有する機能が標準で備わっていますから、適当なマシンに外付けドライブの光学ドライブを接続し、ネットワークからアクセスできるようにするのは難しくありません。しかし、適当なWindowsマシンを常に起動しておくのも消費電力が気になるところですから、サーバーとして常時稼働する事を前提としたマシン、例えばNASなんかを使いたい気持ちになります。

 本記事では、我が家で使っているSynology社のNAS、DS920+に接続した外付け光学ドライブをネットワークで共有し、ローカルネットワーク上の他のマシンから見られるようにした際の手順を紹介します。実機で検証はしていませんが、Synology Virtual Machine Managerをサポートしている同社のNASであれば同様の手段で光学ドライブを共有できるものと思われます。

続きを読む

ダイクストラ法の一般化と,その正当性の Coq を用いた検証

 AtCoder Beginner Contest の E 問題で2回続けてダイクストラ法が出題される昨今,いかがお過ごしでしょうか?[^1]

 その2つの E 問題のうち,先に出題された E - Come Back Quickly はいかにも典型的だなあといった問題なので良いのですが,後に出題された E - Train は一筋縄ではいかないものでした.典型的な最短経路問題は辺の長さが定数であるようなグラフを対象としていますが,その問題では辺の長さが,その辺に辿り着くまでの経路長に依存するようなグラフに対してダイクストラ法を適用するのが想定解だったからです.

 本記事では,頂点uに辿り着くまでの経路長 c に頂点 u から頂点 v に伸びる辺の長さを加えたものが関数 d_{uv}(c) として与えられた際に,d_{uv}(c) が単調増加関数かつ  {c \leq d_{uv}(c)} を満たせばダイクストラ法が最短経路を返すことを解説します.加えて,ナイーブな実装ではありますが,そのようなグラフに対してのダイクストラ法が最短距離を返すことを Coq で証明します.

続きを読む

List.fold_right で List.fold_left を書く

 この記事は ML Advent Calendar 2020 の14日目の記事です.

 リストの Church encoding と言えば List.fold_right で表現することが多いように思いますが,果たして List.fold_right だけしか使わずに様々なリストについての再帰関数を表現できるのか疑問に思う人も多いのではないでしょうか? 本記事では,List.fold_right を用いて List.fold_left を実装する方法を紹介します.後者は末尾再帰なのでわざわざ回りくどいことをせずに直接使った方が良いのはもっともなのですが,foldr/build なんかを考える時に頭の片隅にあると便利かもしれません.

続きを読む

Deforestation で強連結成分分解を改善する

 この記事は ML Advent Calendar 2020 の10日目の記事です.

 本記事では,強連結成分分解を行うアルゴリズムの一種である Kosaraju のアルゴリズムに対して deforestation を施し,トポロジカルソートの結果をリストとして保持することなく計算できることを観察します.

12/11 Kosaraju のアルゴリズムを勘違いしていたので実装を修正しました.根本的な勘違いのせいで TaPL 27章みたいな事になっており,厳しい…

続きを読む

ML のサブセットの型推論器を Coq で検証する

 この記事は言語実装 Advent Calendar 2020 の5日目の記事です.

 一度でも型推論器を書いたことがあれば,そのあまりの邪悪さ,あるいはその複雑さに恐れ慄いたことでしょう. 参照を用いて単一化を実現しようものなら構文木は参照に汚染され,純粋関数型に実装しようものなら大量の型代入をどのような順序で適用したものか悩まされる. これは Hindley-Milner 型推論器を実装する上での宿命のようなものです.

 本記事では,MLのサブセット——型付きλ計算をletと参照で拡張した,let多相をサポートする言語——の型推論器を Coq で実装し,その正当性を証明します. Coq で検証を行うことで我々は型推論器のバグへの恐怖とデバッグの労力から真に解放され,枕を高くして眠ることができることでしょう. もっとも、型付きλ計算を let 多相で拡張した言語の型推論器の正当性は実はすでに証明していて, あとは対象言語を参照で拡張するだけという話もありますが.

続きを読む

効率的な正規表現エンジンを Coq で検証する

 今年はそれらしきアドベントカレンダーが無いので,この記事は ML アドベントカレンダー 2020 の4日目の記事と言い張ってみます. ML って本を正せば定理証明支援系由来ですし.最後にちょっと OCaml を使ってますし.

 Coq によって検証された正規表現エンジンは既に存在していて,探せば他にもいくつもあると思うのですが, それらの実装は主として検証の簡単さに重きが置かれており,OCaml のコードを extract して使ってみると実用に堪えないものが多いように思います. 本記事では,以前 OCaml で書いた効率的な実装を Coq に移植して検証します. 加えて,extract によって OCaml のコードを再び生成し, AtCoder の問題に投げてみても TLE にならないことを確認します.

続きを読む