概要

wg-easyを利用して WireGuard VPNを構築します。

構築する環境

Client PC と Wireguard 間でVPN接続をおこない、Wireguard サーバを経由して、GCPのLAN内にあるApp Serverに接続します。GCP Networkは 10.50.0.0/24 で設定します。

Image

用意するサーバはGCPでなくても構いません。Networkについても 10.50.0.0/24 で設定していますが、ご自身の環境に合わせて設定してください。

事前準備

  • GCP FIrewallで 51820/udp51821/tcp のIngress通信(外部 → GCP)を解放します。
  • Wireguard Serverのインスタンスに外部IPをアタッチして、外部通信ができるようにしておきます。
  • Wireguard ServerのインスタンスでIP転送を有効にしておきます。(GCPではデフォルトでオフに設定されています。)
  • Wireguard Serverのインスタンスに Docker と Docker Compose をインストールします。(参考:https://docs.docker.com/engine/install/

Wireguard VPN Serverのネットワーク

wg-easyでは、Wireguard Server を Docker bridge Network 上で構築しています。以下でネットワークを整理します。

Image

ホストに元々付与されている Interface が ens4 (10.50.0.1/16)で、他サーバーとの通信はこのInterfaceを利用します。 docker0(172.19.0.1/16)はdockerをインストールすると自動的に作成される bridge network のInterfaceです。新たにcontainerを実行した時にデフォルトでは 172.19.0.0/16 ネットワーク帯のIPが付与されたInterfaceが作成されます。上図では、 wg-easy container の eth0(172.19.0.2/16) に対応します。 wg0(192.168.250.1/24) はwireguard用のInterfaceでこのInterfaceを利用してクライアントPCの 192.168.250.2/24 とVPN接続を行います。

wg-easyの設定方法

wg-easyのリポジトリに docker-compose.yaml のサンプルファイルがあります。こちらを参考に、ファイルを作成します。

version: "3.8"
volumes:
  etc_wireguard:

services:
  wg-easy:
    environment:
      - LANG=en
      # ⚠️ Required:
      # Change this to your host's public address
      - WG_HOST=<Host Public IP>
      - WG_DEVICE=eth0
      - PASSWORD=foobar123
      - WG_DEFAULT_ADDRESS=192.168.250.x
      - WG_ALLOWED_IPS=192.168.250.0/24, 10.50.0.0/24
    image: ghcr.io/wg-easy/wg-easy
    container_name: wg-easy
    volumes:
      - ~/.wg-easy:/etc/wireguard
    ports:
      - "51820:51820/udp"
      - "51821:51821/tcp"
    restart: unless-stopped
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    sysctls:
      - net.ipv4.ip_forward=1
      - net.ipv4.conf.all.src_valid_mark=1

環境変数については、最小限の設定にしています。必要な変数がある場合は、こちらを参考に設定します。WG_DEFAULT_ADDRESS は、クライアントIPの取りうるレンジです。末尾の .x の部分がレンジになるので、もしクライアント数が多くてこのレンジに収まらない場合は、 .x.x のように指定する必要があります。 WG_ALLOWED_IPS には、VPN通信に利用するネットワーク192.168.250.0/24とGCP Network 10.50.0.0/24を指定します。このAllowedIPsはクライアントのconfを作成する際に利用されます。

また、上記の設定には表れていませんが、パケットをVPNサーバから他サーバに転送する際には、iptables で FORWARD と MASQUERADE の設定が必要になりますが、wg-easy の Default設定 で実施されるためそのまま利用します。

この設定ファイルを利用して、wg-easyコンテナを起動します。

# docker-compose up -d
# docker ps
CONTAINER ID   IMAGE                     COMMAND                  CREATED          STATUS          PORTS                                                                                          NAMES
ab7211443733   ghcr.io/wg-easy/wg-easy   "docker-entrypoint.s…"   13 minutes ago   Up 13 minutes   0.0.0.0:51820->51820/udp, :::51820->51820/udp, 0.0.0.0:51821->51821/tcp, :::51821->51821/tcp   wg-easy

51820->51820/udp がWireguard用のportで、 51821->51821/tcpがWeb UIのためのPortです。

コンテナが起動したらbashで接続します。

docker exec -it wg-easy /bin/bash

WireguardとInterfaceを確認します。以下、コマンドの結果を載せます。 eth0(172.19.0.2/16)wg0(192.168.250.1/24)インターフェースが作成され、iptablesでFORWARDとMASQUERADEが設定されています。

// wireguard 設定確認
# wg
interface: wg0
  public key: YtPrFXdBAXKm2cWT3EuRXht/bF0raECsmNZqQLMMrGQ=
  private key: (hidden)
  listening port: 51820

// eth0 interface 確認
# ip a show eth0
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:13:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.19.0.2/16 brd 172.19.255.255 scope global eth0
       valid_lft forever preferred_lft forever

// wg0 interface 確認
# ip a show wg0
2: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none
    inet 192.168.250.1/24 scope global wg0
       valid_lft forever preferred_lft forever

// FORWARD設定確認
# iptables -L -v
...
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  wg0    any     anywhere             anywhere
    0     0 ACCEPT     all  --  any    wg0     anywhere             anywhere

// nat テーブル確認
# iptables -L -v -t nat
...
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 MASQUERADE  all  --  any    eth0    192.168.250.0/24     anywhere

クライアントの設定

サーバーの設定が終わったので、クライアントの設定をします。 WireguardのInstallページから各OSに対応するリンクからインストールします。

先ほど構築したサーバのWeb UI にアクセスします。Web UI にはVPNサーバにアクセスできるPublic IPを使って、 <Public IP>:51821 でアクセスできます。パスワードは、docker-compose.yaml に設定したPASSWORD=foobar123を利用します。

あとは、画面に従ってクライアント用の設定ファイルをダウンロードしてインポートします。

Image

動作確認

クライアント端末から、VPNサーバ、App サーバにアクセスして疎通できるか確認します。

// Wireguard VPN Server
# ping -c 3 192.168.250.1
PING 192.168.250.1 (192.168.250.1): 56 data bytes
64 bytes from 192.168.250.1: icmp_seq=0 ttl=64 time=465.156 ms
64 bytes from 192.168.250.1: icmp_seq=1 ttl=64 time=378.526 ms
64 bytes from 192.168.250.1: icmp_seq=2 ttl=64 time=408.049 ms

// App server
# ping -c 10.50.0.11
PING 10.50.0.11 (10.50.0.11): 56 data bytes
64 bytes from 10.50.0.11: icmp_seq=0 ttl=62 time=605.980 ms
64 bytes from 10.50.0.11: icmp_seq=1 ttl=62 time=390.996 ms
64 bytes from 10.50.0.11: icmp_seq=2 ttl=62 time=366.563 ms

以上で設定完了です。複数クライアントを管理したい場合は、wg-easyを使うことで、Web UIからclientファイルの作成ができるため便利そうです。 ~/.wg-easy:/etc/wireguard の設定で、ホストにファイルを保存しているため、このファイルをバックアップすることで簡単に再構築が可能です。