みーのぺーじ

みーが趣味でやっているPCやソフトウェアについて.Python, Javascript, Processing, Unityなど.

WireGuardで理想のVPNを目指す

OpenVPNのpacket loss

以前OpenVPN Cloudを利用してVPNを作成し,使用していたのですが,通信が安定しませんでした.2拠点間の通信をpingコマンドで確認したところ,18.4% packet loss という結果でした.同時にそれぞれの拠点からgoogle.comに対してpingコマンドを実行したところ,packet lossはありませんでした.OpenVPNが関与するとpacket lossが発生するわけです.

--- 10.0.0.2 ping statistics ---
38 packets transmitted, 31 packets received, 18.4% packet loss
round-trip min/avg/max/stddev = 34.296/86.453/141.667/30.424 ms

みーの設定がいまいちだったのかもしれませんが,どうしても解決できなかったので,WireGuardを使用してみることにしました.

WireGuardでVPNを構築する

Global IP アドレスを付与したRaspberry PIをサーバーとして使用します.WireGuardを設定し,サービスとして登録し,常時実行するようにします.

サーバーのIPアドレスを設定

Ubuntu 20.04.4 LTS (GNU/Linux 5.4.0-1065-raspi aarch64)

$ sudo apt install wireguard

$ cat /etc/netplan/50-cloud-init.yaml
network:
  ethernets:
    eth0:
      dhcp4: true
      optional: true
  version: 2

$ cat /etc/netplan/60-global.yaml
network:
  version: 2
  ethernets:
    eth0:
      addresses:
        - xx.xx.xx.xx/24
      nameservers:
        addresses: [ ... ]
      routes:
        - to: default
          via: xx.xx.xx.yy

$ sudo netplan apply
$ ip addr
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether dc:a6:32:xx:xx:xx brd ff:ff:ff:ff:ff:ff
    inet xx.xx.xx.xx/24 brd xx.xx.xx.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet zz.zz.zz.zz/18 brd zz.zz.zz.255 scope global dynamic eth0
       valid_lft 604584sec preferred_lft 604584sec

まず,上記の如くnetplan.ioを用いて,グローバルIPアドレスxx.xx.xx.xxおよびローカルエリアネットワーク(LAN)用のプライベートIP アドレスzz.zz.zz.zzをeth0に付与しました.

グローバルIPアドレスはあまり管理したくないので,適当にドメインを取得してDNSレコードに登録しておくと便利です.以下ではserver.example.comに対してAレコードをxx.xx.xx.xxで設定することを前提とします.

WireGuardを設定

公式サイトに記載されている方法に従ってwg0.confを作成します.なお,以下のキーはテスト用の値です.

$ wg genkey | tee privatekey | wg pubkey > publickey
$ ls
privatekey  publickey
$ cat privatekey
SJXOK9m2xB5pLZ5RMG7a0RjLhyxSsDFmwgDMgfkCwUA=
$ cat publickey
bkXTeN98sJGeE4YACpcclmzDgcFGJeZQlItli2ejqzo=
$ nano wg0.conf

Serverのwg0.conf

[Interface]
Address = 10.0.0.1/32
ListenPort = 51820
PrivateKey = [Server PRIVATE KEY]

[Peer]
# Client
PublicKey = [Client PUBLIC KEY]
AllowedIPs = 10.0.0.2/32
Endpoint = zz.zz.zz.aa:51820

Clientのwg0.conf

[Interface]
Address = 10.0.0.2/32
ListenPort = 51820
PrivateKey = [Client PRIVATE KEY]

[Peer]
# Server
PublicKey = [Server PUBLIC KEY]
AllowedIPs = 10.0.0.1/32
Endpoint = server.example.com:51820
# PersistentKeepalive = 25

これら2個の設定において,ClientのEndpoint = server.example.com:51820および,server.example.comはインターネットで名前解決が可能であることから,ClientからServerへのアクセスが可能になります.したがって,Endpointはserver.example.com:51820のみ指定します.

もしClientがNATの内側に存在する場合は,PersistentKeepalive = 25 を有効にして,定期的に keepalive パケットを送信するようにします.

LANにFORWARDするならばiptablesやufwなどを使用してそのように設定しますが,ひとまずは不要です.

以下のコマンドで動作するか確認します.

$ wg-quick /full/path/to/wg0.conf

$ ip addr
...
4: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none
    inet 10.0.0.1/32 scope global wg0
       valid_lft forever preferred_lft forever

$ ping 10.0.0.2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
...
--- 10.0.0.2 ping statistics ---
15 packets transmitted, 15 received, 0% packet loss, time 14251ms

問題なければ,これを/etc/wireguard/wg0.confにrootをownerとして保存します.プライベートキーが平文で記載されたファイルが外部に漏洩すると大変なので,rootのみが読み書きできるよう最低限のパーミッションを付与します.

$ sudo -s
$ chown root:root wg0.conf
$ mv wg0.conf /etc/wireguard/
$ chmod 600 /etc/wireguard/wg0.conf
$ ls /etc/wireguard/ -l
total 4
-rw------- 1 root root 239 Jun  8 17:53 wg0.conf

WireGuardをサービスとして登録

wg-quick@wg0.service は /etc/wireguard/wg0.conf を読み込んでWireGuardを起動してくれますので,systemdのサービスとして有効化します.

$ sudo systemctl enable wg-quick@wg0.service
$ sudo systemctl start wg-quick@wg0.service

ファイアウォールを設定

ufwを使用して51820/udpの通信を許可します.

$ sudo ufw allow 51820/udp
$ sudo ufw status verbose
51820/udp                  ALLOW IN    Anywhere

OpenVPNとWireGuardの比較

同じ2拠点間においてOpenVPNまたはWireGuardを用いてVPNを作成し,pingコマンドで往復の通信状況を確認しました.

OpenVPN

冒頭のデータと同じです.

--- 10.0.0.2 ping statistics ---
38 packets transmitted, 31 packets received, 18.4% packet loss
round-trip min/avg/max/stddev = 34.296/86.453/141.667/30.424 ms

WireGuard

--- 10.0.0.2 ping statistics ---
35 packets transmitted, 35 received, 0% packet loss, time 34051ms
rtt min/avg/max/mdev = 12.712/70.402/119.046/30.159 ms

packet lossがなくなりました.安定した通信ができているようです.レイテンシは同じぐらいでした.

各OSのClient

WireGuardのClientはとても充実しており,有名なOSならばそのまま使用できるように開発されています.

Installation - WireGuard

Linuxならばコマンドでもよいですが,MacOSやWindowsならばマウスで操作できると便利なので,このあたりの使い勝手もよいです.

MacOS

WireGuard

WireGuard

  • WireGuard Development Team
  • ユーティリティ
  • 無料
apps.apple.com

GUIによる設定が可能で,直感的にWireGuardの切り替えが可能です.

また,汎用的なVPNなので,MacOSのシステム環境設定のネットワークにも馴染むよう設計されています.

参考