ネットワーク環境は下記のようになっていると仮定する。

ファイアーウォール内環境(192.168.100.0/24)
|
インターネット-外部クライアント
|
自宅(192.168.200.0/24)

ここで、外部クライアントにWireGuardクライアントを入れてファイアーウォール内環境にアクセスしたい。ファイアーウォールのポート開放権限はないが、VPNは繋いで良い、という状況です。

そこで、まず自宅のローカルネットワーク内にラズパイなり適当なUbuntuマシンでWireGuard VPNサーバを立てます。次にファイアーウォール内環境にもUbuntuマシンを設置して自宅のVPNサーバに向けてVPNトンネルを張ります。これで自宅からファイアーウォール内環境にアクセスすることができます。ファイアーウォール内環境は外から中へアクセスすることはできないようになっていますが、中から外へはアクセスできるので、中から外へ向けてトンネルを張ってやれば、トンネル内を通って外から中へアクセスできるようになるわけです。その上で外部クライアントも自宅のVPNサーバに接続すれば、外部クライアントから自宅のVPNサーバ経由でファイアーウォール内環境に接続できるようになります。つまり、以下のように構成します。

ファイアーウォール内環境(192.168.100.0/24)
VPNクライアントWORK(eth0:192.168.100.2,work0:172.16.100.2)
|
インターネット-外部クライアントOUT(out0:172.16.100.3)
|
VPNサーバHOME(eth0:192.168.200.2,home0:172.16.100.1)
自宅(192.168.200.0/24)

なお、上記の図には示していませんが、自宅のローカルネットワークにはルータがあり、必要なUDPポートが開放され、HOMEに向けてポートフォワーディングも設定されているものとします。ポート番号はユーザーポート番号(1024~49151)から適当に決めればいいです。

NTPによる時刻同期の有効化

いずれのマシンもntpで時計合わせはなされるようにしておきましょう。現行のUbuntuでは、systemdに標準で時計合わせ機能timesyncdがあるので、/etc/systemd/timesyncd.confを編集してntpサーバ(ntp.jst.mfeed.ad.jpなど)を指定し、以下のコマンドでtimesyncdを再起動します。

sudo systemctl restart systemd-timesyncd

自宅サーバまたは外部VPSでの設定

UbuntuへのWireGuardのインストールは以下のコマンドで行います。

sudo apt install -y wireguard

Ubuntu上での秘密鍵の生成・公開鍵の生成は、以下のコマンドで行います。

wg genkey > hogehoge.key
cat hogehoge.key | wg pubkey > hogehoge.pub

設定後は削除しておくか、所有者をroot、パーミッションを600に設定して、所有者をroot、パーミッションを700にした/etc/wireguardに置いておきます。

HOMEの/etc/wireguard/home0.confは以下のようになります(/etc/wireguardのパーミッションは700、/etc/wireguard/home0.confのパーミッションは600です)。

[Interface]
PrivateKey = サーバ(HOME)秘密鍵
Address = 172.16.100.1/24
ListenPort = ポート番号
PostUp = iptables -A FORWARD -i home0 -j ACCEPT; iptables -A INPUT -i home0 -j ACCEPT; iptables -t nat -A POSTROUTING -o home0 -j MASQUERADE
PostDown = iptables -D FORWARD -i home0 -j ACCEPT; iptables -D INPUT -i home0 -j ACCEPT; iptables -t nat -D POSTROUTING -o home0 -j MASQUERADE
DNS = 1.1.1.1, 1.0.0.1
Table = off
[Peer]
PublicKey = クライアント(WORK)公開鍵
AllowedIPs = 172.16.100.2/32, 192.168.100.0/24
[Peer]
PublicKey = クライアント(OUT)公開鍵(後述)
AllowedIPs = 172.16.100.3/32

ここで特に重要なのは、PostUp・PostDownによるルーティング設定と、AllowedIPsの設定です。AllowedIPsには、「そのマシンからVPNを通じて通信を繋ぐ宛先」を書きます。DNSは内部のDNSサーバでも構いません。また、iptablesでIPフォワーディングを行うように設定しているので、/etc/sysctl.confを編集してnet.ipv4.ip_forward=1とし、以下のコマンドでIPフォワーディングを有効化する必要があります。

sudo sysctl -p

Ubuntu 20.04では、WireGuardからresolvconfが見えない不具合があるため、これを修正するために以下のようにシンボリックリンクを張ります。

sudo ln -s /usr/bin/resolvectl /usr/local/bin/resolvconf

最後に以下のコマンドでデーモンとして起動するのを有効化して動作確認します。

sudo systemctl enable --now wg-quick@home0
sudo ip a
sudo wg show

Dynamic DNSによるDNS自動更新の設定(固定IPある場合は不要)

自宅サーバはIPアドレスが固定ではないことが多いと思います。その場合はDynamic DNSサービスを利用して、固定したドメイン名でIPアドレスが引けるようにする必要があります。うちの場合は自宅のローカルネットワーク内にQNAP NASがあるので、NASによってドメイン名が取得されています。ルータにも同様の機能を持つものがあります。VPSサービスを利用していて固定IPアドレスが振られているならドメイン名を使わず固定IPアドレスを使えばいいです。それらがない場合はNo-IPなどのDynamic DNSサービスで取得し、HOMEにddclientなどをインストールして名前が引けるようにします。インストールは下記のコマンド行えます。

sudo apt install -y ddclient

No-IP用の/etc/ddclient.conf例は以下のようになります(/etc/ddclient.confのパーミッションは600です)。

daemon=60
ssl=yes
protocol=noip
use=web
login=ユーザー名
password='パスワード'
ドメイン名

また、/etc/default/ddclientも以下のように編集する必要があります。

run_dhclient="false"
run_ipup="false"
run_daemon="true"
daemon_interval="60"

以下のコマンドで動作確認、デーモン有効化、状態確認です。

sudo ddclient -daemon=0 -verbose
sudo systemctl enable --now ddclient.service
sudo systemctl status ddclient.service

ファイアーウォール内サーバでの設定

WORKの/etc/wireguard/work0.confは以下のようになります(/etc/wireguardのパーミッションは700、/etc/wireguard/work0.confのパーミッションは600です)。

[Interface]
PrivateKey = クライアント(WORK)秘密鍵
Address = 172.16.100.2/24
PostUp = iptables -A FORWARD -i work0 -j ACCEPT; iptables -A INPUT -i work0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i work0 -j ACCEPT; iptables -D INPUT -i work0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
DNS = 1.1.1.1, 1.0.0.1
[Peer]
PublicKey = サーバ(HOME)公開鍵
AllowedIPs = 172.16.100.1/32
EndPoint = ドメイン名またはグローバルIPアドレス:ポート番号
PersistentKeepalive = 25

ここでもPostUp・PostDownによるルーティング設定と、AllowedIPsの設定がちゃんと通信できるかどうかを決めます。キープアライブの間隔は他の値にしても構いません。IPフォワーディングの有効化・デーモン起動有効化はHOMEと同様に行います。

外部クライアントでの設定

外部クライアントOUTの設定は、Windows・macOSだとすると、クライアント起動画面の「トンネルの追加」から「空のトンネルを追加」を選択します。「名前」はインターフェイス名なので上記の例だとout0になります。ダイアログ上で公開鍵が表示されているので、HOMEの/etc/wireguard/home0.confにはそれを貼り付けます。out0の設定は以下のようになります。

[Interface]
PrivateKey = クライアント(OUT)秘密鍵
Address = 172.16.100.3/24
DNS = 1.1.1.1, 1.0.0.1
[Peer]
PublicKey = サーバ(HOME)公開鍵
AllowedIPs = 172.16.100.1/32, 192.168.100.0/24
EndPoint = ドメイン名:ポート番号
PersistentKeepalive = 25

AllowedIPsの設定がちゃんと通信できるかどうかを決めますので、注意が必要です。

今回の設定例では、192.168.100.0/24へのトラフィックのみがVPNを流れるように記述してありますが、192.168.100.0/24を0.0.0.0/0に置き換えれば、全てのトラフィックをVPN経由にすることも可能です。つまり、特定のWebサイトに対してファイアーウォール内からのアクセスと見せかけることができます。

参考になったページ