🐙

WireGuardを利用したVPN構築

2022/12/30に公開約4,500字

はじめに

今回は、簡単にVPNを構築できる 【WireGuard】 を実際に構築してみたいと思います。

WireGuardとは

以下は、公式ホームページからの抜粋です。
https://www.wireguard.com/

WireGuard® is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache. It intends to be considerably more performant than OpenVPN.

高速・シンプル・高セキュリティを売りにした新しいVPNツールのようです。
確かにIPsecやOpenVPNなどのように、今までメジャーだったものと比較すると、シンプルだなとは思いました。
※理解はまだまだ浅いですが。

今回の構成

自宅では、固定グローバルIPを持っていないので、AWS上に2台のサーバを用意し、VPNで繋いでみたいと思います。

項目 サーバA サーバB
OS AmazonLinux2 AmazonLinux2
外部IPアドレス 13.115.170.181 43.207.47.224
内部IPアドレス 192.168.1.244 172.16.1.91
VPN用IPアドレス 172.16.12.1 172.16.12.2
WireGuard利用ポート 44455 55544
秘密鍵ファイル名 serverkey clientkey
公開鍵ファイル名 serverpubkey clientpubkey

※外部グローバルIPアドレスは、EC2起動時に自動で払い出されるIPアドレスを利用しています。

図にするとこんな感じです。

NW構成図

事前準備(パッケージのインストール)

WireGuardのパッケージは、デフォルトではインストールされていないため、別途インストールする必要があります。
標準リポジトリではなくて、拡張リポジトリ(EPEL)からインストールすることができるので、インストールします。
以下は、AmazonLinux2の場合の手順です。

$ sudo amazon-linux-extras install epel -y
$ sudo yum install wireguard-tools

WireGuardの設定ファイルが格納されるのは/etc/wireguard/ディレクトリですが、パッケージをインストールするだけでは何もファイルはありませんでした。
今回は、上記ディレクトリをワークディレクトリとします。

WireGuard の設定

1. 鍵の作成

WireGuardは共通鍵を利用してVPNを張るので、接続元と接続先それぞれで秘密鍵と公開鍵を作成します。
WireGuardでは、wgコマンドを使って鍵を作成することができます。

# サーバAでの作業
# 秘密鍵の作成
$ wg genkey > serverkey #rootで実行

# 秘密鍵から公開鍵を作成
$ wg pubkey < serverkey > serverpubkey #rootで実行

# 作成したファイルの権限を変更
$ chmod 0600 server* #rootで実行

※サーバBでも同様に鍵を作成します。名前を前述の通り、「clientkey」と「clientpubkey」としています。

2. ネットワークインターフェイスの作成

WireGuardで利用するネットワークインターフェイスを作成します。

# サーバAでの作業
$ ip link add dev wg0 type wireguard #rootで実行

# 以下のように作成されます。
$ ip a #rootで実行
3: wg0: <POINTOPOINT,NOARP> mtu 1420 qdisc noop state DOWN group default qlen 1000
    link/none

# 作成したインターフェイスにIPアドレスを設定します。
$ ip addr add dev wg0 172.16.12.1/24 #rootで実行

$ ip a #rootで実行
3: wg0: <POINTOPOINT,NOARP> mtu 1420 qdisc noop state DOWN group default qlen 1000
    link/none 
    inet 172.16.12.1/24 scope global wg0
       valid_lft forever preferred_lft forever

※サーバBでも同様に作成します。設定は、前述の通りとします。

3. WireGuardの設定

作成したインターフェイスに、WireGuardの設定をしていきます。
なお、WireGuardがVPNを張る時のプロトコルは、「UDP」 を利用しています。

# サーバAでの作業
# WireGuardで待ち受けるポート番号と使用する秘密鍵を指定します。
$ wg set wg0 listen-port 44455 private-key ./serverkey #rootで実行

#サーバBで作成した公開鍵の情報がこの後必要になるため、以下のコマンドをサーバーBで実行して、その結果をメモします。
$ cat clientpukey #サーバBで実行
BBBBBBBB #公開鍵情報

$ wg set wg0 peer BBBBBBBB persistent-keepalive 25 allowed-ips 172.16.12.2/32 endpoint 43.207.47.224:55544 #rootで実行

※サーバBでも同様に設定します。設定は、前述の通りとします。
【補足】
persistent-keepalive: パーシステントの持続時間の設定(秒)。必須ではなく、デフォルトは「off」。指定した時間間隔で、空のパケットをPeerに送信する。
allowed-ips: この説明は、別記事にしたいと思います。
endpoint: 対向のグローバルIPアドレスとポートを指定

以下のコマンドを実行することで、設定の確認が可能です。
【Interface】が自分自身の設定で、【Peer】が対向の設定になります。
Peerは複数設定することが可能なので、1対多でVPNを張ることが可能です。

$ wg showconf wg0 #rootで実行
[Interface]
ListenPort = 44455
PrivateKey = AAAAAAAA

[Peer]
PublicKey = BBBBBBBB
AllowedIPs = 172.16.12.2/32
Endpoint = 43.207.47.224:55544
PersistentKeepalive = 25

4. インターフェイスの起動

サーバAとBの両方で、以下コマンドを実行してインターフェイスを起動させます。

$ ip link set dev wg0 up

5. 疎通確認

ここまでの手順でVPNは張れたので、疎通確認します。

$ ping 172.16.12.2
PING 172.16.12.2 (172.16.12.2) 56(84) bytes of data.
64 bytes from 172.16.12.2: icmp_seq=1 ttl=255 time=0.626 ms
64 bytes from 172.16.12.2: icmp_seq=2 ttl=255 time=0.838 ms
64 bytes from 172.16.12.2: icmp_seq=3 ttl=255 time=0.715 ms

pingが通っていることが確認できました。

ちなみに、wgコマンドを実行する事で、Peerとの通信状況を確認することができます。

$ wg #rootで実行
interface: wg0
  public key: AAAAAA
  private key: (hidden)
  listening port: 44455

peer: BBBBBB
  endpoint: 43.207.47.224:55544
  allowed ips: 172.16.12.2/32
  latest handshake: 2 minutes, 13 seconds ago
  transfer: 980 B received, 1.15 KiB sent
  persistent keepalive: every 25 seconds

おわりに

取り敢えずWireGuardについて知りたいだけなら十分だと思っていますが、実用を考えた時はこれだけでは不十分です。
もう少し踏み込んだ内容は、別の記事で書きたいと思います。
※ここまで書くだけで疲れました。

ちなみに、今回検証してみてどうしてもわからなかったことがあります。
AWS上に構築したEC2 2台のセキュリティグループは、私のクライアント端末からのSSHのみ許可する設定していたにも関わらず、EC2同士でVPNを張れているように見えます。
本来であれば、UDPのポートに対する通信許可をしてあげないといけないのでは?と思っていたのですが。。。
もしわかる方いらっしゃったらコメントください。

Discussion

ログインするとコメントできます