2022/03/09(水)OpenWrtでIPv6とDS-LiteとPPPoEを全部使う
OpenWrtを設定&構築したメモ。DS-LiteではなくMAP-Eでも参考になるかと思います。
- ことの発端
- 構築目標
- OpenWrtと対応機種
- OpenWrtのインストール
- IPv6パススルーの設定
- DS-Liteの設定
- PPPoEとマルチルーティングの設定
- ファイヤーウォールの設定
- フェイルセーフモードと強制復旧方法
- その他の設定
- 通信速度例
- 特定のポートアクセスをルーティングする(2024/05/17)
- まとめ
- メモ
※ネットワークの知識がない方はOpenWrtには手を出さないでください。
ことの発端
家庭内ルーターとして「NEC Atermシリーズ」を使っていたのですが、性能は申し分ないものの問題点があります。
- 最新機種でもDS-Lite使用時PPPoEをパススルーできない。*1
- そのせいで、PPPoEとDS-Liteの併用ができない。*2
- LAN内にDNSサーバを立てるとルータのDNSマスカレード機能が不安定になる。
WG1200HSはDS-Lite非対応なので、PPPoEと併用可能なら新しいのに買い替えてもよかったのですが、こんな状況ではAtermが選択肢に入らない。かといってBuffaloは安定性に問題ありそうなので、いっそのことOpenWrtルーターすればよいのでは? と。
構築目標
- PPPoEとDS-Liteを併用する
- LAN内の一部のマシンのみPPPoE側を使用する。
前提条件
- ルーターのWAN側にはONU(光回線終端装置)が接続されている。
- IPv6オプション(IPv6ネイティブ通信)が利用可能になっている。
- DS-Lite(or MAP-E等)が使える状況になっている。
- PPPoEが使える状況になっている(プロバイダ側で併用が許可されている)。
OpenWrtと対応機種
OpenWrtはLinuxで動作するフリーのルーターソフトウェアです。市販ルーター等のファームを入れ替えて使用することができます。
公式サイトの対応機種一覧を眺めてみると、TP-Linkあたりが価格も安く性能もそこそこでも入手性も良さそうです。今回はArcher A6を買ってみました(日本で発売されているものはA6 v3です)。
Device TechdataにCPU/Flash ROM/RAMが書かれていますので、対応ルーター選ぶ際は参考にすると良いです。
OpenWrtのインストール
ファームウェアダウンロードページから該当機種の「Install」用イメージをダウンロードし、ルーター(Stock ROM)のファームウェア更新画面からアップロードしてインストールします。
インストールに成功すると、192.168.1.1でルーターが起動しますので有線LANにPCを接続します(DHCPで自動取得するはず)。その後 http://192.168.1.1 にアクセスして、初期設定を行います。この辺の詳しい話は、検索すれば出てきますので、そちらを参考にしてください。
うまく行かない場合は、sshで192.168.1.1にアクセスし、root/passなしでログイン。下記コマンドを入力してください。
opkg update opkg install luci
luci(Webインターフェイス)の日本語化には「luci-i18n-base-ja」パッケージをインストールしてください。
IPv6パススルーの設定
まずはこれを設定しないと始まりません。WAN6インターフェイスの設定を開き、DHCP設定→IPv6設定の各種項目をリレーモードに設定します。masterを忘れずにチェックしてください。
続いてLANインターフェイスの、同じくDHCP設定→IPv6設定を開きます。こちらもリレーモードに設定しますが、masterはチェックしません(できません)。
設定の適用(もしくは再起動)をすれば、WAN6インターフェイスにIPv6アドレスが振られ、同じネットワークのアドレスのIPv6アドレスがLAN内にも振られるかと思います。
こうなればIPv6通信が可能になっているはずです。うまく行かない場合は、Firewallの設定を疑ってください。
解説
IPv6の経路情報は、RAやNDPといったICMPv6パケットでやり取りしています。これらの情報をリレーさせることで、ブリッジが実現するみたいです。
DS-Liteの設定
IPv6通信ができる状態になっていることを確認し、ds-liteモジュールをインストールします。opkgでも、Webの管理画面でもお好きな方法でインストールしてください。
既存のWANインターフェイス(DHCPv4)のプロトコルをDS-Liteに変更します。ファイアーウォールの手動設定をしたくなければインターフェイスを削除せず、必ず編集から変更してください。*3
- AFTRアドレス: gw.transix.jp(IIJmioの場合)
- プロバイダ指定のものを入力します。AFTRはIPoE(IPv4 over IPv6)トンネル通信の相手を示しています。IPv6アドレス直書きではなく、ホスト名が無難です。*4
- 詳細設定: 「トンネルインターフェイスのMTU」に1460
- MTU初期値が1280になっていますので、1460に設定します。
- 詳細設定: 「ピアから通知されたDNSサーバーを使用」のチェックを外す
- OpenWrtがDNSマスカレード(proxyみたいなもの)をしてくれているのですが、このDNSマスカレードの上位DNSとしてIPv6のものを使用したいからです*5。DS-Liteのものに上書きされたくないので、このチェックを外します。
LAN内からIPv4通信がうまくいけば成功です。うまく行かない場合は、Firewallの設定を疑ってください。
PPPoEとマルチルーティングの設定
PPPoE接続と条件によるルーティング振り分けを設定します。
ルーティングテーブルを増やす
OpenWrt(Linux)はルーティング時に参照するテーブルを複数持つことができます。テーブル情報ファイルにPPPoE用のルーティングテーブル情報を作成します。
/etc/iproute2/rt_tables ファイルを編集し、次の行を最後に追加します。
200 pppoe
Webインターフェイスからは編集できませんので、sshで接続しvi等で書き換えてください。
編集後、ルーターを再起動してください。
この作業を行いたくない場合は、以下の項目でルーティングテーブルを指定する際「prelocal (128)」を使用すれば問題なさそうです(未確認)。
pppoeインターフェイスを作成する
- エイリアスではない(デバイス一覧にある)wanデバイスを指定します。
- 詳細設定の「IPv4 ルーティングテーブルのオーバーライド」にpppoeテーブルを指定します。
- 詳細設定の「ピアから通知されたDNSサーバーを使用」のチェックを外します。
- ファイヤーウォールゾーンは既存の「wan」を指定してください。
- pppoeゾーンを分ける方法はファイアウォールの項目で説明します。
- DHCPタブで、DHCPサーバをセットアップしてから「このインターフェースを無視」をチェックします。DHCP→IPv6設定もすべて無効にします。
- この作業をしないと、wan側(wan6)のDHCPv6が機能しなくなります。
- 詳細設定の「IPv6アドレス取得」は無効にしないこと(自動のままにする)。
- 無効に設定すると、wan6がIPv6アドレスを取得できなくなります。*6
「デフォルトゲートウェイを使用」はチェックしたままにしておきます。これらの設定より、PPPoEによる接続とそのルーティング情報は、ルーティングテーブル「pppoe」に記録されるようになります。
ルーティング設定
メニューの「ルーティング」→「IPv4ルール」に移動し、ルーティング条件を設定します。
LANのIPは 192.168.1.0/24 とします。
画像では「192.168.1.1~62」の範囲のIPを持つ機器からの接続をPPPoE経由で接続するように設定しています。*7
ここまで設定できれば、指定範囲のIPを持つ機器からのインターネット接続はPPPoEを経由しているはずです。
接続が安定しない場合
サイトによって読み込みが不安定な場合、mssに原因があることがあります。ファイヤーウォール設定の「wan ⇒ REJECT」(Masqueradingにチェックがある)の編集を開き、「MSS clamping」をチェックします。
ファイヤーウォールの設定
ゾーン設定
今回は以下のように設定しました。
ゾーン設定をいじっていると個別のTraffic Rules(個別ルール)が消失し、一時的にネットに繋がらなくなることがあります*8。ネットワーク知識のない方はゾーン設定をデフォルトのまま使用し、決して変更しないでください。
Linuxのiptablesと同じですが、INPUTはOpenWrt自体へのアクセスを意味しています。基本的にINPUTはdropしたいのですが、間違えてLAN側からのINPUTをDROPするとルーターにアクセスできなくなりますので、(ゾーンではなく)基本ルールのINPUTはacceptのままにておきましょう(死亡した場合は復旧モードを参照)。
- 各ゾース詳細設定にある「Restrict to address family」は「IPv4 and IPv6」のままにしてください。
- 例えばDS-LiteはIPv4のみなので「IPv4」に、同様にwan6は「IPv6」に設定したくなりますが、これを設定すると同インターフェイスを共有する接続が死亡したりします。*9
- 「PPPoE ⇒ REJECT」の設定にある「MSS clamping」はチェックを入れてください。
- MTU/MSSを適切に設定し、各種のサーバと適切に通信するために必要です。
個別ルールの設定
デフォルトのままでも良いかと思いますが、自分で使用している最低限のルールを説明しておきます。
- DNS: DNSを正しく動作させるためのルールです。IPv6のDNSだけ生かしているので、IPv6だけ通過させています。
- DHCPv6: IPv6通信をするために必須です。
- ICMPv6: IPv6では経路情報等をICMPパケットで交換するため、IPv6通信に必須です。*10
最後の行は、LAN内のサーバをIPv6で外部公開するための設定です。細かいセキュリティはサーバ自体のip6tables(ファイヤーウォール)で行っていますので、ルータでは単純にパケット転送だけしています。
また、IPsecを構築する場合は、さらに追加のルールが必要になります。
フェイルセーフモードと強制復旧方法
OpenWrtには、設定ミスや何らかのバグ等で起動しなくなった場合の復旧方法が用意されています。
詳しくはFailsafe Mode, Factory Reset, and Recovery Mode(翻訳)にありますが、以下簡単に説明します。
ファクトリーリセット
OpenWrtの全設定消去機能です。OpenWrtが正常起動している状態(LEDが点滅していない状態)で、リセットボタンを10秒押し続けます。
モジュールやカーネルの不具合等で、そもそも起動しない(起動が無限ループしている)場合、この方法は使用できません。
failsafeモードへ
起動時に適切なタイミングでリセットボタン押します。
モード | LED点滅 |
---|---|
フェイルセーフ待機中 | 5回/秒 |
フェイルセーフモード | 10回/秒 |
通常起動 | 2.5回/秒 |
フェイルセーフモードの待機中にリセットボタンを押すとフェイルセーフモードに入ります。*11
フェイルセーフモードでは、ルーターは 192.168.1.1 のIPで起動しますので、LAN 1ポートに有線接続して、ssh ID:root/PASSなしでルーターにログインし、次のコマンドを入力します。
firstboot -y && reboot
これですべての設定を消去して、ルーターを再起動できます(CUIから個別に設定を修正することも可能ですが、この方が楽かと思います)。
リカバリーモード
OpenWrtの機能ではなく、ルーターそのものが持つ復旧手段を用いて、ルーターのファームウェアを復旧する方法が、Rescue from failed firmware upgrade(翻訳)にまとめられています。
TFTPを使うものが多いようです。
ここにある方法を使うと、OpenWrtから元のルーターファームに戻すといったことも可能になります。
その他の設定
ルーティング/NATのオフロード設定
カーネルのルーティング負荷を減らす設定がファイヤーウォールの項目に存在します。Hardwareオフロードはデバイスによるかと思いますが、Archer A6(MediaTek MT7621)ではこの設定でパフォーマンスが倍ぐらい良くなるので、各自確認すると良いかと思います。
PPTP接続(VPN接続)のパススルー
このままでは、LAN内のPCからの外部のPPTPサーバへの接続がうまく行きません。DS-LiteやMAP-EはそもそもVPN接続ができませんが、PPPoEでも設定が必要です。
PPTPの場合、GREという特殊なパケット*12が通過できないのが原因です。「Port Forwards」で設定する方法もありますが、LAN側のIPを固定する必要が出てくるのでカーネルにモジュールを導入します。
- パッケージ管理ツールから「kmod-nf-nathelper-extra」をインストール。
- 「システム」→「スタートアップ」→「ローカルスタートアップ」のexitより前に次を追加。
sysctl net.netfilter.nf_conntrack_helper=1 sysctl net.netfilter.nf_conntrack_gre_timeout_stream=86400
※sysctl.confを書き換えても構いません。
サーバの外部公開
もしLAN内にサーバがありIPv4で外部公開したい場合は、ファイヤーウォールの「Port Forwards」の項目を設定します。
ゾーンごとの設定になりますので、意味のないDS-Lite側のポート転送を一緒に設定したくなければ、ゾーンを分離する必要があります。
通信速度例
IIJmio + DS-Lite, OpenWrt on Archer A6(v3), check by iNoniusスピードテスト.
見ての通りPPPoEのほうが速いのですが、PPPoEはたまに極端な速度低下をするので、その点DS-Liteのほうが安定している印象です。
余談
元々、LAN側4ポートの中に1つ100Mbpsの機器があり、それがあるとLAN→ルーターへの転送(LAN内転送は問題ない)が100Mbpsで頭打ちになる問題がありました。
Archer A6のLAN側はスイッチではなく、イーサネットが4ポートある仕様になっています。この辺ドライバの仕様っぽい感じなので4ポートブリッジをやめ、「3ポートブリッジ」+「1ポート」とVLANを分けて対策しました。
※追記:OpenWrt 23.05.3に更新したところ、この謎症状は治ったようです。
特定のポートアクセスをルーティングする(2024/05/17)
アクセス元を指定したルーティング(PPPoE/DS-Liteの振り分け)の設定を応用して、特定ポートへのアクセスをルーティングします。
具体的には、Androidのプッシュ通知用のTCP接続をすべてPPPoEに振り分ける設定を行います。
- Android(Google FCM)のプッシュ通知はTCPの5228~5230ポートを使用している。
- この接続の接続先は fcm.googleapis.com であるが、IPアドレスは固定ではない。
- プッシュ通知のTCP接続は30分以上維持する必要がある。
- GoogleのFCMに関する資料に「ポート5228~5230での接続に30分以上のタイムアウトを設定してください」と記載あり。
- transixのDS-Lite環境では、IPv4 TCP接続(Established)は330秒程度で切断されてしまう。
- つまりDS-Lite環境ではプッシュ通知が遅延することが(多々)ある。
OpenWrtの初期設定では、TCPタイムアウトは2時間になっているので、PPPoE側にルーティングさえすれば問題ありません。
firewallでマークを付ける
ポートを指定して直接ルーティングすることは不可能なので、まず該当のパケットにファイヤーウォールを使用してマークします。
「ネットワーク」→「ファイヤーウォール」→「トラフィック・ルール」に進んで次のようなルールを追加します。
ルーティングを設定する
「ネットワーク」→「ルーティング」→「IPv4 ルール」に進み、pppoeテーブルを参照するルールを追加します。詳細設定の「Firewall mark」に「5228」(上で設定したマーク値)を設定するのを忘れないようにしてください。
ポートによるルーティングまとめ
この設定を応用すると、sshだけ特定のインターフェイス(PPPoE)からアクセスするといったことも可能になります。
DS-Liteのポート数制限(1024らしい)も考慮すると、Webアクセス(80と443)のみDS-liteからアクセスするほうが平和かも知れません。
設定後、通知のタイムラグが減ったように感じるので効果はありそうです。テストすればいいだろうと言われそうですが、元々送る側の設定として優先度が存在し、「優先度:高」ではない通知はそもそも遅延するので、(簡単に試せる優先度標準の通知で)テストしても意味がないのです……。
まとめ
- 安価で、非常に自由度の高いルーターを手に入れた。
- OpenWrtの設定はWebインターフェイスだけで、ほぼ困らない。
- OpenWrtは安定しているが、設定時の注意点(罠)が多い。
Linuxなので、ネットワークを柔軟に設定できるのがとても良いです。
メモ
ルール(ルーティングテーブルの参照)設定を確認する。
ip rule
特定のルーティングテーブルの中身を表示する。
ip route show table pppoe