家と作業拠点との間をVPNで接続したくなり、格闘の末なんとか目的を達成できたので、その記録。
実際に色々ハマりながら、なんとか動作する設定に至ると、「あぁこういうことだったのか」と感じることも多く、面白いですね。
環境とここでの用語
家には実は2回線あったことを思い出し(1回線は全然使っていなかったのだけど解約もしていなかった)、これは「2拠点接続の勉強をするのに最適ではないか!」ということで、今回の着手に至った次第。
思い出したほうの回線にラズパイを接続してルータにてDMZ指定。同じネットワークにWindowsのノートPCが一台接続されている状態にしました。こちらをここでは便宜上「サーバ側」とか「RPi側」とか呼ぶことにします。
一方のアクセス元となる環境は、普段の自分の家の環境。WindowsPCが動いています。こちらここでは便宜上「クライアント側」と呼びます。
サーバ側は 192.168.1.0/24、家のほうは 192.168.0.0/24 です。
VPN接続までのおおまかな流れ
サーバ側:
- WireGuardのインストール
- 設定ファイルの記述1:予め作成した自分の鍵情報を記述する
- 設定ファイルの記述2:接続を許可する先(クライアント)の鍵情報などを記述する
- WireGuard立ち上げ(そして待ち受け)
クライアント側:
- WireGUardのインストール
- 設定ファイルの記述1:予め作成した自分の鍵情報を記述する
- 設定ファイルの記述2:接続先の情報を記述する
- 接続指示!と確認
構築手順
WireGuardインストール
クライアント側はまずは WSLのUbuntu上にて作業した(後に Windows用アプリを入れてネイティブでも動作確認済)。
サーバ側・クライン側とも
apt install wireguard
鍵ペアの作成
本質的にはサーバ側、クライアント側ともに同じ事をするが、ファイル名を異なるものにしている(べつにファイル名は何でも良いのだけど、なくさないためにファイルに保存し、パーミション制限している。厳密に言えば作ってからパーミッション変更すると、作った瞬間に覗かれる可能性を排除できないので、umaskしたり予めパーミション設定したファイル(touchなど)に鍵を書き込むなどのほうがベスト。)。
サーバ側:
# 秘密鍵を作成 wg genkey | sudo tee /etc/wireguard/server.key sudo chmod 600 /etc/wireguard/server.key # 公開鍵を生成 sudo cat /etc/wireguard/server.key | wg pubkey | sudo tee /etc/wireguard/server.pub sudo chmod 600 /etc/wireguard/server.pub
クライアント側:
# 秘密鍵を作成 wg genkey | sudo tee /etc/wireguard/client.key sudo chmod 600 /etc/wireguard/client.key # 公開鍵を生成 sudo cat /etc/wireguard/client.key | wg pubkey | sudo tee /etc/wireguard/client.pub sudo chmod 600 /etc/wireguard/client.pub
設定ファイルの記述(サーバ側)
サーバ側(接続を待ち受ける側)の設定。[Interface]セクションに自分の(サーバ側の)条件を書き、[Peer]側に接続を許可する相手側の情報を書く
/etc/wireguard/wg0.conf (新規作成する。wg0というインタフェース名にする場合はこのファイル名)
[Interface] PrivateKey=wOchd2/do5Pe4VRzk3L3pVQHgO4kDUh/3Aec+GBPxFo= Address=172.16.0.10 ListenPort=51830 [Peer] PublicKey=bgzIVy3u0A9b+AB5lvknZb5mlfugZ91/9Z0YOBNk460= AllowedIPs=172.16.0.0/24
InterfaceのPrivateKeyには自分の秘密鍵(server.key)の内容を記述し、
PeerのPublicKeyには接続を許可する相手の公開鍵(client.pub)の内容を記述する。
ここでAddressは、VPN接続に使うインタフェースのアドレス(決める)、
AllowedIPsは、接続を許可する相手のネットワークを記述する。
設定ファイルの記述(クライアント側)
クライアント側(接続をしかける側)の設定。[Interface]セクションに自分の(クライアント側の)条件を書き、[Peer]側に接続先の情報を書く。
[Interface] PrivateKey = eBXv9XmFgNJYfWxoQH3Z6jBgo4KaX/X22DvTKZKo8lc= Address = 172.16.0.12/32 [Peer] PublicKey = aeMvyD+IIlAzphOLS/uyVn9gZdF/pwsT/K6Rs4GtOj4= AllowedIPs = 172.16.0.0/16, 192.168.1.0/24 Endpoint = XXX.YY.ZZZ.83:51830
InterfaceのPrivateKeyには自分の秘密鍵(client.key)の内容を記述し、
PeerのPublicKeyには接続を許可する相手の公開鍵(server.pub)の内容を記述する。
Addressは、VPN接続に使うインタフェースのアドレス(サーバに設定したのと同じネットワークで、かぶらないもの)。
AllowedIPsは、接続先でアクセスするIPアドレスの範囲。今回はラズパイの裏側にあるネットワーク(今はノートPC1台しかないけど)にもアクセスしたいので、書いておく(実際は裏側にアクセスするためにもう少し設定が必要なので、あとで加えても良いのだけど)。
Endpointは、サーバのIPアドレスと、サーバのwg0.confに記述したポート番号。
接続
サーバ側の待ち受け
sudo systemctl start wg-quick@wg0
(停止したいときは stop、再起動したいときは restart)
設定が正しければ、何のメッセージもなく完了する。誤りがある場合は何か表示される。
このとき wg コマンドで以下の様に表示される。peerに許可先の公開鍵とネットワークが表示されていることがポイント。
$ sudo wg interface: wg0 public key: abcdltOAzph/uMvyDZdF/pw+yVSsT/K6Rs4Gn9gOLj4= private key: (hidden) listening port: 51830 peer: YiKGzKIo6YimEBO5+EsNTuxQymc4VUfC3NgSRJLqryU= allowed ips: 172.16.0.0/24
クライアント側からの接続
wg0インタフェースを立ち上げる
sudo wg-quick up wg0
(落とすときは down)
wgコマンドで状態を確認するとこんな感じ。
$ sudo wg interface: wg0 public key: gZAB3ku4VlZfbA0m6nb7I9zy30/NZ+vk9u1OYB5bll0= private key: (hidden) listening port: 50673 peer: tKPslcohiT3Hmsf2mNbvozREpsshlZ+hoAXrBtsc6Bw= endpoint: XXX.YY.ZZZ.83:51830 allowed ips: 172.16.0.0/16, 192.168.1.0/24
正しく設定されていれば、サーバ側RPiへのPingが通るはず。
\> ping 172.16.0.10 172.16.0.10 に ping を送信しています 32 バイトのデータ: 172.16.0.10 からの応答: バイト数 =32 時間 =53ms TTL=64 172.16.0.10 からの応答: バイト数 =32 時間 =17ms TTL=64 172.16.0.10 からの応答: バイト数 =32 時間 =19ms TTL=64 172.16.0.10 からの応答: バイト数 =32 時間 =23ms TTL=64
一度(pingなどで)アクセスがあると、サーバ側ではpeerに接続情報が表示されるようになる。
interface: wg0 public key: abcdltOAzph/uMvyDZdF/pw+yVSsT/K6Rs4Gn9gOLj4= private key: (hidden) listening port: 51830 peer: YiKGzKIo6YimEBO5+EsNTuxQymc4VUfC3NgSRJLqryU= endpoint: PPP.QQ.RRR.219:26718 allowed ips: 172.16.0.0/24 latest handshake: 20 minutes, 33 seconds ago transfer: 564 B received, 476 B sent
以上で、家とサーバ側とでVPNが張れました。ただしこの時点では、先方のラズパイとつながっただけです。
なので、最後に「サーバ側で、サーバの裏側のネットワークにもアクセスできるようにする」設定をします。
サーバ側のネットワーク上の機器にアクセスできるようにするための設定
wg0.confの設定
ip a などでフォーワードしたいネットワークアダプタの名前を確認します(ここでは eth0。無線LANを使っている場合は wlan0とかの場合もあるでしょう)。
[Interface] (略) PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
アクセス元の wg0.confの設定
ここで wg0.confの [Peer] の AllowedIPsに相手方のアクセスしたネットワーク(ここでは 192.168.1.0/24)を指定するのが流れなのですが、今回は最初に設定してしまったので、とくにここでやることはないです。
あとは、相手側ネットワーク上のPCに向けてアクセスできることを確認すれば良いです。
例:
\> ping 192.168.1.10 192.168.1.10 に ping を送信しています 32 バイトのデータ: 192.168.1.10 からの応答: バイト数 =32 時間 =26ms TTL=127 192.168.1.10 からの応答: バイト数 =32 時間 =23ms TTL=127 192.168.1.10 からの応答: バイト数 =32 時間 =35ms TTL=127 192.168.1.10 からの応答: バイト数 =32 時間 =23ms TTL=127
(おまけ)リモートデスクトップ接続しようとしてハマった件
総仕上げとして、相手側ネットワークにあるWindowsマシンへとリモートデスクトップ接続しようとして、えらくハマりました。私がハマったポイントを。
1. ノートPCをwi-fiに繋ぐ際に「パブリックネットワーク」にしてしまったせいで、全然外からアクセスできなかった
2. セキュリティソフトが「ネットワーク保護」として、外からのアクセスを拒否していた(ファイアウォール)
3. そもそもそのノートでリモートデスクトップ許可していなかった