WireGuardでSite to site VPN(一方は直接グローバルIPアドレス使えない環境)
Overview
やりたいこと
一方の拠点ではグローバルIPアドレスを自由に使えるけど、もう一方はNAT配下で自由に使えない。
そんな環境で拠点間VPN使いたい、って時。
例えばOpenVPNでグローバルIPアドレス持てる側をサーバに、持てない側をクライアントにして後は必要に応じてiptablesでMASQUERADEとかすればいい感じになる。
そんなVPNを動かしてる環境を機械がどちゃくそ古いからいい加減新しくしたい!というお仕事があり、「今やるならせっかくだしOpenVPNよりWireGuard使いたいなー」と思ったためその検証をば。
この構成図で言うところのマシンAからマシンBへ通信するのが今回の目標ですが、マシンBからマシンAへの通信はルーティングどうにかすればできますね。
拠点A側
WireGuardサーバ側マシン
Ubuntu server 20.04 beta使いました。
物理的なネットワークインタフェースは2つ。
IPアドレス等設定
Ubuntuの公式ページを参考に/etc/netplan/99_config.yaml
を作成、編集。
network:
version: 2
renderer: networkd
ethernets:
eth0:
addresses:
- X.X.X.X/X
dhcp4: no
dhcp6: no
gateway4: <必要なものを>
nameservers:
addresses: [<プライマリ>, <セカンダリ>]
eth1:
addresses:
- x.y.z.254/24
編集後sudo netplan apply
UFW, iptables, カーネルパラメータ
途中までUFWでやってましたがNAT書くのに結局iptablesの書式で書かなきゃ駄目っぽくてうるせ~~~~~しらね~~~~~~~となり直接iptables叩いたりしてます(アホ)。
- ルータ的に動かすのでマシンAからの通信が意図せず蹴られるのも面倒くさいなと思いデフォルトallowに
- 今回の場合はインターネット側からのSSHを蹴れればOK
- 堅くやるならブラックリスト形式よりホワイトリスト形式を取るべきですが……
以下投入したコマンド等
sudo ufw default allow outgoing
sudo ufw default allow incoming
sudo ufw deny from any to X.X.X.X port 22 proto tcp
/etc/default/ufw
をDEFAULT_FORWARD_POLICY="ACCEPT"
に編集- ここ
sudo ufw default allow routed
でよかった気がする
- ここ
iptables -A FORWARD -i eth1 -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
- このMASQUERADEはマシンAがインターネットに出られるように。必須ではない
/etc/sysctl.conf
にnet.ipv4.ip_forward=1
を追記(コメントアウトを外したんだったかも)
2020/04/16/14:15頃追記
iptablesでコマンド投入するのをやめて/etc/ufw/before.rules
末尾に以下を追加して対処。
末尾じゃなくてfilterの前に置いたほうがいいかも?
# NAT
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -o eth0 -j MASQUERADE
COMMIT
WireGuard
インストール
sudo apt install wireguard
鍵作成
クライアント用とサーバ用とで2組必要(多分同じ鍵でも動くんだろうけど)
wg genkey > wg_server_privatekey
wg publickey < wg_server_privatekey > wg_server_publickey
wg genkey > wg_client_privatekey
wg publickey < wg_client_privatekey > wg_client_publickey
設定ファイル
ここ公式ドキュメントほぼゼロでどちゃくそ辛かったです。
Arch Wikiありがとうありがとう……。
/etc/wireguard/wg0.conf
を作成、編集。
[Interface]
PrivateKey = <wg_server_privatekey。ファイルパスではなく中身>
Address = i.j.k.254/30
ListenPort = 51820
[Peer]
PublicKey = <wg_client_publickey>
AllowedIPs = i.j.k.252/30, a.b.c.0/24
PersistentKeepalive = 60
AllowIPsにはWireGuardを通したいネットワークを書く。
私が詰まった所としては、ここにa.b.c.0/24(つまりは拠点B側のネットワーク)を書かず、ip route add
コマンドでスタティックルートをWireGuardサーバに追加したんですがpingすら通らずVPN対向先でtcpdumpしてもなにも届いておらず、ただサーバ側でtcpdumpするとwg0インタフェースから送信してる……というやつ。
ここに書かれていないネットワークはWireGuardが受け取っても処理してくれない。
実行
- 起動
wg-quick up wg0
- 停止
wg-quick down wg0
- systemctlなら
wg-quick@wg0
サービスを指定 sudo systemctl enable wg-quick@wg0
でマシン起動時に起動してくれるようになる
マシンA
適当にネットワーク設定のみ。
- x.y.z.1/24
- Default Gateway x.y.z.254
拠点B
WireGuardクライアント側マシン
こっちもUbuntu server 20.04 beta。
こちらはネットワークインタフェース一枚。
IPアドレス等設定
Ubuntuの公式ページを参考に/etc/netplan/99_config.yaml
を作成、編集。
network:
version: 2
renderer: networkd
ethernets:
eth0:
addresses:
- a.b.c.200/24
dhcp4: no
dhcp6: no
gateway4: <必要なものを>
nameservers:
addresses: [<プライマリ>, <セカンダリ>]
編集後sudo netplan apply
UFW, iptables, カーネルパラメータ
sudo ufw default allow outgoing
sudo ufw default allow incoming
/etc/default/ufw
をDEFAULT_FORWARD_POLICY="ACCEPT"
に編集- ここ
sudo ufw default allow routed
でよかった気がする
- ここ
/etc/sysctl.conf
にnet.ipv4.ip_forward=1
を追記(コメントアウトを外したんだったかも)
WireGuard
設定ファイル
/etc/wireguard/wg0.conf
を作成、編集。
[Interface]
PrivateKey = <wg_client_privatekey。ファイルパスではなく中身>
Address = i.j.k.253/30
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
[Peer]
PublicKey = <wg_server_privatekey。ファイルパスではなく中身>
AllowedIPs = i.j.k.252/30, x.y.z/24
Endpoint = X.X.X.X:51820
PersistentKeepalive = 60
マスカレードがない場合このWireGuardクライアント用マシンから外には出られない。(というより出ても戻ってこれない)
後はsystemctl enableして終わり。
マシンB
適当にアドレス振っとく。
- a.b.c.1/24
感想
ここまでやればマシンAからマシンBにpingなりtcp/udp通信なりできるようになる。
例えばマシンAにprometheusやらzabbixなんかのPull型監視システムを入れといて、拠点Bの中を監視したいだとかそういう事ができる。
あるいはマシンBから拠点Aのネットワークへアクセスしたい場合は、今回の場合だと冒頭に書いたx.y.z.0/24へのスタティックルートをマシンBに書くとか、拠点B側のルータやらL3スイッチでWireGuardクライアントのLAN側アドレスに向けてあげるとか。
それができない場合はWireGuardクライアント用マシンでフォワードとかNATすればいいかな?
例えばa.b.c.dをB側WireGuardに持たせて、x.y.z.dにDNATするとか。
前OpenVPNで似たようなことやろうとしてiptablesに泣かされて苦手意識あったけど今回うまいこと動いてよかったよかった。