「WireGuard」の版間の差分
Kusanaginoturugi (トーク | 投稿記録) |
Kusanaginoturugi (トーク | 投稿記録) (→鍵の生成: 空行を削除) |
||
67行目: | 67行目: | ||
# wg genpsk > preshared |
# wg genpsk > preshared |
||
− | |||
=== 手動設定 === |
=== 手動設定 === |
2023年3月10日 (金) 09:48時点における版
WireGuard のホームページより:
- Wireguard は最先端の暗号技術を使用する非常にシンプルで高速な VPN です。IPSec よりも高速・単純・軽量・有用であることを目指しており、面倒なことを避けています。OpenVPN と比べると高いパフォーマンスを発揮します。WireGuard は組み込みインターフェイスからスーパーコンピュータまで様々な環境に対応する汎用の VPN として設計されています。最初は Linux カーネル用にリリースされましたが、現在はクロスプラットフォーム(Windows、macOS、BSD、iOS、Android)であり、広く展開できます。
この記事で使用されている主な概念の大まかな紹介は、WireGuard のプロジェクトホームページにあります。 WireGuard は、2019年後半から Linux カーネルに組み込まれています。
インストール
ユーザースペースユーティリティの wireguard-tools パッケージをインストールしてください。
または、ピアキーが使用可能な場合、さまざまなネットワークマネージャーが WireGuard のサポートを提供します。詳細については、#設定の永続化 を参照してください。
グラフィカルクライアント
- Qomui — 高度な機能と複数のプロバイダーのサポートを備えた OpenVPN GUI。
コマンドラインツール
- wg_tool — サーバーとユーザーの wireguard 設定を管理するツール。
使用方法
ここでは以下の構成でピア間のトンネルを設定する方法を説明します:
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 アドレスの /24
は CIDR です。
鍵の生成
秘密鍵を作成するには:
$ 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] MTU = 1420 [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.conf
に net.ipv4.ip_forward = 1
を追加します。
インターネットに接続する場合はファイアウォールを設定することが推奨されます:
- WireGuard が動作するポートの UDP トラフィックを許可してください (例えば 51820/udp のトラフィックを許可)。
- WireGurad の設定
/etc/wireguard/wg0.conf
に転送ポリシーを記述しない場合はファイアウォールで転送ポリシーを設定してください。以下の例はそのまま動作します。
最後に、WAN からアクセスできるようにするため WireGuard のポートをルーターからサーバーの LAN の IP に転送するようにする必要があります。
鍵の生成
サーバーとクライアントの鍵を#鍵の生成で説明しているように生成してください。
サーバーの設定
サーバーの設定ファイルを作成:
/etc/wireguard/wg0.conf
[Interface] Address = 10.200.200.1/24 SaveConfig = true ListenPort = 51820 PrivateKey = [SERVER PRIVATE KEY] MTU = 1420 # 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 MTU = 1420 [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 MTU = 1420 [Peer] PublicKey = [SERVER PUBLICKEY] PresharedKey = [PRE-SHARED KEY] AllowedIPs = 0.0.0.0/0 Endpoint = my.ddns.address.com:51820
クライアントがスマートフォンなどの場合、qrencode を使って設定を共有することができます:
$ qrencode -t ansiutf8 < foo.conf
トンネルのテスト
トンネルが確立されたら、netcatを使ってトラフィックを送り、スループットや CPU 使用率などをテストすることができます。
トンネルの片側で nc
を listen モードで実行し、もう片側で /dev/zero
から送信モードの nc
にデータをパイプします。
以下の例では、ポート 2222 がトラフィックに使用されています(ファイアウォールを使用している場合は、ポート2222のトラフィックを必ず許可してください)。
トンネルの片側で、トラフィックを確認する。
$ nc -vvlnp 2222
トンネルの向こう側では、トラフィックを送ってください。
$ dd if=/dev/zero bs=1024K count=1024 | nc -v 10.0.0.203 2222
状態の監視は wg
で直接行うことができます。
# wg
interface: wg0 public key: UguPyBThx/+xMXeTbRYkKlP0Wh/QZT3vTLPOVaaXTD8= private key: (hidden) listening port: 51820 peer: 9jalV3EEBnVXahro0pRMQ+cHlmjE33Slo9tddzCVtCw= preshared key: (hidden) endpoint: 192.168.1.216:53207 allowed ips: 10.0.0.0/0 latest handshake: 1 minutes, 17 seconds ago transfer: 56.43 GiB received, 1.06 TiB sent
ヒントとテクニック
秘密鍵を暗号化して保存
設定ファイルの [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 で再度変更をチェックすることはありません [1]。
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 のエンドポイントを更新する例 [2]:
/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
を起動・有効化してください。
Generate QR code
If the client is a mobile device such as a phone, qrencode can be used to generate client's configuration QR code and display it in terminal:
$ qrencode -t ansiutf8 -r client.conf
デバッグログを有効にする
ダイナミックデバッグをサポートするカーネル上で Linux カーネルモジュールを使用する場合、実行することでデバッグ情報をカーネルリングバッファ(dmesg や journalctl で表示可能)に書き込むことができます。
# modprobe wireguard # echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control
ピア(サーバー)設定の再読み込み
WireGuard ピア(主にサーバ)が設定から他のピアを追加または削除し、アクティブなセッションを停止せずに再読み込みしたい場合、次のコマンドを実行することができます:
# wg syncconf ${WGNET} <(wg-quick strip ${WGNET})
ここで、$WGNET
は WireGuard インターフェース名または設定ベース名です。例えば、wg0
(サーバー用) または client
です。(クライアント用には .conf という拡張子をつけません)。
トラブルシューティング
ルートが定期的にリセットされる
NetworkManager が WireGuard のインターフェイスを管理しないようにしてください:
/etc/NetworkManager/conf.d/unmanaged.conf
[keyfile] unmanaged-devices=interface-name:wg0
Broken DNS resolution
When tunneling all traffic through a WireGuard interface, the connection can become seemingly lost after a while or upon new connection. This could be caused by a network manager or DHCP client overwriting /etc/resolv.conf
.
By default wg-quick uses resolvconf to register new DNS entries (from the DNS
keyword in the configuration file). This will cause issues with network managers and DHCP clients that do not use resolvconf, as they will overwrite /etc/resolv.conf
thus removing the DNS servers added by wg-quick.
The solution is to use networking software that supports resolvconf.
Users of NetworkManager should know that it does not use resolvconf by default. It is recommended to use systemd-resolved. If this is undesirable, install openresolv and configure NetworkManager to use it: NetworkManager#Use openresolv.
Low MTU
Due to too low MTU (lower than 1280), wg-quick may have failed to create the WireGuard interface. This can be solved by setting the MTU value in WireGuard configuration in Interface section on client.
foo.config
[Interface] Address = 10.200.200.2/24 MTU = 1420 PrivateKey = PEER_FOO_PRIVATE_KEY DNS = 10.200.200.1
Key is not the correct length or format
To avoid the following error, put the key value in the configuration file and not the path to the key file.
# wg-quick up wg0
[#] ip link add wg0 type wireguard [#] wg setconf wg0 /dev/fd/63 Key is not the correct length or format: `/path/example.key' Configuration parsing error [#] ip link delete dev wg0
Unable to establish a persistent connection behind NAT / firewall
By default, WireGuard peers remain silent while they do not need to communicate, so peers located behind a NAT and/or firewall may be unreachable from other peers until they reach out to other peers themselves (or the connection may time out). Adding PersistentKeepalive = 25
to the [Peer]
settings of a peer located behind a NAT and/or firewall can ensure that the connection remains open.
# Set the persistent-keepalive via command line (temporarily)
[#] wg set wg0 peer $PUBKEY persistent-keepalive 25
Loop routing
Adding the endpoint IP to the allowed IPs list, the kernel will attempt to send handshakes to said device binding, rather than using the original route. This results in failed handshake attempts.
As a workaround, the correct route to the endpoint needs to be manually added using
ip route add <endpoint ip> via <gateway> dev <network interface>
e.g. for peer B from above in a standard LAN setup:
ip route add 203.0.113.102 via 192.168.0.1 dev eth0
To make this route persistent, the command can be added as PostUp = ip route ...
to the [Interface]
section of wg0.conf
. However, on certain setups (e.g. using wg-quick@.service
in combination with NetworkManager) this might fail on resume. Furthermore, this only works for a static network setup and fails if gateways or devices change (e.g. using ethernet or wifi on a laptop).
Using NetworkManager, a more flexible solution is to start WireGuard using a dispatcher script. As root, create
/etc/NetworkManager/dispatcher.d/50-wg0.sh
#!/bin/sh case $2 in up) wg-quick up wg0 ip route add <endpoint ip> via $IP4_GATEWAY dev $DEVICE_IP_IFACE ;; pre-down) wg-quick down wg0 ;; esac
If not already running, start and enable NetworkManager-dispatcher.service
.
Also, make sure that NetworkManager is not managing routes for wg0
(see above).
NetworkManager で切断される
デスクトップの場合、全てのトラフィックを WireGuard のインターフェイス経由にすると切断が発生することがあります。アクセスポイントに新しく接続してしばらくした後に切断が発生します。
デフォルトでは wg-quick は openresolv などの 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 MTU = 1420 [Peer] PublicKey = [SERVER PUBLICKEY] AllowedIPs = 0.0.0.0/0, ::0/0 Endpoint = [SERVER ENDPOINT]:51820 PersistentKeepalive = 25
新しく利用可能になった DNS サーバーに優先度を与えるためにドメイン名は "~."
に設定する必要があります。
wg0
が落ちたときに systemd-resolved は自動的に全てのパラメータを戻すため PostDown
キーは必要ありません。