WireGuardによるVPNサーバをAWS(EC2 or Lightsail)に構築します。
WireGuardそのものはサーバソフトではなく、ピア・トゥ・ピアで端末間どうしの接続を確立するVPN(Virtual Private Network)ソフトウェアです。接続をリクエストする側とリクエストされる側双方にインストールされるソフトウェアは同一のもので、設定ファイルによりそれぞれがピア(クライアント)またはサーバとしての役割を担います。OpenVPNなど従来のVPNサーバと比較して、よりセキュアかつ軽量であり接続も非常に安定しています。
VPNにおけるサーバとピア(クライアント)の関係は、家庭内におけるホームルータとPCとの関係に相当すると考えると理解しやすいでしょう。
WireGuard導入のメリットは次の通りです。
- サーバのリージョン指定により、日本国内から海外国内ユーザ限定のサイトへのアクセス(各国のメディアサイト提供の番組視聴など)
- グローバルな固定IPが割当てられていないホームサーバへのアクセス(リバースプロキシによる)
参考サイト
WireGuard: fast, modern, secure VPN tunnel
How To Set Up WireGuard on Ubuntu 20.04 | DigitalOcean
Getting Started with WireGuard
Docker WireGuard
GitHub - linuxserver/docker-wireguard
0. 事前準備
事前準備として、サーバ側にAWSによるインスタンス(EC2またはLightsail)を用意して下さい。インスタンスにはSSH接続できるようにしておきます。推奨インスタンスはLightsailによるものです。WireGuardによるVPNサーバとして3.5USDのLinuxインスタンスを選択してもデータ転送量上限が1TBに設定されており、メモリ512MB、ディスク容量も20GBと十分なスペックです。
1. インストール
サーバ側、クライアント側共にインストール手順は同じです。同じ作業をサーバ側とピア(クライアント)側で実行します。
$ sudo apt update
$ sudo apt install wireguard
インストール後、WireGuardのwg genkeyとwg pubkeyコマンドからプライベートキーとパブリックキーを作成します。umask コマンドでシェル内で作成されるこれらファイルやディレクトリへのアクセスにオーナのみの制限を設けます。この設定はシェル終了時点でリセットされます。
$ umask 077
プライベートキーの作成
wg genkey コマンドによりプライベートキーを作成し、private.keyとして保存します。
$ wg genkey | sudo tee /etc/wireguard/private.key
パブリックキーの作成
プライベートキーprivate.keyからwg pubkeyコマンドによりパブリックキーを作成し、public.keyとして保存します。
$ sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key
2. ローカルIPの定義
WireGuardで使用するVPNネットワークのIP範囲とその種類(IP4, IP6または両方)を定義します。今回はIP4のみを定義し、以下の代表的にローカルIPとして使用されているアドレスの中から10.8.0.0/24を選択します。
10.0.0.0
to10.255.255.255
(10/8 prefix)172.16.0.0
to172.31.255.255
(172.16/12 prefix)192.168.0.0
to192.168.255.255
(192.168/16 prefix)
3. サーバ側のIPフォワーディング設定
WireGuardによるネットワークインターフェイスwg0からサーバのネットワークインターフェイスeth0経由でインターネットに繋げるためIPフォワーディングの設定をします。
$ sudo nano /etc/sysctl.conf
以下のセクションをコメントアウトして1に設定します。
sysctl.conf
net.ipv4.ip_forward=1
上記設定を反映させます。
$ sudo sysctl -p
output
net.ipv4.ip_forward = 1
ネットワークインターフェイスの確認は以下コマンドで行って下さい。
$ ip route list default
Output
default via 203.0.113.1 dev eth0 proto static
この場合、インターネットに繋がっているインターフェイスはeth0となります。
4. 設定ファイルの作成
サーバ側、ピア(クライアント)側それぞれに設定ファイルを作成します。設定ファイルの名称から拡張子を除いたwg0がネットワークインターフェイスの名称となります。
サーバ側の設定ファイル
必要な情報として、
- サーバ側で作成したプライベートキーprivate.keyの内容
- ピア(クライアント)側で作成したパブリックキーpublic.keyの内容
- サーバ側に割当てるローカルIP(範囲): 10.8.0.1/24
- ピア(クライアント)側の受入IP(範囲): 10.8.0.2/32
- ポートはデフォルトの51820を指定 注)AWSのインスタンスでこのポート(in)は開放して下さい。
$ sudo nano /etc/wireguard/wg0.conf
wg0.conf
[Interface]
Address = 10.8.0.1/24
SaveConfig = true
PostUp = iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
PreDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
ListenPort = 51820
PrivateKey = server_private_key
[Peer]
PublicKey = peer_client_public_key
AllowedIPs = 10.8.0.2/32
iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
- iptablesのマスカレーディングによりVPNのインターフェイスwg0がeth0と見なされます。- SaveConfigにより終了時点の接続ピアの情報などが保存されます。
ピア(クライアント)側の設定ファイル
必要な情報として、
- ピア(クライアント)側で作成したプライベートキーprivate.keyの内容
- サーバ側のパブリックキーpublic.keyの内容
- サーバ側のグローバルIP:ポート: instance_global_IP:51820
- ピア(クライアント)側に割当てるローカルIP(範囲): 10.8.0.2/24
$ sudo nano /etc/wireguard/wg0.conf
wg0.conf
[Interface]
Address = 10.8.0.2/24
PrivateKey = peer_client_private_key
#optional below
#PostUp = ip rule add table 200 from 192.168.1.xxx
#PostUp = ip route add table 200 default via 192.168.1.1
#PreDown = ip route delete table 200 default via 192.168.1.1
#PreDown = ip rule delete table 200 from 192.168.1.xxx
#DNS = 1.1.1.1
[Peer]
PublicKey = server_public_key
AllowedIPs = 0.0.0.0/0
Endpoint = instance_global_IP:51820
PersistentKeepalive = 25
サーバをインターネットへのゲートウェイとして利用するため、AllowedIPsには0.0.0.0/0を指定。
注)#オプション箇所の詳細については
How To Set Up WireGuard on Ubuntu 20.04 | DigitalOcean
を参照して下さい。
DNSオプションを設定した場合、resolvconfをインストールする必要があります。
$ sudo apt install resolvconf
ピア(クライアント)がNATやファイヤーウォールの背後に配置されている場合、PersistentKeepalive =
を指定しないとNATまたはファイヤーウォールから接続が切断されてしまします。詳しくは、
Quick Start - WireGuard
NAT and Firewall Traversal Persistence
By default, WireGuard tries to be as silent as possible when not being used; it is not a chatty protocol. For the most part, it only transmits data when a peer wishes to send packets. When it’s not being asked to send packets, it stops sending packets until it is asked again. In the majority of configurations, this works well. However, when a peer is behind NAT or a firewall, it might wish to be able to receive incoming packets even when it is not sending any packets. Because NAT and stateful firewalls keep track of “connections”, if a peer behind NAT or a firewall wishes to receive incoming packets, he must keep the NAT/firewall mapping valid, by periodically sending keepalive packets. This is called persistent keepalives. When this option is enabled, a keepalive packet is sent to the server endpoint once every interval seconds. A sensible interval that works with a wide variety of firewalls is 25 seconds. Setting it to 0 turns the feature off, which is the default, since most users will not need this, and it makes WireGuard slightly more chatty. This feature may be specified by adding the
PersistentKeepalive =
field to a peer in the configuration file, or settingpersistent-keepalive
at the command line. If you don’t need this feature, don’t enable it. But if you’re behind NAT or a firewall and you want to receive incoming connections long after network traffic has gone silent, this option will keep the “connection” open in the eyes of NAT.
5. サーバ起動
初めにサーバ側を起動します。WireGuardのシステムデーモンを有効にしてから起動します。
$ sudo systemctl enable [email protected]
$ sudo systemctl start [email protected]
ステータス確認
$ sudo systemctl status [email protected]
Output
● [email protected] - WireGuard via wg-quick(8) for wg0
Loaded: loaded (/lib/systemd/system/[email protected]; enabled; vendor preset: enabled)
Active: active (exited) since Wed 2021-08-25 15:24:14 UTC; 5s ago
Docs: man:wg-quick(8)
man:wg(8)
https://www.wireguard.com/
https://www.wireguard.com/quickstart/
https://git.zx2c4.com/wireguard-tools/about/src/man/wg-quick.8
https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8
Process: 3245 ExecStart=/usr/bin/wg-quick up wg0 (code=exited, status=0/SUCCESS)
Main PID: 3245 (code=exited, status=0/SUCCESS)
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] wg setconf wg0 /dev/fd/63
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] ip -4 address add 10.8.0.1/24 dev wg0
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] ip -6 address add fd0d:86fa:c3bc::1/64 dev wg0
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] ip link set mtu 1420 up dev wg0
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] ufw route allow in on wg0 out on eth0
Aug 25 15:24:14 wg0 wg-quick[3279]: Rule added
Aug 25 15:24:14 wg0 wg-quick[3279]: Rule added (v6)
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] ip6tables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
Aug 25 15:24:14 wg0 systemd[1]: Finished WireGuard via wg-quick(8) for wg0.
停止
$ sudo systemctl stop [email protected]
接続状態の確認
どのクライアントと接続しているか、通信量などが確認できます。
$ sudo wg
Output
interface: wg0
public key: U9uE2kb/nrrzsEU58GD3pKFU3TLYDMCbetIsnV8eeFE=
private key: (hidden)
listening port: 51820
peer: PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg=
allowed ips: 10.8.0.2/32, fd0d:86fa:c3bc::/128
6. ピア(クライアント)からサーバへ接続
サーバ側が起動している状態で接続します。
接続
$ sudo wg-quick up wg0
Output
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.8.0.2/24 dev wg0
[#] ip -6 address add fd0d:86fa:c3bc::2/64 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] resolvconf -a tun.wg0 -m 0 -x
[#] wg set wg0 fwmark 51820
[#] ip -6 route add ::/0 dev wg0 table 51820
[#] ip -6 rule add not fwmark 51820 table 51820
[#] ip -6 rule add table main suppress_prefixlength 0
[#] ip6tables-restore -n
[#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820
[#] ip -4 rule add not fwmark 51820 table 51820
[#] ip -4 rule add table main suppress_prefixlength 0
[#] sysctl -q net.ipv4.conf.all.src_valid_mark=1
[#] iptables-restore -n
停止
$ sudo wg-quick down wg0
接続状態の確認
$ sudo wg
Output
interface: wg0
public key: PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg=
private key: (hidden)
listening port: 49338
fwmark: 0xca6c
peer: U9uE2kb/nrrzsEU58GD3pKFU3TLYDMCbetIsnV8eeFE=
endpoint: 203.0.113.1:51820
allowed ips: 10.8.0.0/24, fd0d:86fa:c3bc::/64
latest handshake: 1 second ago
transfer: 6.50 KiB received, 15.41 KiB sent
ピア(クライアント)のIPがサーバのパブリックIPに変更したかどうかの確認は、以下のcurlコマンドで行います。
$ curl https://ipinfo.io/ip
7. 複数ピアの接続
複数のピア(クライアント)を接続するには、新たに接続するピア2でもピア1と同様にWireGuardのインストール、プライベート・パブリックキーの作成、設定ファイルwg0.confにサーバ情報などを記載します。
Peer2 IP Address:10.8.0.3
Peer2: wg0.conf
[Interface]
Address = 10.8.0.3/24
PrivateKey = peer2_client2_private_key
#optional below
#PostUp = ip rule add table 200 from 192.168.1.xxx
#PostUp = ip route add table 200 default via 192.168.1.1
#PreDown = ip rule delete table 200 from 192.168.1.xxx
#PreDown = ip route delete table 200 default via 192.168.1.1
#DNS = 1.1.1.1
[Peer]
PublicKey = server_public_key
AllowedIPs = 0.0.0.0/0
Endpoint = instance_global_IP:51820
PersistentKeepalive = 25
サーバ側の設定ファイルwg0.confに新しく加わるピア2の情報を追加します。
Server: wg0.conf
[Interface]
Address = 10.8.0.1/24
SaveConfig = true
PostUp = iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
PreDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
ListenPort = 51820
PrivateKey = server_private_key
[Peer]
PublicKey = peer_client_public_key
AllowedIPs = 10.8.0.2/32
[Peer]
PublicKey = peer2_client2_public_key
AllowedIPs = 10.8.0.3/32
サーバ側のWireGuardを再起動後、
$ sudo systemctl restart [email protected]
ピア2のWireGuardを起動します。
$ sudo wg-quick up wg0
本ブログの内容はフォーラムにも掲載、補足・訂正事項などはフォーラムにてフォローします。
https://forum.ficusonline.com/t/topic/436
2021/12/28追加 :フォーラムでの追加内容を転載
WireGuardの使用例
WireGuardのネットワークを利用すると、グローバルIPが割当てられていないホストマシンでも 固定IP(AWSインスタンス) によるサーバ運営(マルチドメイン)が可能です。
方法1:VPNサーバにプロキシーサーバを配置Nginx
のプロキシーサーバを VPN Server
に配置し、ドメインごとに Peer2:10.8.0.3
のポート番号を指定します。
方法2:iptablesのポートフォワードルールを適用VPN Server
で iptables
によるポートフォワーディングルールを追加します。
$ sudo iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 443 -j DNAT --to-destination 10.8.0.3:443
$ sudo iptables -A FORWARD -p tcp -d 10.8.0.3 --dport 443 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
注) 上記コマンドの下段はファイヤーウォールを設定している場合に必要です。
Peer2にプロキシーサーバを配置。
iptablesによる方法をお勧めします。