なんのこっちゃという感じだが、自宅サーバのWebサイトに対してドメインでアクセスしてしまうと、LAN内になるのにインターネット経由になってしまう。それはなんだか阿呆みたいなので、LAN内からはLANでつなげたい。
つまりこういうことです。
graph TD
subgraph "インターネット (外からの道)"
A["スマホ (4G/5G)"] --> B["Cloudflare (中継)"]
B --> C["トンネル (暗号化)"]
end
subgraph "家の中 (LAN内の道)"
D["PC / スマホ (Wi-Fi)"] --> E["AdGuard Home (近道の案内板)"]
end
C --> F["Caddy (玄関口)"]
E -->|"近道 (爆速)"| F
F --> G["WordPress / 自分のアプリ"]
style E fill:#f96,stroke:#333,stroke-width:2px
style F fill:#f9f,stroke:#333,stroke-width:2px
style G fill:#bbf,stroke:#333,stroke-width:2px
同じドメインで、LANとインターネットで別々のルートにする。LAN内ではLAN内DNSを使って名前解決する、ってことだね。これによって、LAN内のアプリにhttps://app.example.comでインターネットを使わずにアクセスできるようになる。
IPアドレス直打ちやTailscaleのMagicDNSとかじゃあかんのか?という向きもあると思うが、WordPressなどはサイトドメインにリダイレクトする仕様があったりするためそうもいかないし、そもそもLANとインターネットで2つのブックマークを作るというのは、なんだかつらいものがある。
ということで、色々頑張った結果、なんかLinux Mint Xfce + Caddy(+Cloudflare) + Tailscale + AdguardHome という構成になって1日かかってしまったんだが、正直ここまで頑張らなくてももっとシンプルにやれる。
目次
構成
基本の構成
順番に考えていこう。外からの通信はみんな大好きCloudflare Tunnel から直通でOK。問題は、LAN内だね。
まずは、LAN内DNSを作って、ルータでそこに向ける。これにAdGuard Homeを使う。AdGuardHomeで特定のドメインを、リバースプロキシのCaddyに向ける。考え方の基本はこれだけ。
graph TD
subgraph "インターネット (外からの道)"
User_Ext["ユーザー"]
Tunnel["Cloudflare Tunnel<br/>(cloudflared)"]
end
subgraph "LAN内 (秘密の近道)"
User_Int["自分 (Wi-Fi)"]
AGH["AdGuard Home<br/>(案内板: DNS書き換え)"]
Caddy["Caddy<br/>(玄関: HTTPSプロキシ)"]
end
subgraph "アプリ群"
App["WordPress / AIアプリ 等"]
end
%% 外のルート (Caddyをバイパス)
User_Ext --> Tunnel
Tunnel -->|"直接ポートを指定"| App
%% 内のルート (Caddyを経由)
User_Int -.->|"① 案内を聞く"| AGH
AGH -.->|"② CaddyのIPを回答"| User_Int
User_Int -->|"③ HTTPSでアクセス"| Caddy
Caddy -->|"④ アプリへ転送"| App
style AGH fill:#f96,stroke:#333
style Caddy fill:#f9f,stroke:#333
style Tunnel fill:#fff,stroke:#333
style App fill:#bbf,stroke:#333
これが基本なので、単にスプリットDNSしたいだけならこれでよい。というか、個人的にはこれで十分だと思う。なんかAIにのせられてゴチャゴチャとやってしまったが、正直それで思ったのは「いらねぇ」だった。
ここから、ちゃんとした証明書の発行と、仮想ネットワークを混ぜるとたいへんになる。色々と肉付けをしていくと複雑になる。
証明書(諸悪の根源)
ちゃんとした証明書というのは、つまりオレオレ証明書ではないということだ。これがあることで、ブラウザからは完全なるお許しを得られるので、なんかマルウェアサイト扱いされたり安全ではない云々などの小言を挟まれてイライラすることはなくなく。
証明書の発行をCaddyは本来サラッとこれをやってくれるのだが、今回はLAN内であるために、必要な80/443を使えない。
ここで、Cloudflareを利用すれば、API使ってゾーン編集して一時的にTXTレコードを作るなどして、証明書の発行ができるプラグインを活用する(DNS-01チャレンジ)。これによって、LAN内であるにも関わらずオレオレではない証明書ができるので、これにはブラウザもニッコリ。警告が消えるよ!やったね、Googleさん。
と、ブラウザはニッコリなのだが僕はかなりイライラしている。やっていることはほとんど形式的で実際的な意味はない。ついでにCloudflareに依存してしまっている…いやこれは別のプロバイダ用のプラグインもあるので、置き換えはできるんだけど。できるけどなんでこんな大掛かりなことに。
まぁ、とりあえずここまでを図示しよう。
graph TD
subgraph Internet ["インターネット (外からの道)"]
User_Ext["ユーザー"]
Tunnel["Cloudflare Tunnel<br/>(cloudflared)"]
end
subgraph LAN ["LAN内 (秘密の近道)"]
User_Int["自分 (Wi-Fi)"]
AGH["AdGuard Home<br/>(DNS書き換え)"]
Caddy["Caddy<br/>(証明書管理 & プロキシ)"]
end
subgraph Cloudflare_Control ["Cloudflare管理下 (DNS-01)"]
CF_API["Cloudflare API"]
DNS_Rec["TXTレコード (一時的な合言葉)"]
end
subgraph CA ["証明書発行機関 (Let's Encrypt等)"]
Verify["レコードの正当性検証"]
end
subgraph App_Server ["アプリ"]
App["WordPress / 各種アプリ"]
end
%% 外のルート
User_Ext --> Tunnel
Tunnel -->|"直接ポートを指定"| App
%% 内のルート
User_Int -.->|"① ドメインのIPを問い合わせ"| AGH
AGH -.->|"② CaddyのLAN内IPを回答"| User_Int
User_Int -->|"③ HTTPSアクセス (警告なし)"| Caddy
Caddy -->|"④ アプリへ転送"| App
%% 証明書発行 (DNS-01) のプロセス
Caddy <-->|"⑤ APIトークンで認証"| CF_API
CF_API -- "⑥ 証明用のレコードを設置" --> DNS_Rec
DNS_Rec -. "⑦ 外部から合言葉を確認" .-> Verify
Verify -- "⑧ 証明書を発行" --> Caddy
style AGH fill:#f96,stroke:#333
style Caddy fill:#f9f,stroke:#333
style Tunnel fill:#fff,stroke:#333
style App fill:#bbf,stroke:#333
style CF_API fill:#9cf,stroke:#333
2010年代以降、インターネットは同じことをどれだけ複雑にやれるか選手権が全世界で開催されたため、その煽りを受けた格好だ。
単に複雑なだけではなく、これはむしろ脆弱になっていないかと思う。Cloudflare(等のプロバイダ)に依存するために、攻撃対象が純粋に増えている。何してるんだ俺は。俺が俺の作ったアプリを俺のLAN内で使うのに、Cloudflareという第三者をとおすほうがセキュアであるというのはどういう理屈なんだ?そんなに俺は俺が信用できないのか?どうなんだ俺?
俺ではなく今のインターネットの問題である。というか根本的にLAN内で完結することのはずなのに、少なくとも証明書の更新時にインターネット接続が必要になっており、オフラインになると維持できない仕組みだ。まぁさすがに前提条件を考えるとインターネットの維持まで疑っても仕方ないかもしれないが、しかし必要もなくインターネットの外に出ることのどこがセキュリティだというのか。
まぁ一応、なにかあったら仕組みを止めれば良いので、最低限のラインは超えていて依存とは言い切れない、くらいに考えてはいるが、いったいマジで何をやっているんだという気持ちが強い。そもそもCloudflare Tunnel使っとるやないかいと言われそうだが、これは単に玄関で、いざとなればVPS + frpなどで即座に別の玄関に変えることは可能(後述するTailscaleがあればそれも使える)だし、実際似たようなことを以前のConoHa大規模障害時にやったこともあるので、依存ではないと考えている。だがAPIを使った証明書発行と更新というのはなぁ…。
Tailscaleの追加
ここまででもかなり嫌になるが、なんか別の用途があったりしてTailscaleなど使っていると、構成はさらに複雑になる。TailscaleのDNSをAdGuard Homeに向ける必要があるからだ。また、MagicDNSを使えるのはよいのだが、それゆえのハマり要素もある。
結果、最終的に以下の構図になる。インターネット経由の経路と、Tialscaleのネットワーク経由でAdGuard HomeとCaddyを使う経路ができるわけだ。
graph TD
subgraph Internet ["1. インターネット (外からの道)"]
User_Ext["ユーザー"]
Tunnel["Cloudflare Tunnel<br/>(cloudflared)"]
end
subgraph Tailscale_Mesh ["2. Tailscale Mesh (仮想ネットワーク)"]
direction TB
TS_DNS["Tailscale DNS / MagicDNS<br/>(Nameserver: AdGuard IP)"]
User_Int["自分 (PC/スマホ)<br/>Tailscale ON"]
end
subgraph Linux_Server ["3. Linux Server (cimon)"]
direction TB
AGH["AdGuard Home<br/>(DNS書き換え実行)"]
subgraph Docker ["Docker"]
Caddy["Caddy<br/>(HTTPSプロキシ / 証明書管理)"]
end
end
subgraph Mac_Mini ["4. 別マシン (mac-mini)"]
App_Remote["WordPress / AIアプリ"]
end
subgraph Cloudflare_CA ["5. Cloudflare & CA"]
CF_API["Cloudflare API"]
LE["Let's Encrypt"]
end
%% 外のルート
User_Ext --> Tunnel
Tunnel -->|"直接ポート指定"| App_Remote
%% 内のDNSフロー
User_Int -.->|"① DNS問い合わせ"| TS_DNS
TS_DNS -.->|"② 名前解決を丸投げ"| AGH
AGH -.->|"③ CaddyのIPを回答"| User_Int
%% 内の通信フロー
User_Int -->|"④ HTTPSアクセス"| Caddy
%% Caddyからの転送 (MagicDNS vs IP)
Caddy -->|"⑤ Proxy via MagicDNS"| App_Remote
Caddy -.->|"⑤ Proxy via Local IP<br/>(自分自身のループバック回避)"| AGH
%% 証明書取得 (DNS-01)
Caddy <-->|"⑥ TXTレコード操作"| CF_API
CF_API <-->|"⑦ 検証"| LE
style AGH fill:#f96,stroke:#333,stroke-width:2px
style Caddy fill:#f9f,stroke:#333,stroke-width:2px
style TS_DNS fill:#9cf,stroke:#333,stroke-width:1px
style Tunnel fill:#fff,stroke:#333,stroke-width:1px
これにより以下の3つの経路が並立している。
- インターネット経路
- Tailscale経路
- LAN内IP直打ち経路
正直どうかと思う。
しかし、先の証明書と違い、こちらのTailscaleは仮想ネットワークの構築という明確な役割があるため、別用途で必須となっているのであれば、これはやらざるを得ない。
所感:そもそもやるべきか?
ここまで少しずつ段階を書いたのは、納得できる範囲でやるべきだからだ。全部盛りでやってしまうと、どっかぶっ壊れたときにどうしていいかわからなくなる。そもそも、本質的に必要のないことはやるべきではない。
まぁしゃあないので毒を喰らわば皿までで、第三者に自宅の経路を保証してもらうという謎の苦行まではするとして、個人的にはAdGuard Home + Caddyでいいと思う。ブラウザの警告も気にしないならDNS-01チャレンジもいらん。でもここまできたら全部やってもいんじゃね感。普通につかえるとストレスフリーなのはまぁそう。
が、これと別にTailscaleを導入している場合、考えるところが増える。Tailscaleが入ると、そこで名前解決があるので、*.ts.netでいいなら、実はAGHはいらない。ただ今回は外からのドメインを使うという要件があるため、AGH + Tailscale + Caddyというカオスになるのだが…。
そもそもスプリットDNSなんてやらないほうがよかった説も有力である。IPアドレス直打ちはしんどくね問題はあるが、それだけならMagicDNS使ったっていいし。警告なんて知らねぇっていってもいいし。気分の問題の側面が大きい。まぁWordPressのようにサイトドメインの概念があると、ドメインは固定になってしまうため、、同一ドメインで別経路を取るのは価値があるのだが、そこまでして…とも思える。
じゃあなぜお前はやったのか?AIに相談してたらなんかこうなってしまった。AIというやつはそうなるんだ。ベストプラクティスのツギハギをして、本来必要だったものから遠ざかっていく。途中で「絶対こんなのは必要ない」と思ったが、エラーが出ているのは腹立たしいので最後までやってしまった。
自宅サーバってレベルじゃねぇぞ、などという気もしつつ、この記事は、どこが分岐点だったのか?をまとめたものに近い。そういう意味じゃよく理解できたと言えるかもしれないが、疲れた…。AIが過剰に重視してしまう指標と、無視しがちな指標が存在するんだね。 それらの指標は、現実上の重要性とたいてい一致しない。 これは「AI」を「社会」や「組織」に置き換えても成り立つんだな。
まぁでも、僕の性格を考えるとどうせそのうち手を付けた気はする。ブラウザの警告うぜぇとなって、しかしTailscaleのドメインに依存するやり方はいやだろうし、結局スプリットDNS構成になったんじゃないかなぁ…。じゃあいいのか…。と、ここまで書いただけでなんかもうお腹いっぱいなので今回は構成のみ。具体的な手順は次の記事で。
<関連記事>
あわせて読みたい
VPS + Caddy + WordPress を構成する さようならCloudflare Tunnel
脱Cloudflare Tunnel計画で、VPSで入れているCloudflareをCaddyに置き換えようとしている。 前提 構成 構成はこんな感じ。なんか最近AIが秒で書いてくれて地味に助かる...
あわせて読みたい
やらなくていいことばかりしている
色々と疲れてしまったのかなとも思うんだが、僕が社会に出てから15年ばかり、なんだか、自分も周りも、碌でもないことしかしてこなかった気がする。 とても狭い話だけれ...
コメント