0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Tailscaleで自前のDNSと独自ドメインでのHTTPSでの接続を実現する

Last updated at Posted at 2025-01-17

はじめに

最近、外出先から自宅サーバーへとSSHを繋ぎたいことがあってTailscale VPNを導入しましたのですが、せっかくプライベートなネットワークなので自宅のサーバーに常駐するセルフホストのサービスを立ててみました。

しかし、残念なことにポート番号が覚えづらくてならない。

べつにVPNの中なのでわざわざドメインにIPを紐付けなくとも同じIPですし、なんならTailscaleの場合はマシンごとに勝手にドメインを割り当ててくれる(MagicDNS)のでDNSなんてわざわざ建てる必要ないな、なんて思っていたのですが、私の脳ではたった3つ程度のセルフホストのサービスのポート番号すら間違えてしまいます。

そんなわけで、先人たちに倣って私も自前のDNSを建てることにしました。

前提条件

  • Ubuntu 24.04を利用しています
  • 自前の使い道のないドメインを持っている前提です
  • この方法ではドメインのネームサーバーはCloudflareである必要があります

(Cloudflareでドメインを管理していない場合は移管するなりLet's encryptのチャレンジを解決する用のサーバーを建てるなりしてもらう必要があります…)

自前のDNSを立てて、TailscaleのDNSに参照させる

Split DNSの設定

まず、TailscaleのDNSには、Split DNSという便利な機能があります。これは、特定のドメインにアクセスする場合にのみ、特定のDNSを使用して名前解決を図る仕組みです。

ここでは、利用するドメインをexample.comと仮定します。

Tailscaleにアクセスした後、DNSのタブのNameserversにあるAdd nameserverをクリックします。その後、選択肢の中でCustomを選択すると設定できます。この際、Restrict to domain のトグルをONにしてSplit DNSの機能を利用するようにしてください。

まず、ここにDNSを運用するサーバーのVPN上でのIPアドレスと、利用するドメインを登録しておきましょう。

sytemd-resolvedと利用するポートが被る問題を解消

まず、Ubuntuの場合、DNSに利用したい53番ポートはsystemd-resolvedによって使用されています。これは、名前解決のキャッシュや.localでアクセスできるようなローカルネットワークのデバイスIPの名前解決を行ってくれる便利な機能なのですが、今回に限ってはこれの一部機能をOFFにする必要があります。本来であればNameserverのポート番号を指定できれば良い話ですが、残念ながらTailscaleではできないようです。

53番ポートを利用するために、systemd-resolvedのコンフィグを編集しましょう。

sudo bash -c "echo 'DNSStubListener=no' >> /etc/systemd/resolved.conf"
sudo systemctl restart systemd-resolved

DNSサーバーを建てる

つぎに適当なDNSサーバーを立てます。設定が簡単なのはdnsmasqとかだと思います。

sudo apt update
sudo apt install dnsmasq
sudo bash -c "echo 'address=/sample.example.com/xxx.xxx.xxx.xxx' >> /etc/dnsmasq.conf"
sudo systemctl restart dnsmasq

おそらくこれで、dnsmasqが53番で動作していると思います。

動作確認

TailscaleでSplit DNSが機能し、dnsmasqを動作させコンフィグが適切に設定されていれば、これで名前の解決は可能になったはずです。試しに、digコマンドで確認してみましょう。

dig @127.0.0.1 sample.example.com #自分のサーバーで動いているDNS
dig @100.100.100.100 sample.example.com #tailscaleのDNS
dig sample.example.com #現在利用しているDNS

適切に設定されていれば、それぞれのコマンドで同じIPに辿り着くはずです。

nginxとかで適当に振り分ける

例えば、セルフホストのサービスがlocalhost:8080で動作している場合は、以下のようになります。

/etc/nginx/sites-available/sample.example.com
server {
    listen 80;
    server_name sample.example.com;

    location / {
        proxy_pass http://localhost:8080;
    }
}

設定後は以下のようにしてコンフィグを有効にします。

ln -s /etc/nginx/sites-available/sample.example.com /etc/nginx/sites-enabled
sudo nginx -t #コンフィグが正しいか確認
sudo systemctl restart nginx

HTTPSで接続できるようにする

そもそもいる?

セルフホストの、さらにVPNの中で動いているサービスを、わざわざHTTPSにする必要があるのかと疑問に思うかもしれません。
まあ、ぶっちゃけ必要ないのですが、普段使っているブラウザで危険なサイトとして扱われたりしてアクセスするのが面倒だったりします。それを回避するための手段と思ってもらってたら良いかもしれません。

Let's encryptで署名付き証明書を手にいれる

HTTPSで通信するためには、適切に署名された証明書を手に入れる必要があります。しかしながら、これはあくまでVPNのサーバー。外界からは遮断され、よくある方法でDNSの所有権を証明することはできません。

そこで、ドメインのテキストレコードをプラグインで自動的に編集する方法をとります。一度証明書を取得するだけであれば手動で問題ないのですが、let's encryptの証明書の有効期限は三ヶ月です。三ヶ月ごとに毎回作業をするのはダルいので、今回は出回っているプラグインを利用する方法をとります。

sudo apt update
sudo apt install certbot python3-certbot-dns-cloudflare
mkdir -p ~/.secrets/certbot
touch ~/.secrets/certbot/cloudflare.ini
chmod 600 ~/.secrets/certbot/cloudflare.ini

最後に作成した~/.secrets/certbot/cloudflare.iniにはCloudflareのサイトで取得したAPIトークンを登録します。このAPIのトークンはDNSレコードの編集権限を持つだけのものが良いかと思います。

cloudflare.ini
dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN

さて、これでコマンドを実行できるようになるはずです。

sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials ~/.secrets/certbot/cloudflare.ini \
  -d example.com \
  -d *.example.com

ワイルドカードを利用して取得することで証明書取得の手間が省けますが、気になる場合は個別に取得していただいて構いません。

自動更新の設定をする

/etc/systemd/system/certbot-renew.service
[Unit]
Description=Certbot Renewal
Documentation=https://certbot.eff.org/
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/bin/certbot renew --quiet --deploy-hook "/bin/systemctl reload nginx"

[Install]
WantedBy=multi-user.target
/etc/systemd/system/certbot-renew.timer
[Unit]
Description=Run Certbot renewal every day

[Timer]
OnCalendar=*-*-1 00:00:00
Persistent=true

[Install]
WantedBy=timers.target

以下のように登録します。

sudo systemctl daemon-reload
sudo systemctl enable certbot-renew.timer
sudo systemctl start certbot-renew.timer

これで、毎月1日に証明書の自動更新と、それに付随するnginxの再起動が行われます。

nginxの設定を変更する

/etc/nginx/sites-available/sample.example.com
server {
    listen 80;
    server_name sample.example.com;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name sample.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    location / {
        proxy_pass http://localhost:8080;
    }
}

書き換え後にnginxを再起動します。

sudo nginx -t
sudo systemct restart nginx

これで https://sample.example.com にアクセスすると、セルフホスト運用しているサービスへとアクセスできるはずです。

最後に

セルフホストのサービスの中で、特におすすめなのがminifluxです。マジでおすすめです。CSS改造すると、マジでいいですよ。皆さんもぜひ、自宅サーバーライフのご満喫を。

参考

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?