自宅LANから外部公開ドメインで自宅サーバーにアクセス!dnsmasqでDNSスプリットホライズンを構築する方法

未分類

「自宅サーバーをDDNSで外部公開できたのに、自宅のWi-Fiからだけアクセスできない…」
そんな悩みを抱えていませんか?これは NATループバック(ヘアピンNAT) に対応していないルーターで起こる問題です。
本記事では、軽量DNSサーバー dnsmasq を使って、LAN内からDDNSドメインにアクセスした際に自動的にLAN内のIPアドレスへ振り向ける「DNSスプリットホライズン」を構築する方法を解説します。Deco(TP-Link)ルーターのDHCP設定と組み合わせることで、LAN内のすべてのデバイスが設定不要で自動的に恩恵を受けられます。

なぜこの機能を作ったのか?

我が家のスマートホームシステムでは、NUCBoxをホームサーバーとして稼働させており、GrafanaダッシュボードやFlask APIをNginxリバースプロキシ経由でDDNSドメイン名(xxxx.tplinkdns.com)で外部公開しています。
ところが、LINEアプリのLIFFコントローラーやスマホから同じURLでアクセスしようとすると、自宅Wi-Fiにつながっているときだけアクセスできないというトラブルが発生しました。
原因はDecoルーターがNATループバックに対応していないことで、DDNSドメインがグローバルIPに解決されてもルーター内で折り返せないためです。この問題をdnsmasqで根本的に解決しました。

家でも外でも同じURLでサーバーにつながってほしい!

実現したいこと

  • LAN内から外部公開ドメイン名(DDNSドメイン)でアクセスすると、自宅サーバーのLAN IPに直接つながるようにする
  • LAN内のすべてのデバイス(スマホ・PC・タブレット)が自動的に恩恵を受けられるようにする(個別設定不要)
  • 外部からのアクセスはこれまで通りDDNS経由でグローバルIPに接続できる状態を維持する
  • dnsmasqをサービスとして常時稼働させ、サーバー再起動後も自動的に起動する

この記事でわかること

  • NATループバック問題とDNSスプリットホライズンの仕組み
  • dnsmasqのインストールと基本設定方法
  • address= ディレクティブで特定ドメインのDNS解決を上書きする方法
  • Ubuntuでsystemd-resolvedとdnsmasqのポート競合を解決する方法
  • DecoルーターのDHCP設定でLAN内全デバイスへ自動配布する方法
  • 動作確認コマンド(nslookup / dig)の使い方

必要な準備と用意するもの

ハードウェア
  • 自宅サーバー(本記事ではNUCBox、Ubuntu搭載・有線LAN接続、固定IP: 192.168.68.89)
  • Wi-Fiルーター(本記事ではTP-Link Deco)
    • DHCPサーバーのカスタムDNS設定ができるものであればDecoでなくても可
ソフトウェア/サービス
  • Ubuntu(本記事の環境)
  • dnsmasq 2.90
    • 軽量なDNSキャッシュ&プロキシサーバー。aptで簡単にインストール可能
  • DDNS(本記事ではTP-Link DDNS: xxxx.tplinkdns.com
    • 外部に公開しているドメイン名。Deco経由でグローバルIPを自動更新
  • Nginxリバースプロキシ(自宅サーバー上で稼働中)

完成イメージ

設定完了後は、LAN内のスマホやPCから https://xxxx.tplinkdns.com/grafana/ などのURLにアクセスすると、DDNSサーバーを経由せず直接NUCBoxのLAN IP(192.168.68.89)に接続されます。外出先からのアクセスはこれまで通りDDNS→グローバルIP→ルーター→NUCBoxという経路で接続されます。

DecoのDHCPサーバー設定イメージ
DecoアプリでプライマリDNSをNUCBoxのLAN IP(192.168.68.89)に設定すると、LAN内の全デバイスへ自動配布されます。

DecoのDHCPサーバー設定 - プライマリDNSを192.168.68.89に設定
DecoのDHCPサーバー設定でプライマリDNSをNUCBox(192.168.68.89)に設定

システムの仕組み

NATループバック問題とは?

DDNSドメインは通常、ルーターのグローバルIPアドレスを指します。LAN内のデバイスがこのドメインにアクセスすると、DNSがグローバルIPを返し、そのグローバルIPへのパケットがルーターに届きます。ここで問題が起きます。

NATループバック非対応ルーターの場合
ルーターはLAN内のデバイスからグローバルIPへのパケットを受け取っても、それをLAN内のサーバーに転送する「折り返し(ヘアピン)」ができません。パケットが捨てられてタイムアウトになります。

DNSスプリットホライズンで解決

DNSスプリットホライズン(DNS Split-horizon)とは、アクセス元の場所(LAN内か外部か)によって、同じドメイン名に対するDNS応答を変える仕組みです。

今回の構成では:

  • LAN内のデバイス: NUCBox上のdnsmasqがDNS応答を担当 → xxxx.tplinkdns.com192.168.68.89(NUCBoxのLAN IP)に解決
  • LAN外のデバイス: 通常のDNS(Google DNS等)が担当 → xxxx.tplinkdns.com をグローバルIPに解決(変更なし)

LAN内は直接接続でレスポンスも速い!
LAN内はWAN経由を省略してNUCBoxに直結するため、レイテンシが低く安定した接続が得られます。外部公開のセキュリティ設定も維持したまま、LAN内からも同じURLで利用できます。

全体構成図


【LAN内からのアクセス(設定後)】
スマホ/PC (LAN内)
  │ DNS問い合わせ: xxxx.tplinkdns.com
  ▼
NUCBox dnsmasq (192.168.68.89:53)
  │ 応答: 192.168.68.89 (LAN IP)
  ▼
NUCBox Nginx (192.168.68.89:443)
  └─ /grafana/ → Grafana
  └─ /external/ → Flask API
       ✅ 直接LAN接続!

【外出先からのアクセス(変化なし)】
スマホ (外部)
  │ DNS問い合わせ: xxxx.tplinkdns.com
  ▼
Google DNS等
  │ 応答: グローバルIP
  ▼
Decoルーター → NUCBox Nginx
       ✅ DDNS経由で接続!

実装のポイント

① systemd-resolved との競合に注意

Ubuntuには標準で systemd-resolved というDNSサービスが搭載されており、ポート53を使用します。dnsmasqもポート53を使うため、両方が動いているとポート競合でdnsmasqが起動できません。

dnsmasqをインストールする前に、systemd-resolved を無効化する必要があります。無効化するとシステムのDNS解決はdnsmasqが引き継ぐため、server= で上位DNSサーバーを必ず設定してください。

② bind-interfaces でNICを絞る

bind-interfacesinterface=enp3s0 の組み合わせで、dnsmasqを有線NICのみにバインドします。これにより他のサービスとのポート競合リスクを減らし、セキュリティも向上します。

③ address= ディレクティブで特定ドメインを上書き

address=/xxxx.tplinkdns.com/192.168.68.89 の1行が核心です。このワイルドカード形式は、指定ドメインおよびすべてのサブドメインに対してDNS応答を上書きします。

④ DecoのDHCPでLAN全体に自動配布

DecoのDHCPサーバー設定でプライマリDNSをNUCBoxのIPに設定するだけで、LAN内の全デバイスへ自動配布されます。各デバイスへの個別設定は不要です。

事前準備

NUCBoxのIPアドレスを固定する

dnsmasqはDNSサーバーとして機能するため、NUCBoxのLAN IPが変わってしまうと全デバイスのDNS設定が機能しなくなります。Decoのアドレス予約機能、またはUbuntu側の静的IP設定でIPを固定してください。本記事では 192.168.68.89 を使用します。

ポート53の使用状況を確認する

sudo ss -tulnp | grep ':53'

systemd-resolved が起動している場合、127.0.0.53:53 でリッスンしているはずです。この場合は次の手順で無効化します。

実装方法

① systemd-resolved を無効化する

sudo systemctl disable systemd-resolved
sudo systemctl stop systemd-resolved

次に /etc/resolv.conf を直接書き換えます。systemd-resolvedが管理するシンボリックリンクになっている場合は一度削除して作り直します。

sudo rm /etc/resolv.conf
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf

この時点ではdnsmasqがまだ起動していないため、NUCBox自身のDNS解決にGoogle DNS(8.8.8.8)を一時的に使います。dnsmasqが起動した後はdnsmasq経由でDNS解決されます。

② dnsmasq をインストールする

sudo apt update
sudo apt install dnsmasq

インストール後にバージョンを確認します。

dnsmasq --version
# Dnsmasq version 2.90  Copyright (c) 2000-2024 Simon Kelley

③ dnsmasq.conf を設定する

/etc/dnsmasq.conf を編集します。既存のファイルにはコメントアウトされたサンプル設定が大量に記載されていますが、ファイルの末尾に下記を追記する(または有効な設定のみを残す)形で設定します。

sudo nano /etc/dnsmasq.conf

# ===== 基本設定 =====
port=53
domain-needed
bogus-priv

# ===== 外部DNS(上位フォワード先) =====
server=8.8.8.8
server=1.1.1.1

# ===== ローカルドメイン振り分け =====
address=/xxxx.tplinkdns.com/192.168.68.89

# ===== NICバインド設定 =====
bind-interfaces
interface=enp3s0

各設定項目の意味は以下の通りです。

設定項目説明
port=53標準DNSポート53でリッスン
domain-neededドットのない単純なホスト名はDNS転送しない(セキュリティ対策)
bogus-privプライベートIPの逆引きを外部に転送しない(セキュリティ対策)
server=8.8.8.8上位フォワード先DNS(Google DNS)。address= 対象外のドメインはこちらへ転送
address=/xxxx.tplinkdns.com/192.168.68.89このドメイン(とサブドメイン)のDNS応答を192.168.68.89に上書き
bind-interfaces指定したインターフェースにのみバインドする
interface=enp3s0有線LANのNIC名(環境に応じて変更)

NIC名の確認方法
ip link show コマンドで自分の環境のNIC名を確認してください。enp3s0eth0ens3 など環境によって異なります。

④ systemd の起動設定を最適化する(任意)

dnsmasqがネットワーク起動後に確実に起動するよう、systemd のドロップインファイルを作成します。

sudo mkdir -p /etc/systemd/system/dnsmasq.service.d
sudo nano /etc/systemd/system/dnsmasq.service.d/override.conf

[Unit]
After=network-online.target NetworkManager.service
Wants=network-online.target
StartLimitIntervalSec=0

[Service]
Restart=on-failure
RestartSec=3

network-online.target を待ってからdnsmasqを起動させることで、NIC(enp3s0)が確実に準備できた後にバインドできます。

⑤ dnsmasq を起動・自動起動を有効化する

sudo systemctl daemon-reload
sudo systemctl enable dnsmasq
sudo systemctl restart dnsmasq
sudo systemctl status dnsmasq

Active: active (running) と表示されれば起動成功です。

⑥ DecoルーターのDHCPサーバーを設定する

最後に、LAN内の全デバイスがNUCBoxをDNSサーバーとして使うよう、DecoのDHCPサーバー設定を変更します。DecoアプリのホームネットワークからDecoの詳細設定画面を開きます。

ホームネットワーク画面で「詳細」をタップ

詳細設定から「DHCPサーバー」を選択します。

詳細設定メニューから「DHCPサーバー」をタップ

DHCPサーバーの設定画面で「プライマリ DNS」にNUCBoxのLAN IP(192.168.68.89)を入力して保存します。

プライマリ DNS に NUCBox の IP アドレス(192.168.68.89)を入力

設定保存後、LAN内のデバイスは次回のDHCPリース更新時(または再接続時)に新しいDNS設定を受け取ります。すぐに反映させたい場合はWi-Fiをオフ/オンするか、デバイスを再起動してください。

動作確認

① NUCBox上でdnsmasqの応答を確認

まずNUCBox自身からdnsmasqに問い合わせて、正しいIPが返るか確認します。

nslookup xxxx.tplinkdns.com 192.168.68.89

Server:         192.168.68.89
Address:        192.168.68.89#53

Name:   xxxx.tplinkdns.com
Address: 192.168.68.89

Address: 192.168.68.89 ならOK!
グローバルIPではなく、NUCBoxのLAN IP(192.168.68.89)が返ってくれば正しく動作しています。

② LAN内デバイス(スマホ等)から確認

DecoのDHCPリース更新後、LAN内のデバイスから nslookup または dig で確認します。

# digコマンドで確認(LAN内のPCから)
dig xxxx.tplinkdns.com

# 応答のSERVERが192.168.68.89を指していれば成功
# ;; SERVER: 192.168.68.89#53(192.168.68.89)

③ ブラウザからアクセスして確認

LAN内のデバイスのブラウザで https://xxxx.tplinkdns.com/grafana/ などにアクセスし、正常に表示されることを確認します。表示が速ければWAN経由ではなくLAN直結で通信できている証拠です。

うまくいかない場合のチェックリスト
・dnsmasqが起動しているか: sudo systemctl status dnsmasq
・ポート53でdnsmasqがリッスンしているか: sudo ss -tulnp | grep ':53'
・デバイスのDNS設定が192.168.68.89になっているか: Wi-Fiの接続情報を確認
・UFW等のファイアウォールでポート53(UDP/TCP)が開いているか: sudo ufw status

④ ファイアウォールでポート53を開放する(必要な場合)

UFWが有効な場合、LAN内からのDNSポート(53番)へのアクセスを許可します。

sudo ufw allow from 192.168.68.0/24 to any port 53
sudo ufw reload

まとめ

dnsmasqの address= ディレクティブとDecoのDHCPサーバー設定を組み合わせることで、LAN内から外部公開ドメインで自宅サーバーに直接アクセスできるようになりました。

まとめ
  • NATループバック非対応ルーターでも、dnsmasqによるDNSスプリットホライズンで解決できる
  • address=/xxxx.tplinkdns.com/192.168.68.89 の1行でLAN内のDNS解決を上書きできる
  • DecoのDHCPサーバーでプライマリDNSをNUCBoxに設定するだけで全デバイスに自動配布される
  • 外部からのアクセスは変更なし。LAN内・外で同じURLが使えるようになる
  • dnsmasqはsystemdサービスとして自動起動するため、サーバー再起動後も維持される

この設定により、LIFFアプリやGrafanaダッシュボードへのアクセスが自宅内・外出先どちらからでも同じURLで動作するようになり、スマートホームシステムの利便性が大きく向上しました。

タイトルとURLをコピーしました