広告 デバイス

【解説】VPS+VPN(WireGuard)による自宅サーバの公開方法(VPN設定編)

※本ページには、プロモーション(広告)が含まれています。

悩んでいる人

自宅サーバを外部公開したい。

ただ、グローバルIPが割り当てられていないため、なるべく金銭的負担が増えない方法を知りたい。

こんなお悩みを解決します。

本記事の内容を読み進める上で、VPSを用意する必要があります。

どの会社のVPSサーバを選択しようか悩んでいる場合、以下の記事を参考に検討していただければと思います。

あわせて読みたい
【比較】おすすめのVPS 4選

続きを見る

VPSの契約・構築方法については、以下で解説しているので、参考にしてください。

あわせて読みたい
【解説】VPS+VPN(WireGuard)による自宅サーバの公開方法を分かりやすく解説!(VPS契約編)

続きを見る

今回は、VPS上にVPN Serverを構築し、グローバルIPアドレスが割り当てられていない状況下で、自宅サーバを公開する方法について解説します。

必要な設定を順番に解説していきますので、興味がある方はぜひ最後までご覧ください。

現状整理と対応方針

まず、現状のネットワーク構成を共有します。

その上で、グローバルIPアドレスが割り当てられていない状況下で、自宅サーバを外部公開する際の対応方針を示します。

現状整理

私の環境では、以下のようなネットワーク構成になっています。

現状のネットワーク構成

この状況下では、自宅のルータ(= ルータ2)でポート開放を行っても、マンションのルータ(= ルータ1)で通信が遮断されてしまうため、自宅サーバを外部に公開できません。

現状のネットワーク構成の問題点

対応方針

対策として、外部のVPSにVPN Serverを構築し、自宅サーバとVPSをVPNで接続します。

ネットワーク構成の問題亭に対する対策

上記により、以下のようにインターネットからのリクエストを自宅サーバに転送することで、外部にサーバを公開できます。

対策による効果

構築するネットワークの全体構成

最終的なネットワークの全体構成は、以下のようになります。

また、今回は、VPNの実現にWireGuardというアプリケーションを利用します。

ネットワークの全体構成

インターネットからのリクエストが来た時のフローを示すと以下のようになります。(レスポンス部分は省略しています)

  1. インターネットからのリスクエストをNginx(Reverse Proxy)でWireGuard Serverに中継する。
  2. WireGuard ServerのIP MasqueradeによりIPアドレスを変換する。
  3. WireGuard NetworkでVPN Clientにデータを送信する。
  4. WireGuard ClientのIP MasqueradeによりIPアドレスを変換する。
  5. Nginx(Web)で公開されているサイトを引き当て、レスポンスとして返却する。
インターネットからのリクエストが来た時のフロー

事前準備

今回は、Dockerを用いて環境構築を行うため、事前準備としてDockerとDocker-Composeのインストール方法について解説します。

DockerとDocker-Composeは、VPSサーバと自宅サーバの両方にインストールしてください。

Dockerのインストール

下記のコマンドを順番に実行し、Dockerをインストールします。

インストールには管理者権限が必要となるため、下記のコマンドはsudoグループに属しているユーザで実行してください。

# インストール用の shell scriptの取得
curl -fsSL https://get.docker.com -o get-docker.sh

# 動作確認(dry-run)
DRY_RUN=1 sh ./get-docker.sh

# インストール
sudo sh ./get-docker.sh

# Dockerを操作するユーザをdockerグループに追加
# (usernameは、例を参考に、環境に合わせて変更すること)
sudo usermod -aG docker yuruto
# フォーマット
# sudo usermod -aG docker [username]

Docker-Composeのインストール

Docker-Composeは、下記の2ステップでインストールできます。

  1. 該当するDocker-Composeのスクリプトファイルをダウンロードする。
  2. ダウンロードしたスクリプトファイルに実行権限を付与し、/usr/local/bin以下に格納する。

Docker-Composeのスクリプトファイルのダウンロード

Docker-Composeは、以下のサイトで最新版が公開されています。下記のサイトから該当するファイルをダウンロードし、サーバに格納してください。

Docker-Composeのダウンロード

探す際にOSとarchitectureの情報が必要になります。

それぞれ、下記のコマンドを実行することで調べることができます。

# OS
uname -a
出力例:Linux
# architecture
uname -m
出力例:x86_64

また、ダウンロード時は、curlコマンドを利用すると楽に取得できます。

curl -s -L "https://github.com/docker/compose/releases/download/v2.12.2/docker-compose-linux-x86_64" -o docker-compose

Docker-Composeコマンドの有効化

ダウンロードしたDocker-Composeのスクリプトファイルに実行権限を付与し、/usr/local/bin以下に格納してください。

格納後、コマンドを実行し、期待通りのバージョンが出力されれば成功です。

# 実行権限の付与
chmod +x docker-compose

# /usr/local/binへ格納
sudo mv docker-compose /usr/local/bin

# バージョンの確認
docker-compose -v
Docker Compose version v2.12.2

環境構築の詳細

今回は、以下の条件で環境構築を行います。

カテゴリ項目
Nginx (Reverse Proxy)VPSでHTTPのリクエストを待ち受ける際のポート番号443
WireGuard Server/ClientVPN ServerのIPアドレスVPN ServerのIPアドレス10.1.2.1
VPN ClientのIPアドレス10.1.2.2
VPN Server/Clientが属するサブネット10.1.2.0/24
VPN接続時のポート番号51820
VPN接続中に利用するDNS8.8.8.8,10.1.2.1
VPN Server経由で通信するIPアドレス10.1.2.0/24
Nginx (Web)Docker ContainerのIPアドレス10.0.16.3
待ち受けポート8080
構築環境の詳細情報

VPN Serverの設定・構築

VPN Serverを構築する上では、以下の3点に対応する必要があります。順に説明していきます。

  • WireGuardを起動する際のUIDGIDを設定する。
  • VPN Server構築時の環境変数(WireGuard、Nginx)を設定する。
  • Docker Imageを作成する。(Nginxのみ)
  • VPN Serverのiptablesを設定する。
  • HTTPとWireGuardで通信する際に利用するポートを開放する。

また、該当するコードは、GitHubの下記に保存してあります。git cloneして利用してください。

https://github.com/yuruto-free/vpnaccess-wireguard-nginx/tree/v0.2.0

UIDとGIDの設定

VPS上で以下のコマンドを実行し、UIDGIDを確認します。

ここで、表示されるのはコマンド実行時のユーザの情報となります。

id
uid=1000(yuruto) gid=1000(yuruto) groups=1000(yuruto),27(sudo),999(docker)

次に、docker-compose.ymlをエディタで開き、下記の部分を環境に合わせて書き換えます。

wireguard:
    image: lscr.io/linuxserver/wireguard:latest
    container_name: wireguard
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    environment:
      - PUID=1000 # 【変更箇所1】uidの数値を設定
      - PGID=1000 # 【変更箇所2】gidの数値を設定
      - TZ=Asia/Tokyo

VPN Serverの環境変数設定

ここでは、以下の2パターンに分けて環境変数を設定していきます。

  • WireGuard固有の環境変数
  • Nginx固有の環境変数

WireGuard固有の環境変数

ここで設定する環境変数は、以下の9点となります。

環境変数名説明補足
SERVERURLVPN Server接続時のIPアドレス/FQDNWireGuard imageで使用する
SERVERPORTVPN接続時のポート番号WireGuard imageで使用する
PEERSVPN Client一覧WireGuard imageで使用する
PEERDNSVPN接続中に利用するDNSWireGuard imageで使用する
INTERNAL_SUBNETVPN Server/Clientが属するサブネットWireGuard imageで使用する
MTUMTUの値-
KEEP_ALIVEkeep-aliveの値-
ALLOWEDIPSVPN Server経由で通信するIPアドレスWireGuard imageで使用する
SERVER_ALLOWEDIPS_PEER_PublicServerWireGuardのサブネット以外において、VPN Clientが属するサブネットWireGuard imageで使用する
WireGuard固有の環境変数

上記に対し、下記のように設定し、envs/wireguard/.envに保存します。

ここで、SERVERURLSERVERPORTなどは、ご自身の環境に合わせて設定してください。

SERVERURL=example.vpn.com
SERVERPORT=51820
PEERS=PublicServer
PEERDNS=8.8.8.8,10.1.2.1
INTERNAL_SUBNET=10.1.2.0/24
MTU=1380
KEEP_ALIVE=10
ALLOWEDIPS=10.1.2.0/24
SERVER_ALLOWEDIPS_PEER_PublicServer=10.0.16.0/24

Nginx固有の環境変数

ここで設定する環境変数は、以下の10点となります。

環境変数名説明補足
MYDNSJP_MASTER_IDMyDNSのmaster idオプション。Let's EncryptでSSL証明書を取得する際に利用
MYDNSJP_PASSWORDMyDNSのpasswordオプション。Let's EncryptでSSL証明書を取得する際に利用
BASE_DOMAIN_NAMEFQDN-
VHOST_NAMEVirtual hostnameWebサイトへのアクセス時に利用するhostname
SSL_CERT_PATHcrtファイルパスNginxの設定ファイルで利用
SSL_CERTKEY_PATHkeyファイルパスNginxの設定ファイルで利用
SSL_STAPLING_VERIFYOCSP(証明書の失効状態を取得するための通信プロトコル)の検証有無(on/offによる設定)Nginxの設定ファイルで利用
SSL_TRUSTED_CERTIFICATE_PATHtrusted CA certificatesで利用する際のファイルパス(ssl_stapling有効時に参照される)Nginxの設定ファイルで利用
PUBLIC_SERVER_IP_ADDRVPN Clientで公開するサーバのIPアドレスNginxの設定ファイルで利用
PUBLIC_SERVER_PORTVPN Clientで公開するサーバで待ち受ける際のポート番号Nginxの設定ファイルで利用
Nginx固有の環境変数

上記に対し、下記のように設定し、envs/nginx/.envに保存します。

ここで、オプションとしているMyDNSのIDやパスワード等は、ご自身の環境に合わせて設定してください。

MYDNSJP_MASTER_ID=masterid
MYDNSJP_PASSWORD=password
BASE_DOMAIN_NAME=example.com
VHOST_NAME=www.example.com
SSL_CERT_PATH=/etc/letsencrypt/live/example.com/fullchain.pem
SSL_CERTKEY_PATH=/etc/letsencrypt/live/example.com/privkey.pem
SSL_STAPLING_VERIFY=on
SSL_TRUSTED_CERTIFICATE_PATH=/etc/letsencrypt/live/example.com/chain.pem
PUBLIC_SERVER_IP_ADDR=10.0.16.3
PUBLIC_SERVER_PORT=8080

Let's Encryptの設定・NginxのDocker Image作成

ここでは、Let's Encrypt向けの設定とNginxのDocker Image作成について説明します。

Let's Encryptの設定

nginxのディレクトリに移動し、sample.cli.iniをコピーします。

# nginxのディレクトリへ移動
cd nginx
# sample.cli.iniのコピー
cp -f sample.cli.ini cli.ini

そして、cli.iniをエディタで開き、emailの部分を修正します。

これは、Let's Encryptからメールを受信する際に利用します。

# Set E-mail
email = foo@example.com # ←自身の環境に合わせて修正

また、Let's EncryptのSSL証明書更新時に使用する設定ファイルもあわせて修正します。

MyDNSを利用する方

環境変数MYDNSJP_MASTER_IDMYDNSJP_PASSWORDを設定してください。

MyDNS以外を利用する方

チャレンジ方式(現時点では、DNS-01を指定)に合わせて、各自、スクリプトファイルを用意してください。

また、Dockerfileとcli.iniのそれぞれに対し、該当行を環境に合わせて修正してください。

# Dockerfile
# add dns-01 script
COPY ./direct_edit /data/direct_edit # ←環境に合わせて使用するスクリプトに変更
# cli.ini
# 以下を環境に合わせて修正
authenticator = manual
preferred-challenges = dns
manual-auth-hook = /data/direct_edit/txtregist.php
manual-cleanup-hook = /data/direct_edit/txtdelete.php

NginxのDocker Image作成

wrapper.shがあるディレクトリに移動し、以下のコマンドを実行します。

chmod +x wrapper.sh
./wrapper.sh build

VPN Serverのiptablesの設定

wireguard/iptables_scriptに移動し、conf.up.dconf.down.dにそれぞれ以下のようなconfファイルを作成し、保存してください。

ここで、10.0.16.0/24は、環境変数SERVER_ALLOWEDIPS_PEER_PublicServerPUBLIC_SERVER_IP_ADDRと同じサブネットに属するように設定してください。

基本的には、環境変数SERVER_ALLOWEDIPS_PEER_PublicServerと同じ内容を設定しておけば問題ないです。

conf.up.d

conf.up.d/01-forwarding-to-public-server.confに以下の内容を記載し、保存します。

iptables -t nat -A POSTROUTING -d 10.0.16.0/24 -j MASQUERADE

conf.down.d

conf.down.d/01-forwarding-to-public-server.confに以下の内容を記載し、保存します。

iptables -t nat -D POSTROUTING -d 10.0.16.0/24 -j MASQUERADE

VPN Serverの起動

VPS上で以下のコマンドを実行し、VPN ServerとNginx (Reverse Proxy) を起動します。

./wrapper.sh start

正常に起動している場合、wireguard直下に以下のディレクトリ/ファイルが生成されます。

ls wireguard
coredns peer_PublicServer server templates wg0.conf

また、wireguard/wg0.confwireguard/peer_PublicServer/peer_PublicServer.confは以下のようになっていると思います。

wireguard/wg0.conf

[Interface]
Address = 10.1.2.1
ListenPort = 51820
MTU = 1380
PrivateKey = 
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth+ -j MASQUERADE; iptables -A FORWARD -i %i -o %i -j ACCEPT
PostUp = /config/iptables_script/postup.sh
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth+ -j MASQUERADE; iptables -D FORWARD -i %i -o %i -j ACCEPT
PostDown = /config/iptables_script/postdown.sh
[Peer]
# peer_PublicServer
PublicKey = 
PresharedKey = 
AllowedIPs = 10.1.2.2/32,10.0.16.0/24

ここで、PostUpPostDownはそれぞれ1行で表現してください。

# 以下は1行で表現すること
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth+ -j MASQUERADE; iptables -A FORWARD -i %i -o %i -j ACCEPT
# 以下は1行で表現すること
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth+ -j MASQUERADE; iptables -D FORWARD -i %i -o %i -j ACCEPT

wireguard/peer_PublicServer/peer_PublicServer.conf

[Interface]
Address = 10.1.2.2
PrivateKey = 
ListenPort = 51820
MTU = 1380
DNS = 8.8.8.8,10.1.2.1
[Peer]
PublicKey = 
PresharedKey = 
Endpoint = example.vpn.com:51820
AllowedIPs = 10.1.2.0/24
PersistentKeepAlive = 10

このうち、wireguard/peer_PublicServer/peer_PublicServer.confは、VPN Clientで利用します。

ポート開放

現時点では、外部からの通信をファイアウォールで遮断しているため、以下のコマンドを実行し、ポート開放をします。

# HTTP通信向けの設定
sudo ufw allow 443/tcp

# WireGuard向けの設定
sudo ufw allow 51280/udp

VPN Clientの設定・構築

VPN Clientを構築する上では、以下の5点に対応する必要があります。

このうちUIDGIDの設定方法はすでに解説済みのため、2つ目以降について解説します。

  • WireGuardを起動する際のUIDGIDを設定する。
  • VPN Server側で作成されたconfigファイルを格納・修正する。
  • VPN Client構築時の環境変数(Nginx)を設定する。
  • docker-compose.ymlを作成する。
  • Docker Imageを作成する。(Nginxのみ)

また、該当するコードは、GitHubの下記に保存してあります。

https://github.com/yuruto-free/wireguard-client/tree/v0.1.0

configファイルの格納・修正

wireguard-client直下にconfigというディレクトリがあります。

このconfig直下にpeer_PublicServer.confの内容をwg0.confというファイル名で保存します。

その後、wg.confInterfaceの末尾に、以下の2行を追加します。

これは、VPN ClientでIP MasqueradeによりIPアドレスを変換するために必要となります。

PostUp = iptables -t nat -A POSTROUTING -d 10.0.16.0/24 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -d 10.0.16.0/24 -j MASQUERADE

上記の修正を行うと、config/wg0.confの内容は、以下のようになります。

[Interface]
Address = 10.1.2.2
PrivateKey = 
ListenPort = 51820
MTU = 1380
DNS = 8.8.8.8,10.1.2.1
PostUp = iptables -t nat -A POSTROUTING -d 10.0.16.0/24 -j MASQUERADE   # 追加部分
PostDown = iptables -t nat -D POSTROUTING -d 10.0.16.0/24 -j MASQUERADE # 追加部分
[Peer]
PublicKey = 
PresharedKey = 
Endpoint = example.vpn.com:51820
AllowedIPs = 10.1.2.0/24
PersistentKeepAlive = 10

VPN Clientの環境変数設定

ここで設定する環境変数は以下の2点となります。

環境変数名説明
SERVER_HOSTNAMEVPN Clientで公開するサーバのIPアドレス
SERVER_PORTVPN Clientで公開するサーバで待ち受ける際のポート番号
Nginx(VPN Client)で参照する環境変数

ここでは、下記のように設定し、envs/nginx/.envに保存します。

SERVER_HOSTNAME=_
SERVER_PORT=8080

docker-compose.ymlの作成

今回は、Docker環境下でWireGuard ClientとNginxを動作させるため、bridge-mode.ymlファイルをdocker-compose.ymlとして利用します。

このため、以下のコマンドを適用します。

cp -f bridge-mode.yml docker-compose.yml

Docker Imageの作成

以下のコマンドを実行し、Docker Imageを作成します。

docker-compose build --no-cache

VPN Clientの起動

自宅サーバ上で以下のコマンドを実行し、VPN ClientとNginx (Web) を起動します。

docker-compose up -d

起動後、docker-compose logs wireguardのコマンドを実行し、「Client mode」で起動していることを確認してください。

wireguard  | -------------------------------------
wireguard  | GID/UID
wireguard  | -------------------------------------
wireguard  |
wireguard  | User uid:    1000
wireguard  | User gid:    1000
wireguard  | -------------------------------------
wireguard  |
wireguard  | Uname info: Linux 7430de24220f 5.15.61-v7+ #1579 SMP Fri Aug 26 11:10:59 BST 2022 armv7l armv7l armv7l GNU/Linux
wireguard  | **** It seems the wireguard module is already active. Skipping kernel header install and module compilation. ****
wireguard  | **** Client mode selected. ****
wireguard  | [custom-init] No custom files found, skipping...
wireguard  | **** Disabling CoreDNS ****
wireguard  | Warning: `/config/wg0.conf' is world accessible
wireguard  | [#] ip link add wg0 type wireguard
wireguard  | [#] wg setconf wg0 /dev/fd/63
wireguard  | [#] ip -4 address add 10.1.2.2 dev wg0
wireguard  | [#] ip link set mtu 1380 up dev wg0
wireguard  | [#] resolvconf -a wg0 -m 0 -x
wireguard  | [#] ip -4 route add 10.1.2.0/24 dev wg0
wireguard  | [#] iptables -t nat -A POSTROUTING -d 10.0.16.0/24 -j MASQUERADE
wireguard  | [ls.io-init] done.

参考

`/config/wg0.conf` is world accessible」という警告が出ていますが、この警告は無視しても問題ないです。

これはファイルのパーミッションに関する警告となるため、気になる方はホストマシン上で下記を実行し、ファイルのパーミッションを修正してください。

chmod 600 config/wg0.conf

また、Raspberry PiでVPN Clientを構築している場合、「libseccomp」のエラーが発生する可能性があります。

その場合は、README.mdのFAQを参考に、ライブラリをインストールしてください。

https://github.com/yuruto-free/wireguard-client/blob/v0.1.0/README.md

動作確認

WebブラウザからVPN Serverで設定したVirtual Hostのリンク名でアクセスし、Nginxのトップページが表示されることを確認してください。

今回の例の場合、以下のようになります。こちらのリンクにアクセスしても、Nginxのトップページは表示されないので、気を付けてください。

https://www.example.com

まとめ

今回の実装は、下記のリンク先を参考にしてください。

VPN Server側の実装

https://github.com/yuruto-free/vpnaccess-wireguard-nginx/tree/v0.2.0

VPN Client側の実装

https://github.com/yuruto-free/wireguard-client/tree/v0.1.0

注意点

上記を動作させる際は、環境変数の設定が必要になります。詳細は、同封されているREADME.mdまたは以下を参照してください。

制約事項

ドメインを利用して、自宅サーバへアクセスできるようにするため、Dynamic DNSを利用しています。

このため、SSL証明書取得時に利用しているDynamic DNS(= MyDNS)の設定が含まれています。※詳細はコチラの3行目~11行目を参照してください。

このため、利用時はご自身の環境に合わせて設定の変更をお願いいたします。

例えば、ConoHa VPSで割り当てられているドメイン名を利用する場合、ConoHa API等を参考にドメイン情報を取得する必要があります。

スポンサードリンク

-デバイス
-, , , ,