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/ufwDEFAULT_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.confnet.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/ufwDEFAULT_FORWARD_POLICY="ACCEPT"に編集
    • ここsudo ufw default allow routedでよかった気がする
  • /etc/sysctl.confnet.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に泣かされて苦手意識あったけど今回うまいこと動いてよかったよかった。

comments powered by Disqus