WSL上のDebianからWireGuardを使いたい

投稿者: | 2024年9月21日

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

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です