🤖

ローカルDNSやらなんやらを構築してみた

に公開

留意事項

  • コードが長い場合、折りたたみ要素?を使用しています。
    不便・嫌などと感じた方は、コメントお願いします。
  • 初心者のため、あまり良くない書き方があると思います。
    その点、ご留意願います。

TL;DR (概要)

ごっちゃごちゃのネットワークだったから、整理しようと考えたらいつのまにかちょっと大掛かりな構造になってしまった...
それをメモしておきます。

最終ネットワーク構成図

alt text

検証環境

この記事用にVagrantで仮想環境を整えました。
GUI端末である、MainPCのセットアップ方法はこちらの記事を書きましたので、良ければ見てみてください。

Vagrantfile
Vagrant.configure("2") do |config|

  # VPS(独立したネットワーク)
  config.vm.define "vps" do |vps|
    vps.vm.box = "debian/bookworm64"
    vps.vm.hostname = "vps"

    # VPSは独立したネットワーク(インターネット想定)
    vps.vm.network :public_network, bridge: "enp42s0", ip: "192.168.0.57" # ホストのネットワークインターフェースに合わせて変更すること

    vps.vm.provider "virtualbox" do |vb|
      vb.name = "VPS"
      vb.cpus = 4
      vb.memory = "4096"
    end

    vps.vm.provision "shell", inline: <<-SHELL
      #!/usr/bin/env bash
      set -euo pipefail

      echo "nameserver 1.1.1.1" > /etc/resolv.conf

      rm -f /etc/apt/sources.list.d/docker.list /etc/apt/sources.list.d/docker.list.save
      rm -f /etc/apt/trusted.gpg.d/docker.gpg
      mkdir -p /etc/apt/keyrings

      apt-get update -y && apt-get upgrade -y
      apt-get install -y curl ca-certificates gnupg lsb-release systemd-resolved vim gzip rsync

  install -d -m 0755 /etc/systemd
  cat > /etc/systemd/resolved.conf << "CONF"
[Resolve]
DNS=1.1.1.1 8.8.8.8
FallbackDNS=9.9.9.9
DNSStubListener=yes
# Cache=yes         # デフォルトで有効。明示したいならコメント解除
# DNSSEC=no         # 環境により yes/allow-downgrade/no を選択
CONF

      rm -rf /etc/resolv.conf
      ln -s /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
      systemctl enable systemd-resolved --now
      systemctl restart systemd-resolved

      # 5) 動作確認(失敗してもスクリプト全体は止めない)
      resolvectl status || true
      resolvectl query google.com || true
      dig +time=2 +tries=1 @127.0.0.53 google.com || true  
    SHELL
  end

  # メインPC(ArchLinux、プライベートネットワーク+デスクトップ対応)
  config.vm.define "mainpc" do |mainpc|
    mainpc.vm.box = "terrywang/archlinux"
    mainpc.vm.hostname = "main-pc"

    mainpc.vm.network :public_network, bridge: "enp42s0"
    # 同一セグメントで固定IP
    mainpc.vm.network :private_network, ip: "192.168.56.10"

    mainpc.vm.provider "virtualbox" do |vb|
      vb.name = "MainPC"
      vb.cpus = 4
      vb.memory = "4096"
      vb.gui = true
      # VirtualBoxの表示/3D/VRAM設定は customize で行う
      vb.customize ["modifyvm", :id, "--graphicscontroller", "vmsvga"]
      vb.customize ["modifyvm", :id, "--accelerate3d", "on"]
      vb.customize ["modifyvm", :id, "--ioapic", "on"]
      vb.customize ["modifyvm", :id, "--vram", "128"]
      vb.customize ["modifyvm", :id, "--clipboard", "bidirectional"]
    end

    mainpc.vm.provision "shell", inline: <<-SHELL
      # エラー時に停止する用の、セーフティコマンド
      set -eux

      # 時刻同期
      timedatectl set-ntp true

      # キー更新
      pacman -Syy
    SHELL
  end


  # Debian-Server
  config.vm.define "debian-server" do |debian|
    debian.vm.box = "debian/bookworm64"
    debian.vm.hostname = "debian-server"

    debian.vm.network :public_network, bridge: "enp42s0"
    debian.vm.network :private_network, ip: "192.168.56.20"

    debian.vm.provider "virtualbox" do |vb|
      vb.name = "debian-server"
      vb.cpus = 4
      vb.memory = "4096"
    end

    debian.vm.provision "shell", inline: <<-SHELL
      #!/usr/bin/env bash
      set -euo pipefail

      echo "nameserver 1.1.1.1" > /etc/resolv.conf

      rm -f /etc/apt/sources.list.d/docker.list /etc/apt/sources.list.d/docker.list.save
      rm -f /etc/apt/trusted.gpg.d/docker.gpg
      mkdir -p /etc/apt/keyrings

      apt-get update -y && apt-get upgrade -y
      apt-get install -y curl ca-certificates gnupg lsb-release systemd-resolved vim gzip

  install -d -m 0755 /etc/systemd
  cat > /etc/systemd/resolved.conf << "CONF"
[Resolve]
DNS=1.1.1.1 8.8.8.8
FallbackDNS=9.9.9.9
DNSStubListener=yes
# Cache=yes         # デフォルトで有効。明示したいならコメント解除
# DNSSEC=no         # 環境により yes/allow-downgrade/no を選択
CONF

      rm -rf /etc/resolv.conf
      ln -s /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
      systemctl enable systemd-resolved --now
      systemctl restart systemd-resolved

      # 5) 動作確認(失敗してもスクリプト全体は止めない)
      resolvectl status || true
      resolvectl query google.com || true
      dig +time=2 +tries=1 @127.0.0.53 google.com || true  
    SHELL
  end
end

構築準備(CUI端末)

  1. カレントディレクトリを確認
pwd
#/home/vagrant
  1. /var/serverFilesを作成
sudo mkdir -p /var/serverFiles && \
sudo chown vagrant:vagrant /var/serverFiles && \
sudo chmod 755 /var/serverFiles
  1. /var/serverFilesをユーザフォルダへ、シンボリックリンクを作成
cd ~ && ln -s /var/serverFiles serverFiles
  1. dockerインストール
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

構築順序

以下の順番で、構築していきます。

  1. ローカルDNS(technitium/dns-server)
  2. Step-ca (smallstep/step-ca)
  3. Root配布
  4. Caddy (caddy)
  5. WireGuard(WireGuard-UI)

理由

なぜ DNS を最初に構築するか
最初にドメイン名を決めておくと、証明書・VPN・リバースプロキシの設定を全部その名前で統一でき、後から直す手間が減る。

手順

ローカルDNSを構築

DNSをインストール&構築

  1. DNS用のフォルダを作成
cd ~ && mkdir -p serverFiles/dns
  1. vimcompose.yamlを作成し編集する
cd ~/serverFiles/dns && \
vim compose.yaml
  1. DockerComposeを書く (コピペは、ctrl + shift + v)
compose.yaml
version: "3"
services:
  dns-server:
    container_name: dns-server
    hostname: dns-server
    image: docker.io/technitium/dns-server:latest
    ports:
      - "5380:5380/tcp" #DNS web console (HTTP)
      - "53443:53443/tcp" #DNS web console (HTTPS)
      - "53:53/udp" #DNS service
      - "53:53/tcp" #DNS service 
    environment:
      - DNS_SERVER_DOMAIN=home.lan #The primary domain name used by this DNS Server to identify itself.
      - DNS_SERVER_ADMIN_PASSWORD=password #DNS web console admin user password.
      - DNS_SERVER_WEB_SERVICE_ENABLE_HTTPS=true
      - DNS_SERVER_WEB_SERVICE_USE_SELF_SIGNED_CERT=true
      
      # ネットワーク制御
      - DNS_SERVER_RECURSION=AllowOnlyForPrivateNetworks
      - DNS_SERVER_RECURSION_ALLOWED_NETWORKS=127.0.0.1,192.168.0.0/24
      
      # フォワーダー
      - DNS_SERVER_FORWARDERS=1.1.1.1,1.0.0.1
      - DNS_SERVER_FORWARDER_PROTOCOL=Https
      
      # ログ
      - DNS_SERVER_LOG_USING_LOCAL_TIME=true
    volumes:
      - ./config:/etc/dns
    restart: unless-stopped
  1. とりあえず立ち上げてみる
sudo docker compose up -d
  1. ブラウザでHTTP GUIにアクセスしてみる
    http://192.168.56.20:5380/

alt text

ログインできました〜!
alt text


ドメイン登録をしてみる

  1. DNSに、ドメインを登録してみる
    上のタブの、Zones Add Zone を押す

alt text

そうすると、下のようなモーダルが表示され、Zone の欄に任意のドメインを書き、Addを押す。
今回は、home.lanとする。

alt text

上に、画像のような通知バーが出ればOK!

alt text

  1. Aレコードを追加
    この画面で、Add Recordと書かれている、ボタンを押す。

alt text

そうすると、下のようなモーダルが表示されたら、IPv4 Address欄に、192.168.56.20と入力する。
Saveを押す

alt text

  1. 疎通確認
ping -c 3 home.lan

こんな感じに出れば、OK!

vagrant@debian-server:~/serverFiles/dns$ ping -c 3 home.lan
PING home.lan (192.168.56.20) 56(84) bytes of data.
64 bytes from debian-server (192.168.56.20): icmp_seq=1 ttl=64 time=0.029 ms
64 bytes from debian-server (192.168.56.20): icmp_seq=2 ttl=64 time=0.046 ms
64 bytes from debian-server (192.168.56.20): icmp_seq=3 ttl=64 time=0.054 ms

--- home.lan ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2041ms
rtt min/avg/max/mdev = 0.029/0.043/0.054/0.010 ms
  1. CNAMEに、dnscaを追加

Name:dns
Domain Name:home.lan

(dnsの設定)
alt text

これで、dns.home.lanを作成できました。
同じ用に、ca.home.lanも作成しましょう。

疎通確認

ping -c 3 dns.home.lan
ping -c 3 ca.home.lan

こんな感じで、出力されればOK!

vagrant@debian-server:~$ ping -c 3 dns.home.lan
ping -c 3 ca.home.lan
PING home.lan (192.168.56.20) 56(84) bytes of data.
64 bytes from debian-server (192.168.56.20): icmp_seq=1 ttl=64 time=0.030 ms
64 bytes from debian-server (192.168.56.20): icmp_seq=2 ttl=64 time=0.070 ms
64 bytes from debian-server (192.168.56.20): icmp_seq=3 ttl=64 time=0.041 ms

--- home.lan ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2060ms
rtt min/avg/max/mdev = 0.030/0.047/0.070/0.016 ms
PING home.lan (192.168.56.20) 56(84) bytes of data.
64 bytes from debian-server (192.168.56.20): icmp_seq=1 ttl=64 time=0.019 ms
64 bytes from debian-server (192.168.56.20): icmp_seq=2 ttl=64 time=0.052 ms
64 bytes from debian-server (192.168.56.20): icmp_seq=3 ttl=64 time=0.052 ms

--- home.lan ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2045ms
rtt min/avg/max/mdev = 0.019/0.041/0.052/0.015 ms

ACME認証サーバーの構築

ACMEサーバーの構築

  1. フォルダを作成
cd ~ && mkdir -p ~/serverFiles/stepca/step && cd ~/serverFiles/stepca && vim compose.yaml
  1. compose.yamlを書く
compose.yaml
services:
    stepca:
        image: docker.io/smallstep/step-ca
        volumes:
            - "./step:/home/step"
        environment:
            DOCKER_STEPCA_INIT_NAME: "HOME CA"
            DOCKER_STEPCA_INIT_DNS_NAMES: "192.168.56.20,home.lan"
        dns:
            - "192.168.56.20"
        ports:
            - "9000:9000"
  1. 起動して、ログを確認
sudo docker compose up -d && sudo docker compose logs

ログの中から、下のようなパスワード部分を探してメモしておく

(例)
stepca-1  | 👉 Your CA administrative password is: TDmFTSCBYsoKk5LaTN65ZyKbCuH4gFAksNpPVZpk
stepca-1  | 🤫 This will only be displayed once.

これは、adminのパスワード
変更方法はわからない... すみません💦

内部での利用なので、変更しなくてもいい気がする

全体ログ
vagrant@debian-server:~/serverFiles/stepca$ sudo docker compose logs
stepca-1  | /entrypoint.sh: line 56: /home/step/password: Permission denied
stepca-1  | /entrypoint.sh: line 56: /home/step/password: Permission denied
stepca-1  |
stepca-1  | Generating root certificate... done!
stepca-1  | Generating intermediate certificate... done!
stepca-1  |
stepca-1  | ✔ Root certificate: /home/step/certs/root_ca.crt
stepca-1  | ✔ Root private key: /home/step/secrets/root_ca_key
stepca-1  | ✔ Root fingerprint: 9eb1dc2acfb4b842c8e1ff7bf5ec2e601fbaeec57b0ff3ca751670c55365f4ba
stepca-1  | ✔ Intermediate certificate: /home/step/certs/intermediate_ca.crt
stepca-1  | ✔ Intermediate private key: /home/step/secrets/intermediate_ca_key
stepca-1  | ✔ Database folder: /home/step/db
stepca-1  | ✔ Default configuration: /home/step/config/defaults.json
stepca-1  | ✔ Certificate Authority configuration: /home/step/config/ca.json
stepca-1  |
stepca-1  | Your PKI is ready to go. To generate certificates for individual services see 'step help ca'.
stepca-1  |
stepca-1  | FEEDBACK 😍 🍻
stepca-1  |   The step utility is not instrumented for usage statistics. It does not phone
stepca-1  |   home. But your feedback is extremely valuable. Any information you can provide
stepca-1  |   regarding how you’re using `step` helps. Please send us a sentence or two,
stepca-1  |   good or bad at feedback@smallstep.com or join GitHub Discussions
stepca-1  |   https://github.com/smallstep/certificates/discussions and our Discord
stepca-1  |   https://u.step.sm/discord.
stepca-1  |
stepca-1  | 👉 Your CA administrative password is: TDmFTSCBYsoKk5LaTN65ZyKbCuH4gFAksNpPVZpk
stepca-1  | 🤫 This will only be displayed once.
stepca-1  | badger 2025/09/21 16:47:24 INFO: All 0 tables opened in 0s
stepca-1  | 2025/09/21 16:47:24 Building new tls configuration using step-ca x509 Signer Interface
stepca-1  | 2025/09/21 16:47:24 Starting Smallstep CA/0.28.4 (linux/amd64)
stepca-1  | 2025/09/21 16:47:24 Documentation: https://u.step.sm/docs/ca
stepca-1  | 2025/09/21 16:47:24 Community Discord: https://u.step.sm/discord
stepca-1  | 2025/09/21 16:47:24 Config file: /home/step/config/ca.json
stepca-1  | 2025/09/21 16:47:24 The primary server URL is https://localhost:9000
stepca-1  | 2025/09/21 16:47:24 Root certificates are available at https://localhost:9000/roots.pem
stepca-1  | 2025/09/21 16:47:24 Additional configured hostnames: 192.168.56.20, home.lan
stepca-1  | 2025/09/21 16:47:24 X.509 Root Fingerprint: 9eb1dc2acfb4b842c8e1ff7bf5ec2e601fbaeec57b0ff3ca751670c55365f4ba
stepca-1  | 2025/09/21 16:47:24 Serving HTTPS on :9000 ...
  1. 起動しているか確認
curl -k https://192.168.56.20:9000/health

下のように、出力されればOK!

{"status":"ok"}

ACMEサーバーの初期化処理

  1. Step-caを初期化
    Step-caのコンテナにログイン
cd ~/serverFiles/stepca && sudo docker compose exec -it stepca bash

初期化コマンドを打つ

step ca init

そうすると、質問に沿って答えていくだけだけど、英語だから翻訳と推奨値を載せておきます✨️


What deployment type would you like to configure?:
(どのタイプのデプロイを設定しますか?)

  • Standalone - step-ca instance you run yourself
    (スタンドアロン:自分で実行するstep-caインスタンス)
  • Linked - standalone, plus cloud configuration, reporting & alerting
    (リンク済み:スタンドアロン + クラウド設定、レポート、アラート機能)
  • Hosted - fully-managed step-ca cloud instance run for you by smallstep
    (ホスト済み:smallstepが提供する完全管理型step-caクラウドインスタンス)

What would you like to name your new PKI?
(新しいPKIにどんな名前をつけたいですか?)


What DNS names or IP addresses will clients use to reach your CA?
(クライアントが認証局にアクセスするために使用するDNS名またはIPアドレスは何ですか?)


What IP and port will your new CA bind to?
(新しいCAがバインドするIPアドレスとポートはどれですか?)


What would you like to name the CA's first provisioner?
(CAの最初のプロビジョナーにどのような名前を付けたいですか?)


Choose a password for your CA keys and first provisioner.
(CAキーと最初のプロビジョナーのパスワードを選択してください。)

(例)
[leave empty and we'll generate one (空欄のままにしていてください。こちらで生成します。)]: 
✔Password: kXHfMlhrgi7K6PDSwiVOJjic67ebe8Qq

パスワードをメモしたらEnterを押す


Would you like to overwrite /home/step/certs/root_ca.crt [y/n]:
(/home/step/certs/root_ca.crt を上書きしますか [y/n]:)

Would you like to overwrite /home/step/secrets/root_ca_key [y/n]:
Would you like to overwrite /home/step/certs/intermediate_ca.crt [y/n]:
Would you like to overwrite /home/step/secrets/intermediate_ca_key [y/n]:
Would you like to overwrite /home/step/config/ca.json [y/n]:
Would you like to overwrite /home/step/config/defaults.json [y/n]:

下のように表示されたら完了

Your PKI is ready to go. To generate certificates for individual services see 'step help ca'.

FEEDBACK 😍 🍻
  The step utility is not instrumented for usage statistics. It does not phone
  home. But your feedback is extremely valuable. Any information you can provide
  regarding how you’re using `step` helps. Please send us a sentence or two,
  good or bad at feedback@smallstep.com or join GitHub Discussions
  https://github.com/smallstep/certificates/discussions and our Discord
  https://u.step.sm/discord.

  1. パスワードを保存する

パスワードは、各々出力されたパスワードを入力してください〜

echo 'kXHfMlhrgi7K6PDSwiVOJjic67ebe8Qq' > /home/step/secrets/password

このコマンドを打たないと、下記のようなエラーが表示されます。

  1. step-caを再起動する
    一回ホストに戻り(Ctrl + d)、再起動をしましょう
sudo docker compose restart

このような感じで出力されたら、OK!

 ✔ Container stepca-stepca-1  Started
  1. ACMEプロビジョナーを作成
ACMEとは

ACME (Automatic Certificate Management Environment)

Webサーバと認証局との間の相互作用を自動化するための通信プロトコル で、利用者のWebサーバにおいて非常に低コストでPKIX (X.509)形式の公開鍵証明書の自動展開を可能とする

引用: ACME - Wiki

step-caのコンテナにログインをして、下記のコマンドを実行すればOK!

step ca provisioner add acme --type ACME

こんな感じで出力されれば、とりあえずACME設定は完了

✔ CA Configuration: /home/step/config/ca.json

Success! Your `step-ca` config has been updated. To pick up the new configuration SIGHUP (kill -1 <pid>) or restart the step-ca process.
  1. 再起動して設定を読み直す
sudo docker compose restart

クライアントへのCA認証ファイルをインストール

サーバーにroot_ca.crtをインストールする

  1. step-cacertsから、root_ca.crtをコピーする
cd ~/serverFiles/stepca/step/certs/ && \
sudo cp root_ca.crt /usr/local/share/ca-certificates
  1. 証明書を更新する
sudo update-ca-certificates

下のように出力されれば、OK!

Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
  1. 確認
curl -k https://192.168.56.20:9000/acme/acme/directory

下のようなJSONが、出力されればOK!

{
  "newNonce": "https://192.168.56.20:9000/acme/acme/new-nonce",
  "newAccount": "https://192.168.56.20:9000/acme/acme/new-account",
  "newOrder": "https://192.168.56.20:9000/acme/acme/new-order",
  "revokeCert": "https://192.168.56.20:9000/acme/acme/revoke-cert",
  "keyChange": "https://192.168.56.20:9000/acme/acme/key-change"
}

Caddyでプライベート証明書を自動取得

Caddyのインストール

  1. Caddy用のフォルダを作成
cd ~ && mkdir -p ~/serverFiles/caddy/{conf,site} && cd ~/serverFiles/caddy
  1. compose.yamlを作成・編集する
vim compose.yaml
compose.yaml
services:
  caddy:
    image: caddy:latest
    restart: unless-stopped
    cap_add:
      - NET_ADMIN
    network_mode: "host"
    volumes:
      - ./conf:/etc/caddy
      - ./site:/srv
      - caddy_data:/data
      - caddy_config:/config

volumes:
  caddy_data:
  caddy_config:
  1. メインのCaddyfileを作成・編集する
vim conf/Caddyfile
Caddyfile
{
    email admin@home.lan
}

import ./services/*.caddy
  1. 起動して、ログを確認
sudo docker compose up -d && sudo docker compose logs

下のような、エラーが表示されなければOK!

Error: adapting config using caddyfile: EOF

ACME設定の追加

ACMEをCaddyに設定して、SSLを自動取得します

  1. Caddyfileに、ACME設定を追記する
Caddyfile
{
    email admin@home.lan
+   acme_ca https://localhost:9000/acme/acme/directory
+   acme_ca_root /srv/root_ca.crt
}

import ./services/*.caddy
  1. root_ca.crtをコピーしてくる
cp ~/serverFiles/stepca/step/certs/root_ca.crt ~/serverFiles/caddy/site/

Caddyfileの作成

最終的な、フォルダ構造は下のようになります。

./conf
├── Caddyfile
└── services
    ├── ca.caddy
    └── dns.caddy
  1. サービス毎に、Caddyfileを格納しておくフォルダを作成する
mkdir -p ~/serverFiles/caddy/conf/services && \
cd ~/serverFiles/caddy/conf/services
  1. サービス毎の、Caddyfileを作成する
vim dns.caddy
dns.caddy
dns.home.lan { 
    reverse_proxy http://localhost:5380
}
ca.caddy
ca.home.lan {
    reverse_proxy https://localhost:9000 {
        transport http {
            tls_insecure_skip_verify
        }
    }
}
  1. コンテナにログインをして、Caddyfileを再読込する
cd ~/serverFiles/caddy && \
sudo docker compose exec -it caddy ash

/srvがカレントディレクトリとして、ログインされるはずです。

/etc/caddyに移動して、再読み込みコマンドを実行する

cd /etc/caddy && caddy reload

下のように表示されればOK!

2025/09/24 14:57:16.412 INFO    using adjacent Caddyfile
2025/09/24 14:57:16.413 INFO    adapted config to JSON  {"adapter": "caddyfile"}

動作確認

Vagrantでの場合の確認方法

curl -k https://dns.home.lan

こんな感じで、HTMLが表示される(最後部分だけ)

HTMLログ
                            <div class="well well-sm" style="background-color: #fbfbfb;">
                                <div class="form-group">
                                    <label class="col-sm-3 control-label">Group Permissions</label>
                                    <div class="col-sm-9">
                                        <table id="tableEditPermissionsGroup" class="table table-hover">
                                            <thead>
                                                <tr>
                                                    <th><a href="#" onclick="sortTable('tbodyEditPermissionsGroup', 0); return false;">Group</a></th>
                                                    <th><a href="#" onclick="sortTable('tbodyEditPermissionsGroup', 0); return false;" style="width: 65px;">View</a></th>
                                                    <th><a href="#" onclick="sortTable('tbodyEditPermissionsGroup', 0); return false;" style="width: 65px;">Modify</a></th>
                                                    <th><a href="#" onclick="sortTable('tbodyEditPermissionsGroup', 0); return false;" style="width: 65px;">Delete</a></th>
                                                    <th style="width: 76px;"></th>
                                                </tr>
                                            </thead>
                                            <tbody id="tbodyEditPermissionsGroup"></tbody>
                                        </table>
                                        <label class="control-label" for="optEditPermissionsGroupList">Add Group</label>
                                        <select id="optEditPermissionsGroupList" class="form-control"></select>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="modal-footer">
                        <button id="btnEditPermissionsSave" type="submit" class="btn btn-primary" data-loading-text="Saving...">Save</button>
                        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                    </div>
                </div>
            </div>
        </form>
    </div>

    <div id="footer"></div>
</body>
</html>

通常サーバーで構築している場合
https://dns.home.lan
alt text

この用に表示されたら、OK!


WireGuardでプライベートネットワークを構築

WireGuardのみ、2つのやり方を紹介します。
主が、記事を書いている途中に構成を変更したためです♪

Dockerでの構築方法

環境構築

  1. wireguard用のフォルダを作成
cd ~ && mkdir -p serverFiles/wireguard/etc_wg
  1. compose.yamlを作成する
cd ~/serverFiles/wireguard && \
vim compose.yaml
  1. 編集する
compose.yaml
services:
  wg-easy:
    image: ghcr.io/wg-easy/wg-easy:15
    container_name: wg-easy
    network_mode: host
    volumes:
      - ./etc_wg:/etc/wireguard
      - /lib/modules:/lib/modules:ro
    environment:
      WG_HOST: wg.vps.lan
      WG_PORT: "49538"
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
      - NET_RAW
    restart: unless-stopped
  1. 起動する
sudo docker compose up -d
  1. GUIにアクセスする
http://192.168.56.20:51821/

アクセスすると、セットアップ画面が表示される

alt text


  1. ユーザ名パスワードを入力する

alt text

  1. Do you have an existing setup?
    (既存の設定はありますか?)
  1. Please enter the host and port information. This will be used for the client configuration when setting up WireGuard on their devices.
    (ホストとポート情報を入力してください。これは、デバイスでWireGuardを設定する際のクライアント設定に使用されます。)

alt text

  1. You can't log in with an insecure connection. Use HTTPS.
    (安全でない接続ではログインできません。HTTPSをご利用ください。)
    alt text

WireGuard・WireGuard-UIのインストール

  1. WireGuardUIのインストール先ディレクトリを用意する
sudo mkdir /opt/wireguard && cd /opt && \
sudo chown vagrant:vagrant wireguard && \
cd wireguard
  1. aptでWireGuardをインストール
sudo apt install -y wireguard
  1. CPUのアーキテクチャを確認
uname -m

端末によってアーキテクチャが異なるため、ここで確認する
出力表記は、↓に記載

uname -m出力 通常表記
x86_64 amd64
aarch64 arm64
armv7l arm

※ dockerのマルチアーキテクチャで確認しましたが、間違ってたらすみません💦

  1. WireGuard-UIのバイナリファイルを、wgetでダウンロードする
    現時点(2025/10/04)での最新バージョンは、「v0.6.2」
アーキテクチャ 最新版ダウンロードURL(直リンク)
x86_64 WireGuard-UI-amd64
arm64 WireGuard-UI-arm64
arm WireGuard-UI-arm

今回は、amd64の方法で紹介していきます。
アーキテクチャが異なっても、インストール方法は変わらないと思います。

cd /opt/wireguard && \
wget https://github.com/ngoduykhanh/wireguard-ui/releases/download/v0.6.2/wireguard-ui-v0.6.2-linux-amd64.tar.gz
  1. ダウンロードしたファイルを、展開する
tar -zxvf wireguard-ui-v0.6.2-linux-amd64.tar.gz

wireguard-uiが、展開されます。

  1. wireguard-uiをサービス化・シンボリックの作成をする
    サービスファイルの作成
sudo vim /etc/systemd/system/wgui-worker.service

ポート番号は、任意で大丈夫ですが、今回は「51821」で設定します。

wgui-worker.service
[Unit]
Description=wireguard web ui
After=network.target

[Service]
Type=simple
WorkingDirectory=/opt/wireguard
ExecStart=/opt/wireguard/wireguard-ui --bind-address 0.0.0.0:51821
Restart=always

[Install]
WantedBy=multi-user.target

シンボリックの作成

sudo systemctl enable wgui-worker.service --now

インストール作業は完了!

全体設定

  1. IPを確認する

alt text

inetのところに書いてあるのが、IPなのでメモしておきましょう。
今回の場合、192.168.0.57となります。

  1. Web GUIにアクセスしてみる

ユーザによってIPが異なるため、リンクにはしていません

http://192.168.0.57:51821

MAIN-PCからアクセスしてみたら、ちゃんとアクセスできました。
alt text

  1. ログインをしてみる
  1. adminのパスワード変更

左サイドバーから、Users Settingsを押して、
adminユーザのEditボタンを押すと、パスワード変更ができる
alt text

  1. Global Settingsで設定をする

alt text

画像のように設定しましょう!
と言っても、Zennは画像拡大できないと思うので、下に設定した部分だけテーブル化しておきます。

設定項目名 設定値
Endpoint Address external.vps.lan
DNS Servers 10.8.0.0/24

設定はこれだけです。
Saveボタンはちゃんと押しましょう。

とりあえずの全体設定は終わりです。
必要な設定が出た場合、各自設定をしましょう。

サーバーの設定

alt text

設定項目名 設定値 備考
Server Interface Addresses 10.8.0.1/24 WireGuardサーバーのIPアドレスになります。
Listen Port 51820 任意なポート番号でOK!
できたら変更したほうがいいと思う

クライアントの追加

  1. DNSサーバーのクライアント設定

alt text

右上の +New Clientを押すと、ダイアログが表示されます。

DNS(Debian-Server)用クライアント設定

設定項目名 設定値 備考
Name DNS(Debian-Server) DNSサーバー用のクライアント
Email locu@home.lan (任意) 架空のEmailでOK!
Allowed IPs 10.8.0.0/24 0.0.0.0/0は削除し、10.8.0.0/24など必要な範囲のみ記載。
(※この例では10.8.0.2をDNSサーバーに指定)
詳しくは下記メッセージ参照
Extra Allowed IPs 192.168.56.0/24 クライアントのプライベートIPサブネット

Main-PC用クライアント設定(Extra Allowed IPs設定は無し)

設定項目名 設定値 備考
Name Main-PC Main-PCクライアント
Email locu@home.lan (任意) 架空のEmailでOK!
Allowed IPs 10.8.0.0/24 0.0.0.0/0は削除し、10.8.0.0/24など必要な範囲のみ記載。
詳しくは下記メッセージ参照

設定が終わったら、Submitボタンで登録!

画像のような感じになったらOK!
alt text

最後に、右上の ✔Apply ConfigApplyを押して、wg0.confに反映する。

サービスを登録・起動する

WireGuardのwg0.confをサービスに登録しましょう。

sudo systemctl enable wg-quick@wg0
sudo wg-quick up wg0

下のように出力されればOK!

vagrant@vps:/etc/caddy$ sudo systemctl enable wg-quick@wg0
Created symlink /etc/systemd/system/multi-user.target.wants/wg-quick@wg0.service → /lib/systemd/system/wg-quick@.service.
vagrant@vps:/etc/caddy$ sudo wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.8.0.1/24 dev wg0
[#] ip link set mtu 1450 up dev wg0
[#] ip -4 route add 192.168.56.0/24 dev wg0
[#]

クライアントにWireGuardコンフィグをインストールする

DNS(Debian-Server)のみのインストール方法を紹介します。
Main-PCでもインストール方法は同じです。

※DNS(Debian-Server)のSSHにログインしましょう。

  1. WireGuardをインストールする
ubuntu/debian
sudo apt install wireguard
archlinux
sudo pacman -S wireguard-tools
  1. WireGuardコンフィグをダウンロード

WireGuard Clientsの画面で、Downloadというボタンを押すと、コンフィグがダウンロードできます。
alt text

ダウンロードできたら、ファイルを開いてクリップボードにコピーをしましょう。

  1. wg0.confを作成・編集

wg0.confを作成

sudo vim /etc/wireguard/wg0.conf

コピーしたものをペースト(i 押してから、Ctrl + Shift + v)
alt text

こんな感じになればOK!
保存をして、閉じてください。

  1. WireGuardを起動する
sudo systemctl enable wg-quick@wg0
sudo wg-quick up wg0

これでOK!

DNSにサブドメインを追加する

登録の方法は、こちらの見出しで解説しています。
そのため、値だけテーブル表記で記載しておきます。

Zone Name:vps.lan

Name Type IPv4/Domain Name
@ A 10.8.0.1
external A 192.168.0.57(ここで確認したIPアドレス)
wg CNAME vps.lan

こんな感じになりました。
alt text

疎通確認

ping -c 3 home.lan
ping -c 3 vps.lan
ping -c 3 external.vps.lan

こんな感じで出力されればOK!

vagrant@vps:~$ ping -c 3 home.lan
ping -c 3 vps.lan
ping -c 3 external.vps.lan
PING home.lan (192.168.56.20) 56(84) bytes of data.
64 bytes from 192.168.56.20 (192.168.56.20): icmp_seq=1 ttl=64 time=0.539 ms
64 bytes from 192.168.56.20 (192.168.56.20): icmp_seq=2 ttl=64 time=0.532 ms
64 bytes from 192.168.56.20 (192.168.56.20): icmp_seq=3 ttl=64 time=0.611 ms

--- home.lan ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2013ms
rtt min/avg/max/mdev = 0.532/0.560/0.611/0.035 ms
PING vps.lan (10.8.0.1) 56(84) bytes of data.
64 bytes from vps (10.8.0.1): icmp_seq=1 ttl=64 time=0.015 ms
64 bytes from vps (10.8.0.1): icmp_seq=2 ttl=64 time=0.036 ms
64 bytes from vps (10.8.0.1): icmp_seq=3 ttl=64 time=0.067 ms

--- vps.lan ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 3016ms
rtt min/avg/max/mdev = 0.015/0.039/0.067/0.021 ms
PING external.vps.lan (192.168.0.57) 56(84) bytes of data.
64 bytes from vps (192.168.0.57): icmp_seq=1 ttl=64 time=0.011 ms
64 bytes from vps (192.168.0.57): icmp_seq=2 ttl=64 time=0.044 ms
64 bytes from vps (192.168.0.57): icmp_seq=3 ttl=64 time=0.048 ms

--- external.vps.lan ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2608ms
rtt min/avg/max/mdev = 0.011/0.034/0.048/0.016 ms

SSL・リバースプロキシ設定(Caddy)

設定したドメインたちは、ブラウザ上からはリバースプロキシされていないので、GUIにアクセスできません。
そのため、VPS上にCaddyを構築して、設定をします。

今回はDockerを使いません。
Dockerを使いたい場合は、こちらを参考にしてください。

  1. caddy をインストール・起動

Caddyをインストールする

sudo apt install caddy -y

Caddyを起動

sudo systemctl enable caddy --now
  1. caddyのフォルダに移動・servicesフォルダを作成
cd /etc/caddy && \
sudo mkdir -p {services,ca}
  1. Caddyfileを書き換え
sudo vim Caddyfile 
Caddyfile
{
   email admin@home.lan
   acme_ca https://ca.home.lan/acme/acme/directory
   acme_ca_root /etc/caddy/ca/root_ca.crt
}

import ./services/*.caddy
  1. wireguard.caddyを作成
sudo vim ./services/wireguard.caddy
wireguard.caddy
wg.vps.lan {
    reverse_proxy localhost:51821
}
  1. root_ca.crthome.lanからvps.lanにコピーする

Vagrant環境だとなぜか、SSH接続ができないので力技でやります。
ですが、基本的にrsyncコマンドかscpコマンドを使って、ファイルを転送しましょう。

home.lan
cd ~/serverFiles/stepca/step/certs && \
cat root_ca.crt

出力されたものを、選択して ctrl + shift + c でコピーする

vps.lan
cd /etc/caddy && \
sudo vim ca/root_ca.crt

コピーしたものを、ctrl + shift + v でペーストする

ipv4フォワーディングを有効化する

echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-ipforward.conf && \
sudo sysctl --system

ドメインでアクセス確認

https://wg.home.lan

alt

ちゃんとアクセスできましたね

これで、色々の設定は終わりです!

参考文献

https://zenn.dev/k175/articles/0cb767cf395417

感想

疲れたけど、楽しかったしメモも残せたからいい思い出〜

長文な記事を読んでいただきありがとうございます!
不備等あれば、どんどんコメントお願いします🙏

Discussion