WireGuard

提供: ArchWiki
2018年12月18日 (火) 19:07時点におけるKusakata (トーク | 投稿記録)による版 (同期)
ナビゲーションに移動 検索に移動

WireGuard のホームページより:

Wireguard は最先端の暗号技術を使用する非常にシンプルで高速な VPN です。IPSec よりも高速・単純・軽量・有用であることを目指しており、面倒なことを避けています。OpenVPN と比べると高いパフォーマンスを発揮します。WireGuard は組み込みインターフェイスからスーパーコンピュータまで様々な環境に対応する汎用の VPN として設計されています。最初は Linux カーネル用にリリースされており、幅広いデプロイが可能なクロスプラットフォームになる予定です。
警告: WireGuard はセキュリティ監査を完全に通過してはおらずプロトコルはまだ変わる可能性があります [1]

インストール

wireguard-tools パッケージをインストールしてください。

ノート: WireGuard はメインラインに入っていないため DKMS によって必要なカーネルモジュールがビルドされます。そのため、先に必要なカーネルヘッダーパッケージをインストールしてください。

使用方法

ここでは以下の構成でピア間のトンネルを設定する方法を説明します:

Peer A Peer B
外部 IP アドレス 10.10.10.1/24 10.10.10.2/24
内部 IP アドレス 10.0.0.1/24 10.0.0.2/24
wireguard 使用ポート UDP/48574 UDP/39814

外部アドレスはあらかじめ用意してください。例えば、ピア A からピア B に ping 10.10.10.2 で ping が通るようにする必要があります。内部アドレスは ip コマンドで作成する新しいアドレスで、WireGuard ネットワーク内で内部的に共有します。IP アドレスの /24CIDR です。

鍵の生成

ノート: 秘密鍵ファイルを保存するときは 600 などのように厳しいパーミッションを使うことを推奨します。

秘密鍵を作成するには:

$ wg genkey > privatekey

公開鍵を作成するには:

$ wg pubkey < privatekey > publickey

もしくは、秘密鍵と公開鍵を同時に作成するには:

$ wg genkey | tee privatekey | wg pubkey > publickey

量子コンピュータが実用化された場合を考慮して、既存の公開鍵暗号に対称鍵暗号のレイヤーを追加するために事前共有鍵を生成することもできます:

# wg genpsk > preshared

Peer A の設定

このピアでは UDP ポート 48574 を開いて内部・外部 IP アドレスと公開鍵を紐づけてピア B からの接続を許可します:

# ip link add dev wg0 type wireguard
# ip addr add 10.0.0.1/24 dev wg0
# wg set wg0 listen-port 48574 private-key ./privatekey
# wg set wg0 peer [Peer B public key] persistent-keepalive 25 allowed-ips 10.0.0.2/32 endpoint 10.10.10.2:39814
# ip link set wg0 up

[Peer B public key]EsnHH9m6RthHSs+sd9uM6eCHe/mMVFaRh93GYadDDnM= という形式で指定してください。allowed-ips はトラフィックの送信を許可するアドレスのリストを指定してください。allowed-ips 0.0.0.0/0 であらゆるアドレスにトラフィックを送信できるようになります。

Peer B の設定

ピア A とほとんど同じですが、wireguard デーモンで使用するのは UDP ポート 39814 でピア A からの接続だけを許可します:

# ip link add dev wg0 type wireguard
# ip addr add 10.0.0.2/24 dev wg0
# wg set wg0 listen-port 39814 private-key ./privatekey
# wg set wg0 peer [Peer A public key] persistent-keepalive 25 allowed-ips 10.0.0.1/32 endpoint 10.10.10.1:48574
# ip link set wg0 up

基本チェック

パラメータを付けずに wg コマンドを呼び出すことで現在の設定を確認できます。

例えば、ピア A で実行すると以下のように表示されます:

peer-a$ wg
interface: wg0
  public key: UguPyBThx/+xMXeTbRYkKlP0Wh/QZT3vTLPOVaaXTD8=
  private key: (hidden)
  listening port: 48574

peer: 9jalV3EEBnVXahro0pRMQ+cHlmjE33Slo9tddzCVtCw=
  endpoint: 10.10.10.2:39814
  allowed ips: 10.0.0.2/32

トンネルの末端にアクセスすることができるはずです:

 peer-a$ ping 10.0.0.2

設定の永続化

showconf を使うことで設定を保存できます:

# wg showconf wg0 > /etc/wireguard/wg0.conf
# wg setconf wg0 /etc/wireguard/wg0.conf

ピア設定例

/etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.1/32
PrivateKey = [CLIENT PRIVATE KEY]

[Peer]
PublicKey = [SERVER PUBLICKEY]
AllowedIPs = 10.0.0.0/24, 10.123.45.0/24, 1234:4567:89ab::/48
Endpoint = [SERVER ENDPOINT]:51820
PersistentKeepalive = 25

systemd-networkd の設定例

/etc/systemd/network/30-wg0.netdev
[NetDev]
Name = wg0
Kind = wireguard
Description = Wireguard

[WireGuard]
PrivateKey = [CLIENT PRIVATE KEY]

[WireGuardPeer]
PublicKey = [SERVER PUBLIC KEY]
PresharedKey = [PRE SHARED KEY]
AllowedIPs = 10.0.0.0/24
Endpoint = [SERVER ENDPOINT]:51820
PersistentKeepalive = 25
/etc/systemd/network/30-wg0.network
[Match]
Name = wg0

[Network]
Address = 10.0.0.3/32
DNS = 10.0.0.1

[Route]
Gateway = 10.0.0.1
Destination = 10.0.0.0/24

VPN サーバーの設定

このセクションでは OpenVPN などと同じように暗号化されたトンネルを使ってサーバー・ネットワークリソースにアクセスできるようにするため、WireGuard の「サーバー」と汎用的な「クライアント」を設定します。サーバーは Linux で稼働させますがクライアントのプラットフォームは複数選択できます (WireGuard プロジェクトは Linux ネイティブや macOS のソフトウェアに加えて iOS や Android プラットフォームのアプリも提供しています)。詳しくは公式プロジェクトの インストールリンク を見てください。

サーバー

サーバー側のマシンではまず IPv4 フォワーディングを有効にしてください:

# sysctl net.ipv4.ip_forward=1

変更を永続化するには /etc/sysctl.d/99-sysctl.confnet.ipv4.ip_forward = 1 を追加します。

インターネットに接続する場合はファイアウォールを設定することが推奨されます:

  • WireGuard が動作するポートの UDP トラフィックを許可してください (例えば 51820/udp のトラフィックを許可)。
  • WireGurad の設定 /etc/wireguard/wg0.conf に転送ポリシーを記述しない場合はファイアウォールで転送ポリシーを設定してください。以下の例はそのまま動作します。

最後に、WAN からアクセスできるようにするため WireGuard のポートをルーターからサーバーの LAN の IP に転送するようにする必要があります。

鍵の生成

サーバーとクライアントの鍵を#鍵の生成で説明しているように生成してください。

サーバーの設定

サーバーの設定ファイルを作成:

ノート: PresharedKey 行は任意です。使用する場合、事前共有鍵をサーバーとクライアントの設定ファイルで設定する必要があります。詳しくは wg の man ページを参照してください。
/etc/wireguard/wg0.conf
[Interface]
Address = 10.200.200.1/24
SaveConfig = true
ListenPort = 51820
PrivateKey = [SERVER PRIVATE KEY]

# note - substitute eth0 in the following lines to match the Internet-facing interface
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
# client foo
PublicKey = [FOO's PUBLIC KEY]
PresharedKey = [PRE-SHARED KEY]
AllowedIPs = 10.200.200.2/32

[Peer]
# client bar
PublicKey = [BAR's PUBLIC KEY]
PresharedKey = [PRE-SHARED KEY]
AllowedIPs = 10.200.200.3/32
ノート: 必要に応じて同じような形式でピアを追加してください。

インターフェイスは手動あるいは systemctl で制御できます。

wg-quick up wg0 でインターフェイスが立ち上がり wg-quick down wg0 で終了します。

systemctl で制御したい場合、wg-quick@.service起動有効化してください。"@" 記号の後ろにサーバーの設定の名前を入力してください。例:

# systemctl start wg-quick@wg0

クライアントの設定

クライアントの設定ファイルを作成:

foo.conf
[Interface]
Address = 10.200.200.2/24
PrivateKey = [FOO's PRIVATE KEY]
DNS = 10.200.200.1

[Peer]
PublicKey = [SERVER PUBLICKEY]
PresharedKey = [PRE-SHARED KEY]
AllowedIPs = 0.0.0.0/0
Endpoint = my.ddns.address.com:51820
bar.conf
[Interface]
Address = 10.200.200.3/24
PrivateKey = [BAR's PRIVATE KEY]
DNS = 10.200.200.1

[Peer]
PublicKey = [SERVER PUBLICKEY]
PresharedKey = [PRE-SHARED KEY]
AllowedIPs = 0.0.0.0/0
Endpoint = my.ddns.address.com:51820
警告: 設定ファイルを作るときは、公開・秘密鍵と Address = の値を適当に置き換えてください。

クライアントがスマートフォンなどの場合、qrencode を使って設定を共有することができます:

$ qrencode -t ansiutf8 < foo.conf
ノート: NetworkManager を使用している場合、NetworkManager-wait-online.service を、systemd-networkd を使用している場合、systemd-networkd-wait-online.service を有効化することでネットワーク接続が有効になってからサービスが実行されるようになります。

トラブルシューティング

ルートが定期的にリセットされる

NetworkManager が WireGuard のインターフェイスを管理しないようにしてください:

/etc/NetworkManager/conf.d/unmanaged.conf
[keyfile]
unmanaged-devices=interface-name:wg0

NetworkManager で切断される

デスクトップの場合、全てのトラフィックを WireGuard のインターフェイス経由にすると切断が発生することがあります。アクセスポイントに新しく接続してしばらくした後に切断が発生します。

デフォルトでは wg-quickopenresolv などの resolvconf プロバイダを使用して新しい DNS エントリを登録します (設定ファイルの DNS キーワード)。しかしながら NetworkManager はデフォルトでは resolvconf を使用しません。新しい DHCP リースが取得されるたびに NetworkManager は DHCP によって提供されたアドレスで全体の DNS アドレスを上書きします。

resolvconf を使う

システムで resolvconf を使っていて接続が切れる場合、NetworkManager が resolvconf を使うように設定してください:

/etc/NetworkManager/conf.d/rc-manager.conf
[main]
rc-manager=resolvconf

dnsmasq を使う

Dnsmasq#openresolv を見てください。

systemd-resolved を使う

2018年9月時点では、systemd-resolvconf による resolvconf 互換モードは wg-quick で機能しません。ただし PostUp フックを使うことで wg-quick から systemd-resolved を使用することはできます。まず NetworkManager で systemd-resolved を使うように設定: NetworkManager#systemd-resolved。それからトンネルの設定を変更:

/etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.2/24  # The client IP from wg0server.conf with the same subnet mask
PrivateKey = [CLIENT PRIVATE KEY]
PostUp = resolvectl domain %i "~."; resolvectl dns %i 10.0.0.1; resolvectl dnssec %i yes

[Peer]
PublicKey = [SERVER PUBLICKEY]
AllowedIPs = 0.0.0.0/0, ::0/0
Endpoint = [SERVER ENDPOINT]:51820
PersistentKeepalive = 25

新しく利用可能になった DNS サーバーに優先度を与えるためにドメイン名は "~." に設定する必要があります。

wg0 が落ちたときに systemd-resolved は自動的に全てのパラメータを戻すため PostDown キーは必要ありません。

ヒントとテクニック

秘密鍵を暗号化して保存

設定ファイルの [Interface] セクションの PrivateKey 行を以下のように置き換えることで pass を使って秘密鍵を暗号化できます:

PostUp = wg set %i private-key <(su user -c "export PASSWORD_STORE_DIR=/path/to/your/store/; pass WireGuard/private-keys/%i")

user はユーザー名に置き換えてください。詳しくは wg-quick(8) を参照。

IP が変わるエンドポイント

サーバーのドメインの解決後、WireGuard は DNS で再度変更をチェックすることはありません [2]

WireGuard サーバーの IP アドレスが DHCP, Dyndns, IPv6 などによって頻繁に変更された場合、WireGuard クライアントは接続を失います。その際 wg set "$INTERFACE" peer "$PUBLIC_KEY" endpoint "$ENDPOINT" などのようにエンドポイントを更新しなくてはなりません。

また、エンドポイントがアドレスを変更したとき (例えば新しいプロバイダ・データセンターに移行した場合)、DNS を更新するだけでは不十分となるため、DNS ベースのセットアップでは reresolve-dns を定期的に実行する必要が出てきます。

wireguard-tools には WG の設定ファイルを読み込んでエンドポイントのアドレスを自動的にリセットするスクリプト /usr/share/wireguard/examples/reresolve-dns/reresolve-dns.sh が含まれています。

/usr/share/wireguard/examples/reresolve-dns/reresolve-dns.sh /etc/wireguard/wg.conf を定期的に実行することで IP が変わったエンドポイントから復旧できます。

systemd タイマーを使って30秒ごとに WireGuard のエンドポイントを更新する例 [3]:

/etc/systemd/system/wireguard_reresolve-dns.timer
[Unit]
Description=Periodically reresolve DNS of all WireGuard endpoints

[Timer]
OnCalendar=*:*:0/30

[Install]
WantedBy=timers.target
/etc/systemd/system/wireguard_reresolve-dns.service
[Unit]
Description=Reresolve DNS of all WireGuard endpoints
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'for i in /etc/wireguard/*.conf; do /usr/share/wireguard/examples/reresolve-dns/reresolve-dns.sh "\$i"; done'

上記ファイルを作成したら wireguard_reresolve-dns.timer起動有効化してください。