BoringTun で WireGuard を使う
Cloudflare が先日公開した WireGuard の Rust 実装である BoringTun を使って VPN 接続できるかを検証した。WireGuard 自体使うのが初めてだったが、結果としてはうまく接続できた。
ネットワーク構成
以下のような構成で仮想マシンを構築し、client から hidden に VPN を介して接続する。今回は server が WireGuard サーバーになり、client が WireGuard クライアントになる。
+---------------+ +---------------+ +---------------+
| client | | server | | hidden |
| 192.168.10.12 |<-->| 192.168.10.11 | | |
| | | 192.168.20.11 |<-->| 192.168.20.12 |
+---------------+ +---------------+ +---------------+
セットアップ
各マシンのセットアップをしていく。今回は全てのマシンで Ubuntu 18.04 を使用する。
まず最初に hidden サーバーに以下のようにして nginx をインストールしておく。hidden サーバーのセットアップはこれで完了。
$ sudo apt update
$ sudo apt install -y nginx
次に、server と client で以下のようにして、WireGuard をパッケージをインストールする。このパッケージで WireGuard のカーネルモジュールがインストールされるので、これだけで WireGuard 自体は利用可能だったりするのだけど、今回はあえてさらに BoringTun を使ってみる。
$ sudo add-apt-repository ppa:wireguard/wireguard
$ sudo apt install -y wireguard-tools
次に BoringTun をビルドするために、Rust をインストールする。
$ curl https://sh.rustup.rs -sSf | sh
$ source $HOME/.cargo/env
Rust のインストールが完了したら、BoringTun をビルドしてインストールする。
$ git clone https://github.com/cloudflare/boringtun
$ cd boringtun
$ cargo build --bin boringtun --release
$ sudo cp ./target/release/boringtun /usr/local/bin/boringtun
最後に WireGuard で利用する鍵ペアを生成しておく。server と client でそれぞれ別の鍵ペアを生成する必要があることに注意する。
$ umask 077
$ wg genkey | tee private-key | wg pubkey > public-key
これで全てのマシンのセットアップが完了した。
WireGuard サーバーの起動
つづいて、server で WireGuard サーバーを起動する。デバイス名 wg0
を指定して boringtun
コマンドを起動する。
$ sudo /usr/local/bin/boringtun wg0
次に WireGuard のデバイスを設定する wg
コマンドを使用して、接続情報を次のように設定する。${CLIENT_PUBLIC_KEY}
には client で生成した公開鍵の値 (ファイルパスではなく値であることに注意) を指定する。allowed-ips
の値は client の WireGuard デバイスに付与する IP アドレスを指定する。
$ sudo wg set wg0 \
listen-port 51820 \
private-key private-key \
peer "${CLIENT_PUBLIC_KEY}" \
allowed-ips 172.16.1.2/32
設定が正しく反映されているかは wg
コマンドで確認できる。
interface: wg0
public key: lbwK4p0cLAqFaHFJSkOLkq0geLukzEMZdHWOnn5dLnc=
private key: (hidden)
listening port: 51820
peer: S9TZo5n6X+/NEaXPwYTe2NS84Tp69a7CHAsSB8N3JGQ=
allowed ips: 172.16.1.2/32
WireGuard の設定が完了したら、デバイスに IP アドレスを付与して起動する。
$ sudo ip addr add 172.16.1.1/24 dev wg0
$ sudo ip link set up wg0
今回 server は hidden への通信を中継するので、IP マスカレードを有効にしておく。wg0
で受けたパケットを enp0s9
に転送する場合は以下のようになる。このあたりの設定はネットワーク構成によって変わってきそう。
$ sudo sh -c 'echo 1 > /proc/sys/net/ipv4/ip_forward'
$ sudo iptables -A FORWARD -i wg0 -j ACCEPT
$ sudo iptables -t nat -A POSTROUTING -o enp0s9 -j MASQUERADE
これで WireGuard サーバーとして使えるようになった。
WireGuard クライアントの接続
最後に client から server の WireGuard サーバーに接続する。サーバーと同様に、まず boringtun
コマンドを起動する。
$ sudo /usr/local/bin/boringtun wg0
次に wg
コマンドを使用して、クライアント用の設定をする。サーバーとは反対に ``${SERVER_PUBLIC_KEY} に *server* の公開鍵の値を指定する。
allowed-ips には *server* の先にいるネットワーク IP アドレスを指定しておく。
endpoint` には WireGuard サーバーのアドレスを指定する。
$ sudo wg set wg0 \
private-key private-key \
peer "${SERVER_PUBLIC_KEY}" \
allowed-ips 0.0.0.0/0 \
endpoint 192.168.10.12:51820
wg
コマンドを実行して設定した内容を確認しておく。
$ sudo wg
interface: wg0
public key: S9TZo5n6X+/NEaXPwYTe2NS84Tp69a7CHAsSB8N3JGQ=
private key: (hidden)
listening port: 32958
peer: lbwK4p0cLAqFaHFJSkOLkq0geLukzEMZdHWOnn5dLnc=
endpoint: 192.168.10.12:51820
allowed ips: 0.0.0.0/0
設定が完了したら、デバイスに IP アドレスを付与して起動する。
$ sudo ip addr add 172.16.1.2/24 dev wg0
$ sudo ip link set up wg0
デバイスが起動したら、wg0
デバイス経由で、WireGuard サーバーに接続できる。
$ ping 172.16.1.1
PING 172.16.1.1 (172.16.1.1) 56(84) bytes of data.
64 bytes from 172.16.1.1: icmp_seq=2 ttl=64 time=0.757 ms
64 bytes from 172.16.1.1: icmp_seq=3 ttl=64 time=0.631 ms
...
client は hidden サーバーのネットワークに対するルーティング情報を持たないので、以下のようにして設定する。
$ sudo ip route add 192.168.20.0/24 via 172.16.1.2
hidden サーバーの nginx に HTTP リクエストを送信すると、WireGuard 経由でレスポンスを取得できた。
$ curl --head http://192.168.20.12
HTTP/1.1 200 OK
Server: nginx/1.14.0 (Ubuntu)
Date: Mon, 08 Apr 2019 12:18:47 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Mon, 08 Apr 2019 12:17:50 GMT
Connection: keep-alive
ETag: "5cab3bee-264"
Accept-Ranges: bytes
まとめ
BoringTun を使って WireGuard による VPN 環境を構築できた。BoringTun はまだ荒削りな印象がものの、ユーザー空間で動作するので WireGuard クライアントとして利用するとよさそう。ただ自前ビルドが面倒なので公式リリースに期待したい。WireGuard はシンプルな仕組みで使い勝手がいいことが分かったので今後も使っていきたい。コンテナとの相性もよさそうだ。