WireGuardはLinuxカーネルモジュールとして動作するが、少なくとも2024/9/21現在においてWSL純正のカーネルは必要なオプションが有効になっていないらしく、なんやかんやで以下のようなエラーが発生し詰まることになる。
/dev/fd/63:6:65-80: Error: Could not process rule: No such file or directory
カスタムカーネルを使ったりオプションを有効化して自分でビルドし直したりする方法もあるようだが、ユーザー空間で実行させる方法が非常に手っ取り早い。
WireGuardはインストール済みであるとする。
またWireGuard自体の細かいセットアップもここでは割愛する。
今回鍵となるのはwireguard-goで、GitHubにはgit cloneしてmakeと書いてあるものの少なくともDebainはaptでインストール出来たため手早い。
# apt install wireguard-go
続いて通常通り /etc/wireguard/wg0.conf を作成するが、[Interface] 部に記載するのは PrivateKey のみで Address や DNS は記載しない。というのもこのファイルでは設定が出来ないためで、後で別途設定する必要がある。
また、 AllowedIPs = 0.0.0.0/0 としているもののこれによって勝手にルーティングはしてくれないため、こちらも後で別途設定する。
[Interface]
PrivateKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#Addressは不要
[Peer]
PublicKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
PresharedKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Endpoint = <接続先のIP>
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
次に wireguard-go でwg0インターフェースを立ち上げる。
これでwg0が出来るものの、以下のようにIPアドレス等がまだ何も設定されていない。
# wireguard-go wg0
┌──────────────────────────────────────────────────────┐
│ │
│ Running wireguard-go is not required because this │
│ kernel has first class support for WireGuard. For │
│ information on installing the kernel module, │
│ please visit: │
│ https://www.wireguard.com/install/ │
│ │
└──────────────────────────────────────────────────────┘
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
~省略~
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
~省略~
3: wg0: <POINTOPOINT,MULTICAST,NOARP> mtu 1420 qdisc noop state DOWN group default qlen 500
link/none
そこで次のようにしてwg0を設定する。IPはCIDR表記で入力する。
ここでは仮に192.168.10.2/24で割り当てたとする。
# ip address add dev wg0 192.168.10.2/24
# wg setconf wg0 /etc/wireguard/wg0.conf
この時点でWireGuardが接続され wg show コマンドから状態が見えるようになるが、まだインターフェースが上がっていないため繋がらない。
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
~省略~
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
~省略~
3: wg0: <POINTOPOINT,MULTICAST,NOARP> mtu 1420 qdisc noop state DOWN group default qlen 500
link/none
inet 192.168.10.2/24 scope global wg0
valid_lft forever preferred_lft forever
# wg show
interface: wg0
public key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
private key: (hidden)
listening port: XXXXX
peer: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
preshared key: (hidden)
endpoint: <接続先のIP>
allowed ips: 0.0.0.0/0
latest handshake: 7 seconds ago
transfer: 92 B received, 244 B sent
persistent keepalive: every 25 seconds
最後にインターフェースを上げたら完了……と思いきやルーティングが設定されていない。
WireGuardに流したい通信を設定してやることでやっと繋がるようになる。例えば192.168.0.0/16宛をWireGuard経由で流すなら次のようにすればいい。
# ip link set up dev wg0
# ip route add 192.168.0.0/16 dev wg0
これで繋がる。やったぜ。
接続を終了するにはwg0インターフェースを飛ばす。
# ip link del wg0
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
~省略~
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
~省略~
とはいえ毎回この工程をするのもダルいので、適当にスクリプトを書いておくと楽。
8行目のsleepは気分で入れているだけなので特に必要ない。
#!/bin/sh
wireguard-go wg0
ip address add dev wg0 192.168.10.2/24
wg setconf wg0 /etc/wireguard/wg0.conf
ip link set up dev wg0
ip route add 192.168.0.0/16 dev wg0
sleep 1
wg show
そしてこのスクリプトをいい感じにするとこう。改変などご自由に……
今wg0があるかどうかを判断してコマンド一発でup/downを切り替える。パス通しておくと完璧だ。
#!/bin/sh
wg_check () {
command=$(ip a | grep wg0:)
if [ "$command" != "" ]; then
return 0 #wg0 is Active
else
return 1 #wg0 is NOT Active
fi
}
wg_up () {
echo "[wgctl] wg0 up\n"
wireguard-go wg0
ip address add dev wg0 192.168.10.2/24
wg setconf wg0 /etc/wireguard/wg0.conf
ip link set up dev wg0
ip route add 192.168.0.0/16 dev wg0
sleep 1
wg show
}
wg_down () {
echo "[wgctl] wg0 down"
ip link del wg0
}
if [ $(id -u) != 0 ] && [ "$1" != "?" ]; then
echo "[wgctl] ERROR: Please run as root"
exit 1
fi
if [ "$1" = "" ]; then
wg_check
if [ $? = 0 ]; then
wg_down
elif [ $? = 1 ]; then
wg_up
else
echo "[wgctl] ERROR: what?"
fi
elif [ "$1" = "up" ]; then
wg_check
if [ $? = 1 ]; then
wg_up
else
echo "[wgctl] wg0 is currently up\n"
wg show
fi
elif [ "$1" = "down" ]; then
wg_check
if [ $? = 0 ]; then
wg_down
else
echo "[wgctl] wg0 is currently down"
fi
elif [ "$1" = "?" ]; then
echo "Usage:"
echo " wgctl [options]\n"
echo "If no options are specified, wgctl switches connections automatically!\n"
echo "Options:"
echo " up Enable WireGuard connections"
echo " down Remove WireGuard connections"
echo " ? Show this help"
else
echo "[wgctl] Invalid argument"
echo " Use \"wgctl ?\" for help"
fi