OpenWRTでWireGuardを使う

一般的でないと思う構成でWireGuardを使おうとしたら結構躓いたので、その際に試したことのメモ。なおOpenWRTは22.03.05、WireGuardはWindows版が0.5.3である。

私が一般的だと思っている構成

一般的にOpenWRT(の動作しているルータ。以下単にOpenWRT)でWireGuardを使うとなると、例えば以下のような構成を想定しているのではないかと思う。OpenWRTがRTと多段になっているか否かはどちらでもいいが、いずれにしてもOpenWRTで内外のルーティングを行い、192.168.100.0/24はWireGuardの動作するOpenWRT配下にある、という前提があると思っている(知らんけど)。ともかくこういう構成はよくやっている人がいるので情報が色々あり、あまり困らないのかも知れない。

出先(Windows PC)
      |
      |tun                            tun                   自宅
      +==================================+                  +---[Camera]
      |                                 ||                  |
      |                              WireGuard              |
      +------Internet------[RT]------[OpenWRT]--------------+---[PC]
                                            192.168.100.1/24|
                                                            |
                                                            +---[NAS]

私が実現したい構成

私が実現したい構成は以下のような感じ(若干脚色しているので、別記事と比較してFriendlyCore Lite(Ubuntu 20.04 LTSベース)が動いてるNanoPiでWireGuardを動かしたら?などのツッコミは不要)。なお、IPv6のことはまだ考えていない。

出先(Windows PC)                                  自宅  +---[Camera]
      |                                                   |  192.168
      |tun:192.168.17.2                   tun:192.168.17.1|    .100.230
      +===================================================+===[OpenWRT]
      |                                                   |   WireGuard
      |                                                   |
      +------------Internet-----------[RT]----------------+---[PC]
203.0.113.1                  192.0.2.1    192.168.100.1/24|
                         ddns.example.com                 |
                                                          +---[NAS]

これで出先から自宅の192.168.100.0/24にアクセスをしたい。なお、図中に書ききれないが192.168.17.0/24を自宅内でルーティングしない(192.168.100.230にNATする)こととし、全てOpenWRTを踏み台にしてNASやPCと通信するようにしたい。
要は前提として後からOpenWRTを導入するのでルータやネットワーク構成を変更したくなく、つまりこのOpenWRTはWireGuard専用で、物理的なルーティングをしない(言い換えるとWANポートを使用しない)ようにしたい。

知識不足でよくわからなかった点

いくつかの説明を読んでも違和感というかピンと来なかったのは、WireGuardはサーバ・クライアント方式ではなくP2Pで、つまりどちらが責めとか受けとかないので、まずサーバ側の設定をし、それにクライアントが接続しに行くみたいに思っていたからかも知れない。設定上は主従なく対等で、どちらからでも接続できるようになっているが、上記構成だと出先のアドレス(203.0.113.1)は実際には不定で、自宅がサーバで出先がクライアントにしかなり得ないので、まあそういうものだと思って進める(実際サーバ・クライアントとして説明している人も普通にいる)。
またP2PであるというのはWireGuard自体はただのL3トンネル(まさに土管)であり、ルーティングやNATをよしなにしてくれるわけではないので、トンネルが確立した後はOpenWRT側で必要な設定しないといけない(むしろそっちの方が構成によって異なるので面倒かも)という認識がないと、何をやっているのかわからない気がした。
それとOpenWRTにluci-i18n-*-jaを入れているとLuCIの表示が日本語化されるが、英語のまま使い、説明を書いている人もいるので、特に難しい翻訳ではないにせよどの設定がどれなのか照らし合わせないといけないのが若干面倒だったりするのもあった。また、そもそもLuCIを使わずにコンソール(SSH)で設定する人もいる(やっていることは同じだが…)。
あとおそらくだけど、OpenWRTでは同じ設定をするのに複数の方法があるのに、同じ結果をもたらす作業だということを私が理解できていないため手こずったのではないかと思う。この辺は今でもよくわかっていない。

事前の設定

OpenWRTのIPアドレス等を設定する。初期状態だと192.168.1.1/24になっていて、かつLAN側でDHCPサーバも動いているので、オフにする必要がある(WAN側ではDHCPクライアントが動いているがそっちは何も接続しないので、別に…)。

  1. ネットワーク→インターフェース→LAN→編集の一般設定 タブで
    IPv4アドレス:192.168.100.230
    IPv4ゲートウェイ:192.168.100.1(入れなくても動くこともあるような…)
    とし、詳細設定 タブで
    カスタムDNSサーバーを使用:192.168.100.1
    とし、DHCPサーバーの一般設定 タブで
    インターフェースを無視:チェック
    として保存し、保存&適用。

なおIPアドレスを変更する際、変更後にアクセスできなくなると困るので、メッセージにしたがって速やかに新しいIPアドレスでアクセスし直さないと設定が90秒でロールバックする(Apply with revert after connectivity loss)のが通常になっているらしい(多分LuCIの親切な機能)。

WireGuardのインストールと設定

  1. システム→ソフトウェアでリストを更新…ボタンを押し、luci-app-wireguard(OpenWrt 23.05以降ではluci-proto-wireguard)をインストール(必要な依存パッケージはこれだけで全部入るはず)。
  2. システム→再起動→再起動する。
  3. 先にWindowsクライアント(正しくはクライアントではないと思うが…)の設定をする。
    トンネルの追加の右の▼ボタンを押し、空のトンネルを追加…を押す。公開鍵とPrivateKeyだけセットされた状態になるので、いったんこのまま(保存もキャンセルもしないで)置いておく。
  1. OpenWRTのネットワーク→インターフェース→インターフェースを新規作成…ボタンを押し、
    名前:wg0
    プロトコル:WireGuard VPN
    として、インターフェースを作成。
  2. 次の画面の一般設定 タブで、公開鍵の下にあるGenerate new key pairボタンを押し、秘密鍵・公開鍵を生成する。
  3. 続いて同じく一般設定 タブで
    リッスンポート:51820
    IPアドレス:192.168.17.1
    とする。
  1. 続いてファイアウォール設定 タブで、
    ファイアウォールゾーンの作成または割り当て:lan(何でもいいと書いてあるサイトもあるが、本構成ではlanでないとダメっぽい)
    とする。
  1. 続いてピア(接続する対向のこと) タブでピアを追加ボタンを押し、
    説明:わかりやすいように対向の名称を入れる
    公開鍵:手順4.で表示された公開鍵をコピペする
    許可されたIP:192.168.17.2(Optionalとあるが本構成では必須っぽい)
    許可されたIPのルート:チェック
    エンドポイントホスト:(空)
    エンドポイントポート:(空)
    永続的なキープアライブ:25
    とし、保存する。
  1. 手順4.の続きで、Windows側クライアントのトンネル設定において、名前を適当につけ(わかりやすいように対向の名称とか)、内容は次のように編集し、保存する(これで互いが互いの公開鍵を持ち、相互に本物であると認証できる状態になる)。
    [Interface]
    PrivateKey = (表示されているまま変更しない)
    ListenPort = 51820(設定しなくてもよい)
    Address = 192.168.17.2/32
    DNS = 8.8.8.8(設定しなくてもよい)
    [Peer]
    PublicKey = (手順6.で生成した公開鍵をコピペする)
    AllowedIPs = 192.168.100.0/24
    Endpoint = ddns.example.com:51820

    補足:世の中にはVPNというものは全ての通信をVPN経由にする構成が当然であるとして(そういう構成が存在することは知っているが)、説明なく
    AllowedIPs = 0.0.0.0/0
    と書く人がいるが、普通ここは「VPNを経由させたい特定のネットワークアドレス」を書く。言い換えると、AllowedIPsで指定したネットワークのルーティングをトンネルに向ける設定だと思った方がよい。カンマ区切りで複数ネットワークも指定できる。

WireGuard以外の設定

  1. 元々あるルータ(図中のRTのこと)の設定で、外部からport 51820/udp宛のパケットを192.168.100.230に投げるよう設定する(ルータのメーカーによるが、大体「静的IPマスカレード設定」「ポート開放」などと呼ばれている)。
    参考までにYAMAHA NVR510だと
    nat descriptor masquerade static 1000 1 192.168.100.230 udp 51820
    みたいな感じになる。しかしこの記事を読む人はあまりNVR510など使ってない気がするので、参考にならない気がする(偏見)。
  2. OpenWRTのネットワーク→インターフェース→インターフェースを新規作成…で
    名前:wgnat
    プロトコル:静的アドレス
    デバイス:br-lan
    とし、インターフェースを作成し、次の一般設定 タブで
    IPv4アドレス:192.168.17.1
    IPv4ネットマスク:255.255.255.0
    IPv4ゲートウェイ:192.168.100.1(本構成では必須っぽい)
    として保存し、保存&適用。
  1. ネットワーク→ファイアウォール→NATルールで追加ボタンを押し、
    名前:wg2lan
    アドレスファミリの制限:IPv4のみ
    プロトコル:すべて
    送信側ゾーン:すべてのゾーン
    送信元アドレス:192.168.17.0/24
    宛先アドレス:192.168.100.0/24
    アクション:MASQUERADE – 自動的に送信側インターフェースIPへ書き換え
    として保存し、保存&適用。
  1. OpenWRT側はシステム→再起動→再起動する。Windows側は作成したトンネルについて有効化ボタンを押す。これで多分つながる。Plug & Pray.

補足とトラブルシューティング

  • 一般的と思われる構成とは異なり、この構成ではOpenWRTに対するWireGuardの通信(51820/udp)がWAN側ではなくLAN側から入ってくるので、ネットワーク→ファイアウォールの一般設定 タブでゾーンを追加したり、トラフィック・ルール タブで新たなトラフィック・ルールを追加する必要がない(一般的には必要だと思う)。
  • 試した限りでは「本構成では必須」と書いた箇所と手順13.とが、本構成と一般的と思われる構成との設定における違いのような感じがする。知らんけど。
  • インターフェースwg0の設定を変更した際、保存&適用のみならずwg0を再起動しないと反映されないが、それでも変な気がするときはOpenWRTごと再起動(システム→再起動→再起動する)した方が確実かも。
  • WindowsのWireGuardクライアントの有効化ボタンを押すと、問答無用でトンネルが有効になる。有効というのはトンネルが確立して通信可能という意味ではないので、ログ タブでログを見ないとどういう状態なのかがわからない。なお、パケットが相互に到達するとピアの転送欄が
    転送: 2.55 KiB 受信済み、5.43 KiB 送信済み
    のように送受信ともに増加するようになる。送受信ともに増加するからといって公開鍵が間違っていればトンネルは確立できないし、トンネルが確立できていることとルーティングができているかも別問題。段階を追って原因を探らないと何の設定を見直すべきかがよくわからない。一応うまく動いてるところのスクショは以下(端末によって有効化ボタンを押してもピアの転送の欄が出ない謎症状があり、解決していない)。
  • パケットが届いているのかどうかレベルで状況がわからない場合、OpenWRTにtcpdumpを入れてコンソール(SSH)上で確認することができる(WireGuardと同じくシステム→ソフトウェアから)。tcpdumpの使い方は詳しいサイトに譲るとして、要は例えば
    • WireGuardのパケットがそもそも到達しているかどうか
      tcpdump -i eth0.1 udp port 51820
    • SSH以外のパケットを確認(OpenWRTにSSHログインしてるとそのパケットが見えてうざいから)
      tcpdump -i eth0.1 not port 22
    • WireGuardのパケットが到達している状況で、トンネル内に何が流れているか
      tcpdump -i wg0

おまけ – VMwareでOpenWRTを動かす

上記構成において、どうせ自宅にPCがあるのでVMware上のOpenWRTで上記のようなことをすることを考える。いくらVMware上でも母艦のスペックが違うわけで、市販ルータよりは速度が出るのでは…?

  1. VMwareでOpenWRTの仮想マシンを作成する。
    以下のサイトがとても参考になる(ありがとうございました)。 https://www.ocawa.jp/notebook/%E4%BB%AE%E6%83%B3%E7%92%B0%E5%A2%83%E3%81%ABopenwrt-x86%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B%E6%89%8B%E9%A0%86/P
  1. VMwareの仮想マシン設定のネットワーク アダプタのネットワーク接続で以下のように設定する。
    ・ブリッジ:物理ネットワークに直接接続
    ・物理ネットワーク接続の状態を複製:チェックしない
    で、「詳細」ボタンでMACアドレスを「生成」して「OK」する。
  1. 仮想マシンを再生し、コンソールで取り敢えずIPアドレスを設定する。
    # uci set network.lan.proto=static
    # uci set network.lan.ipaddr=192.168.100.230
    # uci commit network
    # ifdown lan
    # ifup lan
  1. 以降、単体のOpenWRTと同じ。

オチ

PCのスペックはそこそこだったのにも関わらず、VMware上のOpenWRTの方が遅かった。以下iperfの結果。

[ ID] Interval Transfer Bandwidth
[ 4] 0.00-10.00 sec 14.0 MBytes 11.7 Mbits/sec sender
[ 4] 0.00-10.00 sec 13.8 MBytes 11.5 Mbits/sec receiver

WCR-1166DSと対向させた場合。

[ ID] Interval Transfer Bandwidth
[ 4] 0.00-10.00 sec 26.2 MBytes 22.0 Mbits/sec sender
[ 4] 0.00-10.00 sec 26.1 MBytes 21.9 Mbits/sec receiver

原因については探ってないが、これだと逆にVMwareでテストした後にハードウェアを購入する方がいいかも。いずれにしても動くか動かないかで言えば動いたので、参考までに。

更におまけ – Windows PCをWireGuardサーバにする

上の方で書いた通りWireGuardはL3トンネルなのでサーバとかいう概念はないはずだが、要は本構成でOpenWRTルータやVMware上のOpenWRTではなくWindows PCを直接使用する方法も考える。OpenWRTは別として、取り敢えずWireGuardを使ってみたいだけならWindowsのICS(Internet Connection Sharing=インターネット接続の共有)で簡単に実現できる。

以下、便宜的に受け側のWindows PCを「サーバ」、接続しに行く側を「クライアント」と呼ぶことにする。あまり検証してないので概要のみ。

  1. サーバ側のWireGuardで以下のようにトンネルを作成する(IPアドレスは後述の理由により192.168.137.1にする)。
  1. クライアント側はOpenWRTの例と同様にトンネルを作成する(IPアドレスは192.168.137.0/24から適当に選択)。
  2. 上記手順 11. と同じようにルータの設定を行う。
  3. サーバ・クライアント双方でトンネルを有効化する(クライアントは後からでもよい)。
  4. サーバ側でインターネットに接続されている方のNICについて、プロパティ→共有 タブのインターネット接続の共有でネットワークのほかのユーザーに、このコンピューターのインターネット接続をとおしての接続を許可する(N)をチェックし、ホーム ネットワーク接続(H)でwg0(1. でつけたトンネルの名前)を選択する(注:サーバ側のトンネルが有効でないとwg0を選択できない)。

ICSはデフォルトで192.168.137.1を強制的に割り振るので、めんどくさいからトンネルのアドレスをそれに合わせている。変更したい場合はレジストリエディタで HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters あたりをいじるといいかも知れない。

なお、速度に関してはVMware上のOpenWRTよりは速い感じがした。

参考にしたサイト

他にもあったような気がするが、主だったところで…(ありがとうございました)。

(2023.05.29 – 2024.05.23)


投稿日

カテゴリー:

投稿者:

タグ: