はじめに
本稿はDNS Over HTTPS(DoH) サーバーを構築したログを記載するものです。
Cloudflare, Tailscale, dns-over-https, Pi-holeで構成しています。
このDoHサーバーの主な目的はDNSリクエストをコントロールすることで、ブラウザに表示される不要な広告を除去(ブロック)することです。
マシン全体ではなく特定のブラウザのみに構築したDoHサーバーを設定できるため、システムや他アプリケーションの安定性を損なうことなくDNSを使用した広告の除去が可能です。
メインのソリューションとなるPi-holeはDNSアクセスをコントロールするためソフトウェアで、十分な機能を揃えたWeb 管理画面からステータスやログを確認したり設定の変更を行うことができます。
ブラウザなどのソフトウェアに設定を行うことで、それらのDNSリクエストについてPi-holeを経由させ、Pi-holeはフィルタ条件に基づき不適切なリクエストを遮断します。この仕組みにより、DNS単位での広告のブロックが可能になります。
デフォルトで事前定義されたブロックリストが読み込まれるため、インストール直後からすぐに広告ブロックのために使うことができます。この手のソフトウェアの例に漏れず定義はやや強めの基準で作られていますが、ブロックの解除も管理画面から簡単に行うことができます。
注記
- この用途で同様のスペックのものとしては例えばADGUARD DNSというマネージドのソリューションが存在しますが、月額$20程度とそれなりによいお値段がします。
- サーバーにはグローバルIPを割り当てる必要があります。
- HTTPS化のためにCloudflare DNS Proxyを使用しているため、Cloudflare上でドメインのAレコードとしてサブドメインを1つサーバーに割り当てる必要があります。
- 検証/運用環境としてOracle Cloud Infrastructure(OCI) のUbuntu 22.04 LTSを使用しています。
想定運用コスト
- ドメイン購入/維持費(サブドメインを1つ使えればよいので既にあれば実質無料)
- Cloudflare - Free Plan(無料)
- Tailscale - Free Plan(無料)
- Oracle Cloud Infrastructure(OCI)
- AMD Compute VM - Free Tier - Always Free(無料)
- Outbound Data Transfer - First 10 TB / Month(無料)
構成図
Pi-hole インストール
curl -sSL https://install.pi-hole.net | bash
インタラクティブなインストールを実施する。
必要があればパスワードをより長いものにする。
pihole -a -p new_passward
全てのインターフェイスからの通信を許可する。
pihole -a -i all
lighttpd 設定
sudo vi /etc/lighttpd/conf-enabled/15-pihole-admin.conf
次の行を追加しポートを8080に変更する。
server.port := 8080
sudo vi /etc/lighttpd/lighttpd.conf
デフォルトのポートが80となっていて、後述するdns-over-httpsでの設定とコンフリクトするため次の行のように適当なポートに変更する。
server.port = 8000
サービスを再起動する。
sudo systemctl restart lighttpd
ファイアウォール 設定
iptablesでDNS(UDP 53), HTTP(TCP 80, 8080)の通信を許可する。
-A INPUT -p udp --dport 53 -j ACCEPT
-A OUTPUT -p udp --sport 53 -j ACCEPT
-A INPUT -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
-A OUTPUT -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
-A INPUT -p tcp --dport 8080 -m state --state NEW,ESTABLISHED -j ACCEPT
-A OUTPUT -p tcp --sport 8080 -m state --state ESTABLISHED -j ACCEPT
注記: 53, 8080ポートはVMの外側のクラウドサービス側のファイアーウォールで遮断され、SSH以外ではTCP 80ポートのみがインターネットからアクセス可能となる想定です。
現在の設定の保存
sudo netfilter-persistent save
設定の編集
sudo vi /etc/iptables/rules.v4
変更の反映
sudo iptables -F
sudo netfilter-persistent reload
DNSサーバーと8080ポートの管理画面にローカルからアクセスできることを確認する。
Tailscale インストール
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
表示された次のようなURLから認証を行う。
https://login.tailscale.com/a/xxxxxxxxxx
設定後、Tailnet内の他端末から管理画面にアクセスできることを確認する。
dns-over-https インストール
sudo apt install make git golang
git clone https://github.com/m13253/dns-over-https.git
cd dns-over-https
make
sudo make install
sudo vi /etc/dns-over-https/doh-server.conf
次の2箇所の設定を変更し、セキュアではないHTTP 80ポートで問い合わせを受けるサーバーを立て、上流のDNSサーバーとしてローカルのPi-holeを使うようにする。
# HTTP listen port
listen = [
":80",
## To listen on both 0.0.0.0:8053 and [::]:8053, use the following line
# ":8053",
]
upstream = [
"udp:127.0.0.1:53",
]
サービスを開始する。
sudo systemctl start doh-server
sudo systemctl status doh-server
サービスが正常に動作することを確認したら常に動作するように有効化する。
sudo systemctl enable doh-server
クラウドサービス側 セキュリティ設定
必要があれば80ポートを開ける作業を実施する。
Cloudflare DNS Proxy設定
Aレコードとして適当なサブドメイン名と対象のサーバーのグローバルIPを指定する。
HTTPS化のため、DNS ProxyがProxiedになっていることを確認する。
DoH(DNS Over HTTPS)サーバー 動作確認
例えば次のようなURLへのGETで200 OKが返ることを確認する。
https://your-domain-name/dns-query?dns=AAABAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB
参考:
「4.1.1. HTTP Request Examples」
「4.2.2. HTTP Response Example」
ブラウザへのDoH(DNS Over HTTPS)サーバー 設定
参考: