ConoHa の VPS に WireGuard を設定する

ConoHa Enterprise Linux 9
このサイトはアフィリエイト広告(Amazonアソシエイト含む)を掲載しています。
スポンサーリンク

不正アクセスが横行しているので、VPS 上の管理者だけがアクセスするプログラムを VPN 経由に制限することにしました。

お手軽に Tailscale を使っても良かったのですが、知識を深めるために WireGuard を使って自前で構築したので記録しておきます。

環境

  • OS:AlmaLinux release 9.8 (Olive Jaguar)
  • Python:3.9.25
  • ウェブサーバー:OpenLiteSpeed 1.9.4
  • ホスティング:ConoHa VPS(メモリ 2GB)
ConoHa VPS

この記事では説明用にサーバーを 10.0.0.1、iPhone を 10.0.0.2 とします。

10.0.0.0/24 は、既存の LAN や別の VPN でも使用されることがあります。利用するネットワークと重複する場合は、別の範囲(10.xx.0.0/24)を選び、この記事の関連設定をすべて置き換えてください。

WireGuard のインストール

dnf install wireguard-tools net-tools git
(out) Dependencies resolved.
(out) =============================================================================================================================================================
(out)  Package                                 Architecture                  Version                                        Repository                        Size
(out) =============================================================================================================================================================
(out) Installing:
(out)  wireguard-tools                         x86_64                        1.0.20210914-4.el9                             appstream                        113 k
(out) Installing dependencies:
(out)  systemd-resolved                        x86_64                        252-67.el9_8.6.alma.1                          baseos                           344 k
(out) 
(out) Transaction Summary
(out) =============================================================================================================================================================
(out) Install  2 Packages
(out) 
(out) Total download size: 457 k
(out) Installed size: 1.0 M
(out) Is this ok [y/N]: y

カーネルの WireGuard 機能を読み込みます。

modprobe wireguard

正常に読み込まれた場合、通常は何も表示されません。続いて、操作ツールを確認します。

wg --version
(out) wireguard-tools v1.0.20210914 - https://git.zx2c4.com/wireguard-tools/

設定ファイルの保存先を作成します。

install -d -m 700 /etc/wireguard

これで WireGuard の導入は完了です。VPN のアドレスや、接続端末の設定は後で行います。

ファイアウォールの設定

ファイアウォール(nftables)の設定に関しては過去の記事をご覧ください。

Red Hat Enterprise Linux 9 のファイアウォール(nftables)設定
ipset が非推奨になった RHEL9 において、ファイアウォールを nftables で設定する手順。管理者用・日本国内の IP リストでポートを制限し、fail2ban で不正アクセスを自動遮断します。

WireGuard のデフォルトポートは UDP 51820 が一般的ですが、以前に設定した TURN サーバー用の UDP 49152 - 65535 とバッティングしているので、今回は UDP 41820 ポートで設定することにします。

ファイアウォール設定(/etc/nftables/filter.nft)の chain UDP に、WireGuard 用のルールを追加します。

table inet filter {
         …
         省略
         …
        chain UDP {
                # 日本国内にのみ開放
                # TURN, TURNS, Janus, WireGuard
                udp dport { 3478, 5349, 20000-40000, 41820, 49152-65535 } ip saddr @domestic accept

                # 全開放
                # HTTP/3
                udp dport { 443 } accept
        }
}

UDP 41820 を国内のみに追加していますので、海外からアクセスする場合は全開放の方に追加してください。

設定の構文チェックをしてから、ファイアウォールの設定を反映します。

nft -c -f /etc/sysconfig/nftables.conf
systemctl reload nftables

WGDashboard のインストール

WGDashboard は、WireGuard の設定や端末管理をブラウザから行うためのアプリです。

WGDashboard | Simple dashboard to manage WireGuard VPN
Manage your WireGuard VPN with ease

Python 3.13 のインストール

AlmaLinux 9 標準の Python のバージョンは 3.9 で、WGDashboard の要件(3.10〜3.13)を満たさないため、EPEL リポジトリから 3.13 をインストールします。

EPEL・CRB が未設定の場合は、有効にします。

dnf install dnf-plugins-core epel-release
dnf config-manager --set-enabled crb
dnf install python3.13 python3.13-pip
(out) Dependencies resolved.
(out) =============================================================================================================================================================
(out)  Package                                      Architecture                   Version                                 Repository                         Size
(out) =============================================================================================================================================================
(out) Installing:
(out)  python3.13                                   x86_64                         3.13.16-1.el9                           epel                               27 k
(out)  python3.13-pip                               noarch                         25.1.1-1.el9                            epel                              2.5 M
(out) Installing dependencies:
(out)  mpdecimal                                    x86_64                         2.5.1-3.el9                             appstream                          85 k
(out)  python3.13-libs                              x86_64                         3.13.16-1.el9                           epel                              9.4 M
(out)  python3.13-pip-wheel                         noarch                         25.1.1-1.el9                            epel                              1.2 M
(out) 
(out) Transaction Summary
(out) =============================================================================================================================================================
(out) Install  5 Packages
(out) 
(out) Total download size: 13 M
(out) Installed size: 55 M
(out) Is this ok [y/N]: y

バージョンを確認します。

python3 --version
(out) Python 3.9.25
python3.13 --version
(out) Python 3.13.16

通常のシェルでは python 3.9、python3.13 として呼ぶと 3.13 を使う事ができます。

WGDashboard のダウンロード

/usr/share/wgdashboard に配置する事にします。

git clone https://github.com/WGDashboard/WGDashboard.git /usr/share/wgdashboard
(out) Cloning into '/usr/share/wgdashboard'...
(out) remote: Enumerating objects: 20285, done.
(out) remote: Counting objects: 100% (7211/7211), done.
(out) remote: Compressing objects: 100% (886/886), done.
(out) remote: Total 20285 (delta 6751), reused 6325 (delta 6325), pack-reused 13074 (from 3)
(out) Receiving objects: 100% (20285/20285), 56.77 MiB | 29.48 MiB/s, done.
(out) Resolving deltas: 100% (14938/14938), done.

Python 3.13 の仮想環境を作成

python3.13 -m venv /usr/share/wgdashboard/src/venv
/usr/share/wgdashboard/src/venv/bin/python3 --version
(out) Python 3.13.16
/usr/share/wgdashboard/src/venv/bin/python3 -m pip --version
(out) pip 26.2.2 from /usr/share/wgdashboard/src/venv/lib64/python3.13/site-packages/pip (python 3.13)

WGDashboard をインストール

chmod u+x /usr/share/wgdashboard/src/wgd.sh
env -C /usr/share/wgdashboard/src PATH="/usr/share/wgdashboard/src/venv/bin:$PATH" ./wgd.sh install

WireGuard の設定ファイルを保護します。

chmod 700 /etc/wireguard
find /etc/wireguard -type f -name '*.conf' -exec chmod 600 {} +

WGDashboard の設定ファイルを作成します。

[Server]
app_ip = 127.0.0.1
app_port = 10086
auth_req = true

設定ファイルを root だけが読み書きできる権限にします。

chmod 600 /usr/share/wgdashboard/src/wg-dashboard.ini

自動起動設定

サービスに登録して自動起動するように設定します。

[Unit]
Description=WGDashboard
Wants=network-online.target
After=network-online.target nftables.service
ConditionPathIsDirectory=/etc/wireguard

[Service]
Type=forking
User=root
WorkingDirectory=/usr/share/wgdashboard/src
PIDFile=/usr/share/wgdashboard/src/gunicorn.pid
ExecStart=/usr/share/wgdashboard/src/wgd.sh start
ExecStop=/usr/share/wgdashboard/src/wgd.sh stop
Restart=on-failure
RestartSec=5
TimeoutSec=120
PrivateTmp=true
UMask=0077

[Install]
WantedBy=multi-user.target

パーミッションを変更し、サービス定義を読み込み、自動起動を有効にして起動します。

chmod 644 /etc/systemd/system/wg-dashboard.service
systemctl daemon-reload
systemctl enable --now wg-dashboard.service
(out) Created symlink /etc/systemd/system/multi-user.target.wants/wg-dashboard.service → /etc/systemd/system/wg-dashboard.service.

WGDashboard が起動しているか、待ち受けポートを確認します。

ss -ltnp 'sport = :10086'
(out) State          Recv-Q         Send-Q                 Local Address:Port                  Peer Address:Port         Process
(out) LISTEN         0              2048                       127.0.0.1:10086                      0.0.0.0:*             users:(("gunicorn",pid=12106,fd=18),("gunicorn",pid=12104,fd=18))

OpenLiteSpeed の設定

OLS の管理画面にログインし、外部アプリとして WGDashboard を登録します。

OpenLiteSpeed で WGDashboard を外部アプリに設定
  • 名前:WGDashboard
  • アドレス:127.0.0.1:10086

バーチャルホストの設定から、リライトを開き Rewrite ルールを追加します。

RewriteCond %{REMOTE_ADDR} ^198\.51\.100\.21$
RewriteRule ^/wg-dashboard/(.*) http://WGDashboard/$1 [P,L]

RewriteCond でアクセスできる IP アドレスを管理者(例:198.51.100.21)に制限し、RewriteRule で外部アプリに設定したアドレスに転送しています。(※アクセス制限が必要な場合のみ)

グレースフル再起動をして、OLS の設定を反映します。

WGDashboard の設定

ブラウザで https://(ドメイン名)/wg-dashboard/ にアクセスして、WGDashboard のログイン画面が表示されることを確認してください。

  • 初期ユーザー名:admin
  • 初期パスワード:admin

初期ユーザー名と初期パスワードでログインして、管理者用パスワードを変更します。

また、設定メニューで言語を日本語に変更しておくと良いでしょう。

WireGuard 構成

Add WireGuard Configuration | WGDashboard Docs
Official Documentation for WGDashboard

ホーム画面から構成を追加します。

  • 構成名:wg0
  • 秘密鍵 & 公開鍵:自動生成されたものを使用
  • 待ち受けポート:41820(通常は 51820)
  • IPアドレス/CIDR:10.0.0.1/24

一度保存したあと、WireGuard 構成一覧から wg0 を開き、構成設定を開きます。

設定項目が増えて Override Peer Settings が設定できるようになりますので、DNS と Endpoint の設定を追加して保存します。

  • DNS:10.0.0.1
  • Endpoint:(VPS のグローバル IP アドレス)

wg コマンドでステータスを確認

WGDashboard で作成した wg0 が正しく反映されているか、ターミナルで確認します。

wg show wg0
(out) interface: wg0
(out)   public key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
(out)   private key: (hidden)
(out)   listening port: 41820

設定ファイルの権限を整えます。

chmod 600 /etc/wireguard/wg0.conf

wg0 の自動起動を有効にします。

systemctl enable wg-quick@wg0.service

iPhone 用のピアを追加

再び WGDashboard に戻り、iPhone 用の Peer(接続端末) を作成します。

  1. ホームの wg0 で「ピアを追加」から以下の内容で追加しました。(DNS と Endpoint Allowed IPs は追加設定を展開すると出てきます。)
    • 名前:iPhone
    • Allowed IPs:10.0.0.2/32(初期値)
    • DNS:10.0.0.1
    • Endpoint Allowed IPs:10.0.0.1/32
  1. 作成したピアのメニュー(…)から、QR コードのアイコンをクリックします。
  2. QR コードが表示された状態で、iPhone 側の操作をします。

iPhone の設定

iPhone で App Store から WireGuard アプリをインストールします。

WireGuardアプリ - App Store
WireGuard Development Teamの「WireGuard」をApp Storeでダウンロードしてください。スクリーンショット、評価とレビュー、ユーザのヒント、「WireGuard」に似たゲームを見ることなどができます。

アプリを起動し「トンネルの追加」>「QR コードから作成」で、WGDashboard に表示されたQR コードを読み取ります。

「WireGuard が VPN 構成の追加を求めています」と出たら許可をタップして追加します。

以上で WireGuard の設定は完了です。

今回ハマったポイントとして、QR コードで読み込んだ設定のエンドポイントが 127.0.0.1:41820 になっており接続できませんでした。エンドポイントが VPS の IP アドレス:41820 になるように wg0 の構成設定を見直したら行けました。

DNS の設定

WireGuard 自体には、ドメイン名を VPN 用 IP アドレスに変換する機能はありません。今回のドメインは公開 DNS にサーバーの公開 IP を登録しているため、そのままでは公開 IP に接続します。10.0.0.1/32 だけを VPN の対象にした構成では、この通信は VPN を通りません。

そこで VPS に Unbound を導入し、対象ドメインへの問い合わせに 10.0.0.1 と回答するよう設定します。iPhone の WireGuard 設定では、DNS サーバーに 10.0.0.1 を指定します。

これにより、既存の URL と HTTPS 証明書をそのまま使いながら、対象サーバーへの通信を VPN 経由にできます。公開 DNS の登録内容を変更する必要はありません。

SSH などで VPN 用 IP を直接指定する場合、この名前解決の仕組みは不要です。

Unbound をインストール

dnf install unbound bind-utils
(out) Package bind-utils-32:9.16.23-40.el9_8.12.x86_64 is already installed.
(out) Dependencies resolved.
(out) =============================================================================================================================================================
(out)  Package                               Architecture                    Version                                      Repository                          Size
(out) =============================================================================================================================================================
(out) Installing:
(out)  unbound                               x86_64                          1.24.2-3.el9_8.8                             appstream                          1.0 M
(out) Installing dependencies:
(out)  unbound-libs                          x86_64                          1.24.2-3.el9_8.8                             appstream                          580 k
(out) 
(out) Transaction Summary
(out) =============================================================================================================================================================
(out) Install  2 Packages
(out) 
(out) Total download size: 1.6 M
(out) Installed size: 5.2 M
(out) Is this ok [y/N]: y

設定ファイルで、追加設定を読み込むように変更します。

grep -nE '^[[:space:]]*include(-toplevel)?:' /etc/unbound/unbound.conf
(out) 794:    include: /etc/unbound/local.d/*.conf
(out) 1019:include: /etc/unbound/conf.d/*.conf

WireGuard 用の設定

VPN 用の設定ファイルを作成します。

server:
    # DNS の問い合わせを受け付ける IP
    interface: 10.0.0.1

    # wg0 より先に Unbound が起動しても待ち受け可能にする
    ip-freebind: yes

    # VPN 内の送信元からの DNS 問い合わせを許可
    access-control: 10.0.0.0/24 allow

    # ドメインを VPN 用 IP に対応させる
    local-zone: "example.com." transparent
    local-data: "example.com. 60 IN A 10.0.0.1"

    # (サブドメインを個別に指定する場合)
    local-zone: "example.net." transparent
    local-data: "example.net. 60 IN A 10.0.0.1"
    local-data: "www.example.net. 60 IN A 10.0.0.1"
    local-data: "subdomain.example.net. 60 IN A 10.0.0.1"

    # (サブドメインをまとめて指定する場合)
    local-zone: "example.jp." redirect
    local-data: "example.jp. 60 IN A 10.0.0.1"

    # 上流の証明書検証に使う CA バンドル(DoT する場合のみ)
    tls-cert-bundle: /etc/pki/tls/certs/ca-bundle.crt

# その他のドメインは外部 DNS(Cloudflare)に問い合わせる
forward-zone:
    name: "."
    forward-tls-upstream: yes
    # IP@ポート#証明書のホスト名(この名前で証明書を検証する)
    forward-addr: 1.1.1.1@853#cloudflare-dns.com
    forward-addr: 1.0.0.1@853#cloudflare-dns.com

DoT(DNS over TLS)することで、送信先が UDP 53 から TCP 853 に変わります。nftables の output chain を制限している場合は 853/tcp を許可してください。

設定を検証して起動

管理用の鍵を準備してから、設定を検証します。

systemctl start unbound-keygen.service
unbound-checkconf
(out) unbound-checkconf: no errors in /etc/unbound/unbound.conf

Unbound の自動起動を設定して起動します。

systemctl enable --now unbound.service
(out) Created symlink /etc/systemd/system/multi-user.target.wants/unbound.service → /usr/lib/systemd/system/unbound.service.

VPS 上で名前解決を確認します。

ip -brief address show wg0
(out) wg0              UNKNOWN        10.0.0.1/24
dig @10.0.0.1 example.com A +short
(out) 10.0.0.1

ファイアウォールの VPN 用設定

以下の記事をベースにしたファイアウォール設定に、VPN を追加します。

Red Hat Enterprise Linux 9 のファイアウォール(nftables)設定
ipset が非推奨になった RHEL9 において、ファイアウォールを nftables で設定する手順。管理者用・日本国内の IP リストでポートを制限し、fail2ban で不正アクセスを自動遮断します。

WireGuard 経由の IP アドレス(10.0.0.0/24)のリストを作成し、DNS 用のポート(TCP 53, UDP 53)を通すように、ファイアウォールの設定(/etc/nftables/filter.nft)を変更します。また、国内向けに開放しているポートにも届くように修正します。

# 現在のルールセットを消去
flush ruleset

# 管理者用 IP アドレスリストを読み込む
include "/etc/nftables/list/admin"
# 日本国内 IP アドレスリストを読み込む
include "/etc/nftables/list/domestic"

table inet filter {

        set admin {
                type ipv4_addr
                elements = $admin
                # admin リストを CIDR(10.0.0.0/24)にするなら flags interval を有効にする
                #flags interval
        }

        set domestic {
                type ipv4_addr
                flags interval
                auto-merge
                elements = $domestic
        }

        set vpn {
                type ipv4_addr
                flags interval
                elements = { 10.0.0.0/24 }
        }
         …
         省略
         …
        chain TCP {
                # 管理者にのみ解放
                # SSH, OLS 管理画面
                tcp dport { 22, 7080 } ip saddr @admin accept

                # 日本国内にのみ開放
                # SUBMISSION, IMAPS, TURN, TURNS
                tcp dport { 587, 993, 3478, 5349 } ip saddr @domestic accept

                # WireGuard 経由(DNS:53 + 国内解放のポート)
                iifname "wg0" ip saddr @vpn ip daddr 10.0.0.1 tcp dport { 53, 587, 993, 3478, 5349 } counter accept

                # 全開放
                # SMTP, HTTP, HTTPS
                tcp dport { 25, 80, 443 } accept
        }

        chain UDP {
                # 日本国内にのみ開放
                # TURN, TURNS, Janus, WireGuard
                udp dport { 3478, 5349, 20000-40000, 41820, 49152-65535 } ip saddr @domestic accept

                # WireGuard 経由(DNS:53 + 国内解放のポート - WireGuard:41820)
                iifname "wg0" ip saddr @vpn ip daddr 10.0.0.1 udp dport { 53, 3478, 5349, 20000-40000, 49152-65535 } counter accept

                # 全開放
                # http/3
                udp dport { 443 } accept
        }
}

iifname "wg0" を付けると、送信元 IP に加えて実際に WireGuard から入った通信かどうかも判定されます。

管理者用の IP アドレスリストに、VPN 越しで管理者にする IP アドレスを追加します。

define admin = {
        198.51.100.21,  # 自宅
        203.0.113.1,    # 会社
        10.0.0.2        # WireGuard 経由の管理者端末
}

設定の構文チェックをしてから、ファイアウォールの設定を反映します。

nft -c -f /etc/sysconfig/nftables.conf
systemctl reload nftables

DNS の問い合わせも WireGuard の中を通るため、ConoHa DNS 側で公開用の 53 番ポートを開ける必要はありません。

逆に、ConoHa DNS 側で公開用の UDP 41820 を開ける必要がありますが、Unbound 側には必要ありません。

Web サイトの IP アドレス制限

例えば WordPress の管理画面(/wp-admin)へのアクセス許可リストを、OpenLiteSpeed の静的コンテキストで絞っている場合などは、10.0.0.* に限定する事で VPN 経由のアクセスだけを通すように設定できます。

参考にしたサイト

VPN接続が不安定ならプロトコルを見直せ――OpenVPNからWireGuardへの移行で解決した話 - Qiita
先日、某クライアントのリモート環境構築で「OpenVPNではどうしても接続が安定しない」という問題に直面しました。原因追求に数時間を費やした後、WireGuardへ乗り換えたところ、接続安定性が劇的に向上しました。本記事では、そのときの経験...
ConoHa VPS

コメント

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