IPoEに対応したPR-S300HIでのサーバ運用について
本稿では、ポートフォワーディング機能が無効化されたIPoE対応ファームウェアの「ひかり電話ルーター(ホームゲートウェイ)」PR-S300HIでサーバ運用する方法について検証します。
2022-09-30
iEPGサーバを運用している実家のインターネット回線は「ドコモ光 for OCN」なのですが、その「ひかり電話ルーター(ホームゲートウェイ)」PR-S300HIの接続方式が2022年6月にPPPoEからIPoEに変更されました。この変更はファームウェアの自動更新と併せて行われており、新しいファームウェアではIPv4でのポートフォワーディング機能が削除されてしまいました。つまり、IPv4では外部からLAN内の端末に接続できなくなり、公開サーバの運用ができなくなりました。本稿の目的は、この制限を克服し、再びPR-S300HIを通して外部からLAN内の端末に接続できるようすることです。
まず、PR-S300HIの仕様と各解決策を検討し、次にIPoEと解決策であるPPPoEの追加について言及します。その後、本稿最大の難関、ルーティングについて考察、最後に名前解決について補足し、まとめとなります。
実行環境は、LAN内のメインサーバ(Intel Core i5-2400 3.10GHz)は、Fedora Core 34 (kernel 5.17.12-100.fc34.x86_64)、バックアップサーバ(Dell Latitude D530, Intel Core2 Duo T7250 2.00GHz)では、Fedora Core 35 (5.17.12-200.fc35.x86_64)となっています。
PR-S300HIは光回線をイーサネット回線に変換するONU部と1000BASE-Tx4のハブを併せ持つルータ部から構成されています。WLANも追加できますが、当環境では使用していないのでWLANについては割愛します。ONU部は特に設定が必要なものはなく、ルータ部は一般的なルータと同様な機能を持ち、ポートフォワーディングなどの設定が可能でしたが、IPoE接続になってからはポートフォワーディングの機能は削除されてしまいました。通信速度については計測ツールなどで測った場合、安定して200~300Mbps、最大では600Mbps強の速度が出ます(IPoE接続時)。実際のダウンロードでも20MB/s強は出ます。
ここではこのポートフォワーディングが無効化されたPR-S300HIで再びポートフォワーディングを有効化する方法を検討します。まず、最も簡単な方法はIPoE接続から再度PPPoE接続に戻してもらうことです。これはOCNに連絡して申請すれば30分ほどで可能だそうです(ドコモ光 for OCNの場合)。この対策は元に戻すだけなので追加の設定等は必要がなく、簡単確実ですが、IPoEの恩恵を受けられないので本稿ではこの方法は採用しません。
次の候補は、「ひかり電話ルーター」の変更です。IPoE接続でポートフォワーディングが無効化される仕様は「ひかり電話ルーター」の300番台(旧機種)に限られ、400番台以降ではIPoE接続でもポートフォワーディングが可能とのことです。「ひかり電話ルーター」のレンタル契約では故障しない限り、交換できないことになっているのでダメモトでOCNに頼んでみるしかないのですが、それなりに対応してくれるらしいです。ただ、この対策は、仮に交換が認められたとして本体の到着には数日かかるため本稿ではすぐ実行できる次の対策が上手くいかなかった場合に選択することとしました。
そして、実際に選択した対策は、IPoE接続の他にPPPoE接続を追加するというものでした。元々、PR-S300HIにはルータ越しには接続できないゲームやアプリに対応するためパソコンなどの機器がグローバルIPで直接インターネットに接続できる「PPPoEブリッジ」という設定があり、その機能はIPoE対応ファームウェアでも維持されています。これならば外部からの接続はPPPoEが担当し、それ以外はIPoEを使うという運用が可能です。ただし、この方法では自力でPPPoE接続を確立する必要があり、また、一つのサーバでゲートウェイを2つ持つことになるためルーティングの難易度が上がってしまうのが難点です。PPPoEについては
第4項、ルーティングについては
第5項にて改めて考察します。
実際の解決策に言及する前にIPoEについて少しふれます。PPPoEはダイアルアップで二点間を接続し、その二点間で通信するイメージとすればIPoEは単純にハブへ繋ぐイメージです。ハブへ繋ぐだけで接続が完了するならPPPのような認証は?となりますが、IPoEでは機器を個別に識別しているのでPPPのようなユーザ認証は不要です。このため、中古等で「ひかり電話ルーター」を入手してもただ交換しただけでは、通常、接続できません。
また、ここまで外部からの接続ができなくなったと繰り返してきましたが、厳密にはIPv6では外部からの接続が可能です。OCNのIPoE接続では、IPv6とIPv4の2つのIPアドレスを持ち、IPv6では容易に外部からのアクセスが可能ですが、IPv4のパケットはIPv6にカプセル化(IPv4 over IPv6)されて通信されるため様々な制限が生じます。IPv4では外部からの接続が困難になるのもその一つです。
このIPv4のカプセル化(IPv4 over IPv6)はIPv6へ完全移行するまでの過度的な技術で早く不要になってほしいものですが、NTTのNGN網は世界最大級のIPv6ネットワークであり、言うなればIPv6は日本のガラパゴス仕様である可能性さえあるので気長に待つしかないようです。実感では2022年現在のIPv6使用率は全体の3割に満たないぐらいで今が一番やりにくい混在状態に感じます。
IPoEで接続されているPR-S300HIにさらにPPPoEセッションを追加するには「PPPoEブリッジ」を有効にした上でPR-S300HIに接続されたルータ等が必要です。PR-S300HIはPPPoEに関しては透過的に中継するだけで何もしないので接続の操作を行うルータ等が別に必要となります。本稿ではメインサーバがそれを担います。このメインサーバには2つのNICが装備されており、それぞれ、IPoE、PPPoEでインターネットに接続されます。IPoEではPR-S300HIがルータの役目を担っており、PPPoEではこのメインサーバがルータの役目を担います。ただし、ルータとしての設定については
次項に譲り、本項ではPPPoE接続の確立についてのみ言及します。
PPPoE接続ツールとしてここではrp-pppoe(3.15-2.fc35.x86_64)を使っています。pppoe-setupで設定を登録し、pppoe-startを実行すれば接続されます。pppoe-setupを実行すると対話的に設定値を入力するよう促されるので設定はそれに答えていくだけです。
入力項目は、PPPインターフェイス名、アカウント名(LOGIN NAME)、ネットワークインターフェイス名(INTERFACE)、接続状態維持の可否、DNS、パスワード(PASSWORD)、一般ユーザの実効権(USERCTRL)、ファイアウォール(FIREWALLING)、ブート時の有効化です。一見、設定項目がたくさんあって難解に見えますが、本当に重要なのはアカウント名とパスワードくらいです。
PPPインターフェイス名はこのPPPoE接続で作成されるインターフェイス名で通常(デフォルト)はppp0です。デフォルト値はシステム依存で、pppoe-setupが自動検出します。PPP接続が複数ある場合などに識別するため任意のインターフェイス名を設定できます。本稿ではデフォルトです。
アカウント名(LOGIN NAME)はプロバイダ指定のものを入力します。
ネットワークインターフェイス名(INTERFACE)はPPP接続に使用するネットワークインターフェイスを指定します。デフォルトはeth0ですが、本稿ではeth0はIPoE接続に割り当てられており、PPPoE接続にはeth1を使っています。最近の環境ではeno1などの新しい命名法が用いられていることも多いので自己の環境に合わせた設定が必要です。
接続状態維持の可否は、繋ぎっぱなしにするか、一定時間通信が無いときは回線を切断するかの選択です。一定時間のアイドル状態で切断したいときはその秒数を指定し、繋ぎっぱなしにする場合はnoを入力します。デフォルトはnoで、本稿では繋ぎっぱなしです。
DNSはDNSを指定します。何も入力しなければPPPoE接続時にDNSに関する操作を行いません。本稿では元々このメインサーバがDNSを兼ねており、DNSに関する操作はここではとくに設定していません。
パスワード(PASSWORD)は先に入力したアカウント名(LOGIN NAME)に対応したパスワードを設定します。
一般ユーザの実効権(USERCTRL)はroot以外のユーザにPPPoE接続の実行権を付与するか否かを指定します。本稿ではrootのみに実行権を付与しています。ファイアウォール(FIREWALLING)とブート時の有効化はpppoe-startとは別個に実行するのでここでは何も設定していません。
設定を確認し、pppoe-setupが正常終了すれば後はpppoe-startで接続できます。pppoe-statusで
pppoe-status: Link is up and running on interface ppp0
と表示されれば完了です。なお、このPPP接続が確立してもPR-S300HI本体のPPP用LEDは点灯しません。
PPPoE接続を単に追加しただけでは外部から接続できません。メインサーバのデフォルトゲートウェイはIPoE側になっており、PPPoE側から入ってきたパケットに対する返信もIPoE側から送出されてしまうからです。このため、PPPoE側から入ってきたパケットへの返信はPPPoE側から送出する設定が必要です。これは「ip rule」で行います(ポリシーベースルーティング)。デフォルトでは以下のようになっています。優先度32766のmainが通常のルーティングテーブルで「ip route」で表示されるルーティングテーブルです。
# ip rule
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
# ip route
default via 192.168.1.1 dev eth0 proto static metric 100
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.103 metric 100
ppp.oe.addr.aaa dev ppp0 proto kernel scope link src aaa.aaa.aaa.aaa
メインサーバのIPアドレスは192.168.1.103、IPoE側のデフォルトゲートウェイ(PR-S300HI)は192.168.1.1となっており、上記、優先度32766のmainテーブルが通常のルーティングテーブルでこのmainテーブルを参照する前にPPPoEの設定を挿入します。PPPoE側から入ってきたパケットの宛先IPは、当然、PPPoE(ppp0)のIPアドレスになっており、返信元のIPアドレスもこのIPアドレスになります。このIPアドレスをaaa.aaa.aaa.aaaとすると
# ip route add table 1 default dev ppp0
# ip rule add from aaa.aaa.aaa.aaa table 1 prio 100
最初の「ip route add」でppp0(PPPoE)をデフォルトゲートウェイとするルーティングテーブルを作成し、次の「ip rule add」でaaa.aaa.aaa.aaaから発信されるパケットはtable 1(ppp0がデフォルトゲートウェイ)を参照するように指示しています。
# ip rule
0: from all lookup local
100: from aaa.aaa.aaa.aaa lookup 1
32766: from all lookup main
32767: from all lookup default
これで、メインサーバ自体は外部からの接続が可能になります。しかし、まだルータとしては機能しておらず、メインサーバ(ルータ)を介してLAN内の端末と接続することはできません。まず、第一段階としてIPマスカレードを設定します。LANのプライベートネットワークは仮に192.168.1.0/24とします。
# iptables -t nat -A POSTROUTING -o ppp0 -s 192.168.1.0/24 -j MASQUERADE
# echo 1 > /proc/sys/net/ipv4/ip_forward
通常、ルータとしての設定はこれで十分なのですが、本稿の場合、メインサーバの本来のデフォルトゲートウェイは外部からは接続できないIPoE側(eth0)にあるので、PPPoE側(ppp0)をデフォルトゲートウェイとし、外部から接続するLAN内端末のための設定が必要です。これは単純に前述のIPマスカレードと連携するように
# ip rule add from 192.168.1.0/24 table 1 prio 1000 #table 1はゲートウェイがppp0
# ip rule
0: from all lookup local
100: from 180.1.83.73 lookup 1
1000: from 192.168.1.0/24 lookup 1
32766: from all lookup main
32767: from all lookup default
とすればいいのですが、こうすると、結局、メインサーバのデフォルトゲートウェイはppp0のみになってしまい、メインサーバではIPoE接続が無意味になってしまうのでIPマスカレードで外部から接続する必要のある端末だけがppp0のゲートウェイを使うようにします。メインサーバのIPアドレス(eth0)は192.168.1.103で、このIPアドレスの場合はtable 1を参照しないようにします(mainテーブルを参照するようにする)。具体的には
# ip rule add from 192.168.1.104/29 table 1 prio 1000
とし、192.168.1.104 ~ 192.168.1.111の端末だけがppp0のゲートウェイを使うようにしています。当環境では192.168.1.106がビデオサーバ、192.168.1.110がバックアップサーバになっており、外部からの接続に対応していますが、それには別途ポートフォワーディングの設定が必要です。以下では、ppp0(IPアドレスaaa.aaa.aaa.aaa)のポート8106に接続すると192.168.1.106(ビデオサーバ)のポート80(webサーバ)に接続されます。
# iptables -t nat -A PREROUTING -i ppp0 -p tcp --dport 8106 -j DNAT --to 192.168.1.106:80
本稿ではポートフォワーディングやセキュリティ等の運用面については主題ではないのでこれ以上ふれませんが、当然、重要な課題です。
また、ppp0の自アドレス(aaa.aaa.aaa.aaa)を発信元としてLAN内の端末へと向かうパケットは先述した優先度100の設定でppp0へと戻されてしまい、LAN内の端末に届きません。この問題を回避するためLAN内へのパケットはppp0ではなくeth0へと向かうように設定します。
# ip route add table 2 default dev eth0
# ip rule add to 192.168.1.0/24 table 2 prio 10
# ip rule
0: from all lookup local
10: from all to 192.168.1.0/24 lookup 2
100: from aaa.aaa.aaa.aaa lookup 1
1000: from 192.168.1.104/29 lookup 1
32766: from all lookup main
32767: from all lookup default
これでメインサーバのルータ、ゲートウェイとしての設定も終了です。あとは各LAN内端末の設定になります。都合、このLANには本来のデフォルトゲートウェイであるPR-S300HI(192.168.1.1)、外部からの接続に対応したメインサーバ(192.168.1.103)が持つゲートウェイ(ppp0)の2つのゲートウェイがあります(厳密にはバックアップサーバにバックアップ回線のゲートウェイもあります)。各端末はデフォルトゲートウェイとしてどちらかを選ぶことになります。外部からの接続に対応したい場合はメインサーバ(192.168.1.103)をデフォルトゲートウェイに選択し、それ以外はPR-S300HI(192.168.1.1)をデフォルトゲートウェイに選択します。実際の物理的ネットワーク構成は下図のようになっています。
メインサーバからは2つのLANケーブルが出ており、同一のハブに接続されています。メインサーバとPR-S300HIは論理的には2つのセッションで繋がっていますが、メインサーバは、ハブを介し、物理的には一本のLANケーブルでPR-S300HIと繋がっています。兼用しても特にスループットに影響が出るようなことはないと思っています。また、わざわざNICを二枚にせず、単独のNICを2つのネットワークインターフェイスに仮想化しても運用可能なはずですが、検証はしていません。
当ドメイン運用のiEPGサーバ(メインサーバ)は6月下旬からIPv4では外部から接続できなくなっていた(iEPGサーバとして機能していなかった)わけですが、どう対応していたかというとIPv4に関してはバックアップサーバが処理を担当していました。どういうことかと言うと、iEPGサーバ・malva.karing.jpを名前解決するとAAAAレコード(IPv6)はメインサーバのIPアドレスを返し、Aレコード(IPv4)はバックアップサーバのIPアドレスを返すようになっていました(バックアップサーバの回線はイオンモバイル)。つまり、一つのホスト名に2つのサーバが割り当てられていました。
本稿ではサーバは一台になりましたが、2つのゲートウェイを持つことから似たような状況になります。karing.jpの名前解決はmydns.jpで行われており、mydns.jpはwebサーバにアクセスしてきたIPアドレスを登録する仕様になっています。よって、IPv6はIPoE側からmydns.jpにアクセスし、IPv4はPPPoE側からmydns.jpにアクセスします(mydns000000:xxxxxxxxxは認証情報)。
# wget -O - https://mydns000000:xxxxxxxxx@ipv6.mydns.jp/login.html
IPoE側(IPv6)はIPv6の特性上、特に何もしなくても想定通りに登録できますが、問題はPPPoE側(IPv4)です。何もしなければデフォルトゲートウェイ(IPoE側)が使われてしまうのでppp0を選択的に使いたければppp0(もしくはそのIPアドレス)を明示的に指定する必要があります。この場合、wgetでは"--bind-address"オプションを使います。ppp0のIPアドレスを調べてその値を指定し、mydns.jpの登録サイトへアクセスします(PPPoE側、ppp0のIPアドレス aaa.aaa.aaa.aaa)。
# wget --bind-address=aaa.aaa.aaa.aaa -O - 'https://mydns000000:xxxxxxxxx@ipv4.mydns.jp/login.html'
発信元を任意に選択して送信するということが意外に難しく、各アプリケーション個別の対応状況に依存します。wgetとpingは発信元選択に対応しているのでテストや確認で困ることはあまりないのですが、その方法に辿り着くまでは少々の時間を要しました。
実家の光回線が5月下旬頃から二度ネットワーク障害を起こし、6/24以降は外部からの接続ができなくなってしまいました。外部からの接続不能は接続方式変更(PPPoE→IPoE)によるもので、この変更前の二度のネットワーク障害は変更にともなう工事によるものだったと邪推しています。このネットワーク障害時、各所に問い合わせをしてみたわけですが、再起動しろだの、コネクタの挿抜だの、設定がどうのだの…こんなのはハードのエラーかネットワーク障害のどちらかでしかないと確信していても向こうのオペレータさんにはこちらの状況やスキルはわからないだろうと仕方なく付き合いましたが、ネットワーク障害でした、てへぺろ、でブチ切れそうになりました、だから最初からそう言ってるだろ!
そんなこんなで本稿のポリシーベースルーティングです。2つのゲートウェイを持つ設定はバックアップサーバで経験済みだったのでそんなに悩みませんでしたが、初見だったらけっこう苦労したかもしれません。バックアップサーバのデフォルトゲートウェイであるバックアップ回線(イオンモバイル)は20KB/sくらいしか出ないのでバックアップサーバに接続されたWebカメラのストリームはPR-S300HI(光回線)経由で再生していました。
しかし、PR-S300HIはIPoE対応機としては最初期の製品であり、実働で10年くらいになるのでこの機にNAT機能が有効な次世代機に交換できるなら交換しても良かったかなと思わないでもないです。ネット上の経験談を見るにOCNの対応も親切丁寧のようで自分も試してみようかなという気にはなるものの、自宅のADSLルータは20年近く動いているので10年くらいで文句言うなとも言われそうな気がして、とりあえず、現在は問題解決できたのでこれでいいかとなっています。