疑似フレッツ光網内の通信を accel-ppp で再現できるか検証する(検討編)

はじめに

この記事は BBSakura Networks Advent Calendar 2023 の 12 日目の記事です。 adventar.org

こんにちは、BBSakura Networks 株式会社の佐藤です。

「インターネット」をテーマに色々と調べていたら、登 大遊さんが書いた資料「230610 講演 第1部 (登) - 配布資料その1 - 秘密の NTT 電話局、フレッツ光、インターネット入門.pdf」を見つけました(こちらからダウンロードできます)。

資料の中ではフレッツ光の内部構成が紹介がされており、宅内 PC・ルータが PPP セッションを経由して ISP に接続するまでの通信フローの解説はとても興味深いものでした。

この記事では検討編と称してフレッツ光網内で PPP セッションが生成されるまでのフローを OSS の組み合わせで再現できるかを検証するために検討したことを紹介します。 余力があれば今後「実装編」を書く予定です。

なお上記の資料は資料内でも述べられているとおり NTT 公式の資料ではないです。資料内に掲載されている内部構成図についても「観測結果だけから検証して作った図」と述べてます。 このため本記事で扱うネットワークは、フレッツ光網に似た「疑似フレッツ光網」となります。

疑似 NTT フレッツ光と PPP セッションの関係

疑似 NTT フレッツ光の概要

疑似 NTT フレッツ光は宅内の PC ・ルータと ISP を中継するネットワークです。上記資料の pp.44-60 でその詳細が説明されています。中継機能の根幹を担う機器が、フレッツ収容ルータと網終端装置です。フレッツ収容ルータは宅内ルータからの通信を L3 終端するゲートウェイとして機能し、網終端装置は ISP との接続点としての役割を果たします。

フレッツ収容ルータと網終端装置の関係を示した概略図。左から右に、宅内のネットワーク、最寄りの電話局のネットワーク、NTT フレッツのバックボーンネットワーク、ISPのネットワーク、の順でネットワークが並び、各ネットワーク内に配置された機器の図を線で結ぶことで、各ネットワークのどの機器同士が接続しているのかを示しています。
フレッツ収容ルータと網終端装置の関係を示した概略図

PPP セッション確立までの流れを資料から読み解く

上記の資料ではフレッツ収容ルータ・網終端装置の振る舞いが記述されています。その一部を下記に抜粋します。

1.ユーザ名(@ より後)で表を検索して接続先となる ISP を決定する(pp.58-59)

(a) 収容ルータは、ユーザーが PPPoE 接続を自宅側から開始したとき、それをどの ISP に接続するか、決定しなければならない。これは、PPPoE 接続におけるユーザー名 username@example.org のような文字列のうち @ よりも後の文字列をもとに、表を検索して決定する。

2.フレッツ収容ルータと網終端装置の間は L2TP を利用する(pp.57-58)

(a) と (b) との間は、PPPoE トンネル (PPPoE: Point-to-Point Protocol over Ethernet。詳しくは後述する。) が張られるが、より正確には、PPPoE の中の PPP というプロトコルを収容ルータで取り出して、これを L2TP (Layer-2 Tunneling Protocol) という UDP プロトコルの一種 (このあたりは、固有名詞なので、分からなくても差し支え無い。今後の続編で詳しく述べる。) に入れ、L2TP の UDP パケットとして飛ばす。

3.ユーザ認証は網終端装置を経由して ISP 毎に設置された RADIUS サーバに問い合わせる(pp.58)

PPPoE の接続は、ユーザー認証を必要とする。ISP は契約しているユーザーからの接続のみを受付けたいためである。そこで、網終端装置から ISP の RADIUSサーバー (ユーザー認証サーバーのことである。詳しくは続編で述べる予定である。) に認証のお伺いが届く。

このように NTT フレッツ光では、接続時のユーザ情報から経由する ISP を判断し、通信経路の生成・決定をしています。

PPP セッション確立までの流れを整理

上記の振る舞いを通信フローとしてまとめたのが下図になります。

PPP セッション確立までの流れを示した図。この図で示した処理の流れは、このあと文書で説明しています。
PPP セッション確立までの流れ

最初にフレッツ収容ルータは以下の処理を実行します。

1. 宅内ルータとの間に PPPoE セッションを生成
2. ユーザ名( @ の後ろ )をキーとして接続先となる網終端装置を問い合わせ
3. 網終端装置との間に L2TP セッションを生成
以降、網終端装置に PPP セッション処理を引き継ぎ、通信を中継に徹します。

処理を引き継いだ網終端装置はフレッツ収容ルータと連携して以下の処理を実行します。

4. ISP 内の RADIUS サーバにユーザ情報を送信 & 認証結果受け取り
5. 結果を宅内ルータに送信し、残りの PPP ネゴシエーションを実施

上記が完了後、宅内ルータと網終端装置の間に PPP セッションが確立して ISP を経由したインターネットへの通信が可能になります。

今回のテスト項目を検討

おおまかな通信の流れが整理できたので今回のテスト項目を整理します。また、OSS で動作検証するためのネットワークを検討します。

テスト項目

動作検証のためのネットワークで以下を実現することを本検証の目的とします。

  • 宅内ルータと網終端装置の間で PPP セッションを確立できること
  • ユーザ名に応じて接続先となる網終端装置・ISP が区別されること
  • PPP セッション確立後は ISP を経由した通信ができること

検証用ネットワーク

以下の図のネットワークを netns, bridge, veth を利用して Linux 上に構築します。

検証用ネットワークの構成図。検証用に用意したネットワークとそのネットワーク内に配置する機器の接続関係を示しています。この後に説明する構成要素間の接続関係を線としてつなげることで表しています。
検証用ネットワークの構成図

構成要素: netns

netns 名 疑似フレッツ上の役割 OSS 検証用ネットワーク上の役割
home-1,2 宅内ルータ rp-pppoe PPPoE クライアント
sse フレッツ収容ルータ accel-ppp PPPoE サーバ・L2TP クライアント・RADIUS クライアント
dispatch 振り分けサーバ free-radius RADIUS サーバ
nte-1,2 網終端装置 accel-ppp L2TP サーバ・RADIUS クライアント
isp-rt-1,2 ISP ルータ - 経路制御
isp-radius-1,2 ISP RADIUS free-radius RADIUS サーバ

構成要素: bridge

bridge 名 疑似フレッツ上の役割
onu-sw home-1,2 - sse 間のネットワーク
core-sw バックボーン内のネットワーク
isp-sw-1,2 ISP 内のネットワーク

成否の判断

まず、home-1 - nte-1 および home-2 - nte-2 でそれぞれ PPP セッションが確立することを確認します。その後、home-1 から home-2 に ping を実行して ISP 1, 2 経由で疎通が確認できたら検証成功と判断します。

選択した OSS と今回の要件の比較

今回のネットワーク構成の肝となるのは、フレッツ収容ルータ・網終端装置が連携して PPP セッションを確立する機能です。今回は accel-ppp の利用を検討しました。

accel-ppp

PPP, PPPoE, L2TP を実装した OSS はいくつかありますが、 accel-ppp は下記の点で優れていると判断しました。

  • PPP(PPPoE, L2TP , RADIUS) に関するサーバ・クライアントの機能を標準で多数有している
  • 各機能がモジューラブルに設計されており、今回のような PPP 機能をカスタムするケースに有利と判断
  • ルータ OS として人気がある VyOS で採用されている

参考にした資料

サーバを中継して PPP セッションを確立するためのフロー

Cisco が公開しているページを参考にしました。 こちらには L2TP セッションを利用して PPP ネゴシエーションを引き継ぐための通信フローが掲載されており大変参考になりました。

accel-ppp が提供する機能

公式サイトのドキュメント Github 上のソースコードを参考にしました。

比較結果

双方の資料を比較した結果、accel-ppp は PPPoE 、L2TP といったプロトコルのサーバ・クライアントを独立した機能として提供することは可能ですが、それらの各機能を連携させて動作させる仕組みを有していないことがわかりました。

不足している機能を示した図。上記で既に述べた「連携させる仕組みが有していない」ことを強調するための図です。
不足している機能

今回の検証を実現するために不足している機能を下記に列挙します。

  • PPP ネゴシエーションの過程で L2TP セッションを生成する機能(L2TP セッションの生成は CLI/Telnet からのコマンド実行でのみ可能)
  • ユーザ名をキーにして L2TP サーバを選択する機能
  • PPPoE セッションと L2TP セッションで生成されたネットワークインタフェース(例: /dev/ppp0 , /dev/l2tp0)間の通信を中継する機能
  • PPPoE セッションの生成過程でクライアントから取得したネゴシエーション情報( LCP、ユーザ情報 )を L2TP セッション側に渡す機能

accel-ppp のソースコードを改修して機能を追加する

フレッツ収容ルータ・網終端装置間の通信を実現するため以下の機能を accel-ppp に追加します。

追加機能の一覧

機能名 処理内容
LT2P セッション動的生成機能 宅内ルータからユーザ情報を受け取ったタイミングで、そのユーザ名から接続先となる網終端装置を決定、その網終端装置との間に L2TP セッションを生成する
PPP セッション間通信中継機能 PPPoE セッションと L2TP セッションの通信を中継する
PPP ネゴシエーション情報中継機能 宅内ルータから受信したネゴシエーション情報を網終端装置側に転送する

各機能の詳細

L2TP セッション動的生成機能

ユーザ名を利用して網終端装置を決定して、その網終端装置との間に L2TP セッションを生成するため、宅内ルータ側からユーザ名を届く Chap Response のタイミングで以下の処理を追加します。

  1. ユーザ名の @ 後ろの文字列を振り分けサーバに送信して接続先(網終端装置の IP アドレス)を取得
  2. 接続先に対して L2TP セッションの生成を開始する

L2TP セッション動的生成機能の図。上記で既に述べた処理によって、どのような変化が起きるのかを示した図です。
L2TP セッション動的生成機能

この機能を実装するときに accel-ppp のモジューラブルな構成が役立ちます。accel-ppp ではユーザ情報取得後の認証処理をハンドラとして組み替えることが可能です。この仕組みを利用してローカルファイルを参照する方法と RADIUS に問い合わせる方法を設定ファイルで選択可能にしています。今回はハンドラとして上記の機能を追加することで、独立性を高め疎結合を保ちます。

PPP セッション間通信中継機能

宅内ルータとフレッツ収容ルータ間で確立した PPPoE セッションと L2TP セッションを紐づけて双方の通信を中継する仕組みが必要です。 それぞれのセッションが確立したタイミングでネットワークインタフェース(例: /dev/ppp0 , /dev/l2tp0)が OS 上に生成されるため、L2TP セッションが生成されたタイミングでこの2つのネットワークインタフェースの通信を中継させるプロセスを動的に生成する機能を設けます。

PPP セッション間通信中継機能の図。上記で既に述べた処理によって、どのような変化が起きるのかを示した図です。
PPP セッション間通信中継機能

PPP ネゴシエーション情報中継機能

標準の機能で PPPoE セッションと L2TP のセッションを生成した場合、独立した2つの PPP セッションが生成されるだけとなります。この独立した2つのセッションを宅内ルータと網終端装置を両端とした1つの仮想的な PPP セッションとして扱うため、PPPoE セッション生成時に受け取ったネゴシエーション情報を網終端装置に渡します。 渡した情報をもとに網終端装置がネゴシエーションを引き継ぐことで仮想的な1つの PPP セッションが生成されます。

PPP ネゴシエーション情報中継機能の図。上記で既に述べた処理によって、どのような変化が起きるのかを示した図です
PPP ネゴシエーション情報中継機能

各機能の実行タイミング

上記機能の実行タイミングを整理します。

機能名 実行タイミング
L2TP セッション動的生成機能 宅内ルータから CHAP Response を受信した後
PPP セッション間通信中継機能 L2TP セッション確立時(ユーザ認証に失敗した場合は即削除)
PPP ネゴシエーション情報中継機能 網終端装置に PPP ネゴシエーション情報を渡す時

以下のフローは、Cisco のページにある通信フローをベースに今回発生する通信を付け加えたものです。

  sequenceDiagram
      participant HR as 宅内ルータ<br>(home)
      participant SR as フレッツ収容<br>(sse)
      participant DS as 振り分けサーバ<br>(dispatch)
      participant N as 網終端装置<br>(nte)
      participant RA as RADIUS<br>(isp-radius)
      HR->>SR: PADI
      SR->>HR: PADO
      HR->>SR: PADR
      SR->>HR: PADS
      Note over HR,SR: PPPoE ネゴシエーション完了
      HR->>SR: LCP Configuration-Request
      SR->>HR: LCP Configuration-Ack
      SR->>HR: LCP Configuration-Request
      HR->>SR: LCP Configuration-Ack
      Note over HR,SR: LCP ネゴシエーション完了
      SR->>HR: CHAP challenge
      HR->>SR: CHAP challenge Response
      Note over HR,SR: CHAP(ユーザ情報受信まで)
      rect rgb(191, 223, 255)
      Note over SR: 実行:LT2P セッション動的生成機能<br>(接続先の取得・L2TP セッション生成を依頼)
      SR->>DS: Access-Request
      DS->>SR: Access-Response 
      Note over SR,DS : RADIUS(接続先の取得)
      SR->>N: SCCRQ
      N->>SR: SCCRP
      SR->>N: SCCCN
      N->>SR: ZLB
      Note over SR,N: L2TP ネゴシエーション(トンネル)
      SR->>N: ICRQ
      N->>SR: ICRP
      SR->>N: ICCN
      N->>SR: ZLB
      Note over SR,N: L2TP ネゴシエーション(セッション)
      end

      rect rgb(168, 168, 255)
      Note over SR: PPP セッション間通信中継機能<br>(宅内ルータからのユーザ情報を転送)
      end

      N->>SR: LCP Configuration-Request
      SR->>N: LCP Configuration-Ack

      rect rgb(153, 255, 153)
      Note over SR : 実行:PPP ネゴシエーション情報中継機能<br>(宅内ルータからの LCP 情報を転送)
      SR->>N: LCP Configuration-Request
      N->>SR: LCP Configuration-Ack
      Note over N,SR: LCP ネゴシエーション完了
      N->>SR: CHAP challenge
      SR->>N: CHAP challenge Response
      Note over SR,N: CHAP(ユーザ情報転送)
      end

      N->>RA: Access-Request
      RA->>N: Access-Response
      Note over N,RA: RADIUS(ユーザ認証)

      rect rgb(168, 168, 255)
      Note over HR,N: PPP セッション間通信中継機能実行後<br>仮想的な PPP セッションとして宅内ルータ - 網終端装置 で通信
      N->>HR: CHAP success/failure 
      Note over N, HR: CHAP(認証結果の送信)
      Note over HR,N: IPCP Complete( IPv4 アドレスの取得)
      Note over HR,N: 仮想的な PPP セッションを利用したデータ通信
      end

おわりに

疑似フレッツ光網の通信を OSS で再現するために検討したことをここまで書きました。上記の検討により実装方針の大枠が定まりましたので、後は実装を進めていくだけとなります。

登 大遊さんの資料を初めて読んだときは OSS の標準的な機能で実現できるだろうと軽い気持ちで考え、netns の環境構築から着手しましたが、検討を進めていく過程で機能追加が必要なことを知り、当初の想定を超える作業が必要であることがわかりました。

普段の業務ではあまり馴染みの無いプロトコルを調査した今回の経験は、今後の業務において良いアイディアを生むきっかけとなりそうです。 せっかくここまで準備したので、機能実装とテストを実施して、その内容をまとめた記事を「実装編」として書きたいと思います(3ヶ月以内ぐらいを目標に)。