OpenBSD で PPPoE と IPoE(MAP-E)の両立
コンテンツ
OpenBSD で IPv4 PPPoE と IPv4 IPoE (MAP-E) の両方をポリシーベースルーティング(Policy-Based Routing)とVRF(Virtual Routing and Forwarding)相当の技術で実現したときのメモ。
ポリシーベースルーティングは pf(4) を利用し、VRF は rdomain(4) を利用する。
PPPoE と IPoE を並用する理由
OpenBSD カーネルにパッチをあてて IPoE (MAP-E) を動作させたため IPv4 の通信路として IPoE 方式と PPPoE 方式の両方が使えるようになった。 各方式の特徴は次の表のようにまとめられることが多く(ただし、私の環境では通信速度に顕著な差はない)、一長一短となっている。
方式 | 通信速度 | ポート範囲 |
---|---|---|
IPoE | 速い | 制限あり |
PPPoE | 遅い | 制限なし |
例えば
- Web アクセスや動画視聴、データダウンロードする際は IPoE を使い、
- SSH などのサービスを公開する際は PPPoE を使う、
とすれば両者の良いとこどりができる。
概念的には次のようなネットワークトポロジでトラフィックに応じて使用するリンク(PPPoE もしくは IPoE)を選択する。
|
|
しかし通常のIPルーティングでは宛先IPアドレスのみでルーティング先が決まるため、上記の実現は困難である。 またルーティング先はデフォルトゲートウェイで決まり、デフォルトゲートウェイは一つだけしか指定できないので複数リンクを使いわけることは困難である。
そこで、送信元IPやプロトコル情報などを含めてルーティングするポリシーベースルーティングと複数のルーティングテーブルを利用できる VRF 相当の技術を利用する。 それぞれ pf(4) と rdomain(4) を利用する。
最終的には次のような構成により PPPoE と IPoE を並用する。
|
|
Routing domain による複数ルーティングテーブル
OpenBSD の rdomain(4) は linux の network namespace 相当の機能をもち、複数のルーティングテーブルと routing domain をもつことができる。 Routing domain はルーティングテーブルとインターフェイスをもつ。 インターフェイスに到着したパケットはインターフェイスが所属する routing domain のルーティングテーブルに従いルーティングされる。
デフォルトの routing domain である rdomain 0 は常に存在している。この rdomain 0 に IPoE インターフェイス gif0
が存在するとして、別の rdomain に PPPoE インターフェイス pppoe0
を作成し、名前が解決できるように設定する。
Routing domain 1 に PPPoE インターフェイスを追加する
通常と同じように /etc/hostname.pppoe0
で設定する。このとき rdomain 1
を追加してインターフェイスが所属する routing domain を指定する。
|
|
コマンド doas sh /etc/netstart pppoe0
などでインターフェイスを作成したあとに netstat -R
で各 routing domain に所属するインターフェイスと routing table を確認できる。
|
|
動作確認
OpenBSD の ping(8) は使用するルーティングテーブルをオプション -V
で指定できる。さきほど作成した PPPoE にひもづくルーティングテーブル 1
を使用するには次のようなコマンドを実行する。
|
|
Linux の ip netns exec
相当は route(8) のオプション -T
で実現でき、指定したルーティングテーブルでコマンドを実行できる。よって ping
のオプション -V
を使用せずにルーティングテーブル 1
から ping
を実行するには次のようなコマンドを実行する。
|
|
Routing domain 1 で名前が解決できるように unwind
を起動する
新しい routing domain を作成した場合、 dig
などで名前が解決できないことがある。例えば /etc/resolv.conf
で nameserver 127.0.0.1
など routing domain 0 で起動している unbound
が指定されている場合である。このとき routing domain 0 と 1 は分離しているため routing domain 1 から routing domain 0 の unbound
へ通信ができないため名前解決ができない。
そこで routing domain 1 で名前解決ができるように unwind
を起動する。
設定ファイル /etc/unwind.conf
を例えば次のように編集して public DNS サーバを指定する。
|
|
次に unwind
が routing domain 1 で動作するように設定する。
|
|
これで routing domain 1 の 127.0.0.1
で unwind
がDNSをリッスンするので名前が解決できるようになる。
動作確認
次のようなコマンドで実際に PPPoE と IPoE でそれぞれ通信が確認できる。
|
|
サイト http://ifconfig.io はアクセス元のIPアドレス情報を表示する。よって上のコマンドではそれぞれ PPPoE と IPoE のIPアドレスが表示される。
両方の routing domain で SSH を起動する
SSH も unwind
同様に rcctl
でも routing domain を指定できるが、 設定ファイル /etc/ssh/ssd_config
で指定できる。設定の ListenAddress
で listen する routing domain を次のように指定できる。
|
|
上の設定で sshd
はデフォルトの routing domain 0 で全ての IPv4 と IPv6 アドレスでリッスンし、 routing domain 1 の全ての IPv4 アドレスでリッスンする。
PF によるポリシーベースルーティング
Routing domain とコマンド route
や rcctl
により OpenBSD から送信されるパケットが PPPoE か IPoE どちらを通るか制御できる。一方で LAN 内のホストから送信されたパケットは routing domain 0 のデフォルトゲートウェイである IPoE を経由してインターネットへ抜ける。
これは LAN 内からのパケットは virtual ethernet bridge である veb0
に到着し、このインターフェイスは routing domain 0 に所属するためである。
そこで PF を利用して LAN 内から到着した特定のパケットを routing domain 0 から 1 に移動して、 PPPoE を経由してインターネットへ抜けるように設定する。
PF ではなく pair(4) でふたつの routing domain を接続し、特定のパケットだけ pair インターフェイスを通し、別の routing domain に流す方法もある。この場合はルーティングテーブルによりパケットが routing domain を移動するので宛先のみでどの routing domain を使用するか決める必要がある。一方で PF の場合は送信元IPアドレスやポート番号も含めてどの routing domain を使用するか決められるため柔軟性が高いため PF を使用する。
経路選択に使用されるルーティングテーブルの変更
PFの設定 pf.conf
でキーワード rtable
を使うことで使用されるルーティングテーブルを変更することができる。
例えば、テーブル via_pppoe
で指定された宛先をもつパケットの経路選択にルーティングテーブル 1
を使用するには次のように設定する。
|
|
特定の LAN 内ホストからのパケットの経路選択にルーティングテーブル 1
を使用するには次のように設定する。
|
|
戻りのパケットのルーティングテーブルを変更するルールは不要である。これは行きのルールマッチ時に作成される state が行きと戻りのパケット両方にマッチするためである。
具体的な pf.conf
の設定例
ポリシーベースルーティングと PPPoE インターフェイスに関連する設定だけ抜粋すると例えば次のような設定となる。
|
|
前半で NAT、後半でポリシーベースルーティングを設定している。
おわりに
PF と routing domain を利用して PPPoE と MAP-E を並用できるようにしたが、通信品質計測してみたところ、私の環境ではどちらの経路も通信品質に大差ないようで残念であった。
作成者 Toru Mano
最終更新時刻 2023-01-01 (c70d5a1)