この記事はLinuxで作るL2TP/WireGuardネットワークの一部です。

今からVPN作るならやっぱりWireGuardですよね~ということで、WireGuardでL3VPNを作ります。 ごくふつうのWireGuardの使い方の通りなので、目新しいものはありません。

事前に用意するもの

  • てきとうなLinuxサーバ2台
    • L2TPを話すサーバ2台(vpn01, vpn02)
    • 今回はubuntu 22.04(5.15.0-30-generic)とAlpine Linux(5.15.40-0-virt)で確認
    • vpn02からvpn01へは相互に通信できる状態としておく
  • wireguard-tools
  • 自由に使えるプライベートIPアドレス範囲
    • WAN側(実験用): 192.168.122.0/24
    • VPN: 10.0.1.0/24

ネットワーク構成

  • VPNサーバ(vpn01)
    • eth0(WAN側): 192.168.122.24/24
    • wg0(VPN側): 10.0.1.11/24
  • VPNクライアント(vpn02)
    • eth0(WAN側): 192.168.122.32/24
    • wg0(VPN側): 10.0.1.21/24

WireGuardにL3VPN ネットワーク図

鍵ペアの生成

vpn01とvpn02の鍵ペアをそれぞれ生成し、加えて事前共有鍵も生成します。

1
2
3
% wg genkey | tee vpn01.key | wg pubkey > vpn01.pub
% wg genkey | tee vpn02.key | wg pubkey > vpn02.pub
% wg genpsk > vpn02.psk

それぞれが持つ鍵は次の通りです。

  • vpn01
    • vpn01.key(VPN01の秘密鍵)
    • vpn02.pub(VPN02の公開鍵)
    • vpn02.psk(VPN02との事前共有鍵)
  • vpn02
    • vpn02.key(VPN02の秘密鍵)
    • vpn01.pub(VPN01の公開鍵)
    • vpn02.psk(VPN01との事前共有鍵)

今回サンプルで利用する鍵データは次の通りです。

1
2
3
4
5
6
% grep "" vpn0?.*
vpn01.key:GJspDd9brXB1f3wcn17h6X/rsBDegHjULzypDxOEDl4=
vpn01.pub:+BBEy1MjXwXtaIXNodhGTSKAA+83U0F9JYj5/v9PZFk=
vpn02.key:cA3EYCKACEx/o00I+ym/MQUAfe223mtFTDxizvsgh1I=
vpn02.psk:Ym9RCnmJq1OMXtK8dkyUaMvSKTFi4HLBufEjJuxbE1k=
vpn02.pub:BAvxl5NXctUX7cJc1kjEG306846fIMFERsRdWazhGis=

秘密鍵と事前共有鍵は漏らさないよう注意しましょう。

vpn01(サーバ側)

サーバ側の設定ファイル(vpn01の/etc/wireguard/wg0.conf)を作成します。 クライアント側との違いはInterfaceブロックのListenPortPeerブロックのEndpointの有無です。

1
2
3
4
5
6
7
8
9
10
11
[Interface]
Address = 10.0.1.11/24
MTU = 1440
ListenPort = 8172
PrivateKey = GJspDd9brXB1f3wcn17h6X/rsBDegHjULzypDxOEDl4=

[Peer]
PublicKey = BAvxl5NXctUX7cJc1kjEG306846fIMFERsRdWazhGis=
PresharedKey = Ym9RCnmJq1OMXtK8dkyUaMvSKTFi4HLBufEjJuxbE1k=
AllowedIPs = 10.0.1.21/32
PersistentKeepalive = 25

設定ファイルが記述できたら、rootのみが読み書きできるようにします。 その後、wg-quickコマンドでwg0インタフェースを開始します。

1
2
3
4
5
6
vpn01% sudo chmod 600 /etc/wireguard/wg0.conf
vpn01% sudo wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.0.1.11/24 dev wg0
[#] ip link set mtu 1440 up dev wg0

設定の確認

wg showwg showconfで現在の設定状況を確認できます。

1
2
3
4
5
6
7
8
9
10
vpn01% sudo wg show
interface: wg0
  public key: +BBEy1MjXwXtaIXNodhGTSKAA+83U0F9JYj5/v9PZFk=
  private key: (hidden)
  listening port: 8172

peer: BAvxl5NXctUX7cJc1kjEG306846fIMFERsRdWazhGis=
  preshared key: (hidden)
  allowed ips: 10.0.1.21/32
  persistent keepalive: every 25 seconds
1
2
3
4
5
6
7
8
9
10
vpn01% sudo wg showconf wg0
[Interface]
ListenPort = 8172
PrivateKey = GJspDd9brXB1f3wcn17h6X/rsBDegHjULzypDxOEDl4=

[Peer]
PublicKey = BAvxl5NXctUX7cJc1kjEG306846fIMFERsRdWazhGis=
PresharedKey = Ym9RCnmJq1OMXtK8dkyUaMvSKTFi4HLBufEjJuxbE1k=
AllowedIPs = 10.0.1.21/32
PersistentKeepalive = 25
1
2
3
4
5
vpn01% ip a s dev wg0
4: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1440 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none 
    inet 10.0.1.11/24 scope global wg0
       valid_lft forever preferred_lft forever

vpn02(クライアント側)

クライアント側の設定ファイル(vpn02の/etc/wireguard/wg0.conf)を作成します。 PeerのAllowedIPsのサブネットマスクを/24としているのは、将来他のVPNクライアントが追加された時に相互通信ができるようにするためです。

1
2
3
4
5
6
7
8
9
10
11
12
[Interface]
Address = 10.0.1.21/24
PrivateKey = cA3EYCKACEx/o00I+ym/MQUAfe223mtFTDxizvsgh1I=
# ClientPublicKey = BAvxl5NXctUX7cJc1kjEG306846fIMFERsRdWazhGis=
MTU = 1440

[Peer]
PublicKey    = +BBEy1MjXwXtaIXNodhGTSKAA+83U0F9JYj5/v9PZFk=
PresharedKey = Ym9RCnmJq1OMXtK8dkyUaMvSKTFi4HLBufEjJuxbE1k=
AllowedIPs   = 10.0.1.0/24
Endpoint     = 192.168.122.24:8172
PersistentKeepalive = 25

vpn01と同様に設定ファイルのアクセス権限を設定し、wg0インタフェースを開始します。

1
2
3
4
5
6
vpn01% sudo chmod 600 /etc/wireguard/wg0.conf
vpn01% sudo wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.0.1.21/24 dev wg0
[#] ip link set mtu 1440 up dev wg0

設定の確認

vpn01と同様に設定を確認します。 うまく設定できていれば、この時点で通信できるはずです。

1
2
3
4
5
6
7
8
9
10
11
12
13
vpn02% sudo wg show
interface: wg0
  public key: BAvxl5NXctUX7cJc1kjEG306846fIMFERsRdWazhGis=
  private key: (hidden)
  listening port: 44507

peer: +BBEy1MjXwXtaIXNodhGTSKAA+83U0F9JYj5/v9PZFk=
  preshared key: (hidden)
  endpoint: 192.168.122.24:8172
  allowed ips: 10.0.1.0/24
  latest handshake: 1 minute, 40 seconds ago
  transfer: 344 B received, 488 B sent
  persistent keepalive: every 25 seconds
1
2
3
4
5
6
7
8
9
10
11
vpn02% sudo wg showconf wg0
[Interface]
ListenPort = 44507
PrivateKey = cA3EYCKACEx/o00I+ym/MQUAfe223mtFTDxizvsgh1I=

[Peer]
PublicKey = +BBEy1MjXwXtaIXNodhGTSKAA+83U0F9JYj5/v9PZFk=
PresharedKey = Ym9RCnmJq1OMXtK8dkyUaMvSKTFi4HLBufEjJuxbE1k=
AllowedIPs = 10.0.1.0/24
Endpoint = 192.168.122.24:8172
PersistentKeepalive = 25
1
2
3
4
5
vpn02% ip a s dev wg0
4: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1440 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none 
    inet 10.0.1.21/24 scope global wg0
       valid_lft forever preferred_lft forever

疎通確認

相互にpingして確認します。

1
2
3
4
5
6
7
8
9
vpn01% ping -c 3 10.0.1.21
PING 10.0.1.21 (10.0.1.21): 56 data bytes
64 bytes from 10.0.1.21: seq=0 ttl=64 time=1.327 ms
64 bytes from 10.0.1.21: seq=1 ttl=64 time=1.334 ms
64 bytes from 10.0.1.21: seq=2 ttl=64 time=1.311 ms

--- 10.0.1.21 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 1.311/1.324/1.334 ms
1
2
3
4
5
6
7
8
9
vpn02% ping -c 3 10.0.1.11
PING 10.0.1.11 (10.0.1.11): 56 data bytes
64 bytes from 10.0.1.11: seq=0 ttl=64 time=1.131 ms
64 bytes from 10.0.1.11: seq=1 ttl=64 time=0.995 ms
64 bytes from 10.0.1.11: seq=2 ttl=64 time=1.505 ms

--- 10.0.1.11 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.995/1.210/1.505 ms

wg0インタフェースに対してtcpdumpするとより分かりやすいかもしれません。

1
2
3
4
5
6
7
8
9
vpn02% sudo tcpdump -i wg0
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on wg0, link-type RAW (Raw IP), snapshot length 262144 bytes
23:18:05.762153 IP 10.0.1.11 > 10.0.1.21: ICMP echo request, id 2138, seq 0, length 64
23:18:05.762252 IP 10.0.1.21 > 10.0.1.11: ICMP echo reply, id 2138, seq 0, length 64
23:18:06.762723 IP 10.0.1.11 > 10.0.1.21: ICMP echo request, id 2138, seq 1, length 64
23:18:06.762827 IP 10.0.1.21 > 10.0.1.11: ICMP echo reply, id 2138, seq 1, length 64
23:18:07.763206 IP 10.0.1.11 > 10.0.1.21: ICMP echo request, id 2138, seq 2, length 64
23:18:07.763303 IP 10.0.1.21 > 10.0.1.11: ICMP echo reply, id 2138, seq 2, length 64

うまく繋がらない時は?

  • IPアドレスやAllowedIPs、鍵の設定に誤りがないか確認
    • ping: sendto: No error informationと出たらこれらを間違えている可能性大
    • ping: sendto: Destination address requiredと出たらまだ接続が確立できていない(待てば繋がる可能性あり)
  • 双方のファイアウォールを確認
    • wg0を通過するパケットを全てdropしてた
    • サーバ側WireGuardのポート(今回は8172)が開いてなかった

参考