NAT ゲートウェイのラボ:nftables でマスカレードとポート転送をブラウザーで学ぶ

アドレス変換(NAT)を学ぶネットワークラボです。生徒の Ubuntu VM 1台の中に3台のマシンを作ります。10.0.0.0/24 のプライベートなホスト、ゲートウェイ、203.0.113.0/24 の外側のサーバーです。外側にはプライベートアドレスへ戻る経路がないので、ホストはサーバーに届きません。生徒はその理由を調べ、ゲートウェイで nftables を使って直さなければなりません。

インストールするものも、買うルーターもありません。マシンはどれもネットワーク名前空間で、本物のコマンドがそのまま使えます。外側のサーバーはどのリクエストにも、それが来たアドレスを返すので、生徒はアドレス変換が何をするかを自分の目で確かめられます。

生徒が学ぶこと

プライベートアドレスがインターネットでは使えない理由と、ゲートウェイが背後のマシンの代わりにどう振る舞うか。出ていくものの送信元アドレスを書き換えるマスカレードと、入ってくるものの宛先を書き換えて、外側からプライベートなホストの1つのサービスに届くようにするポート転送です。conntrack でゲートウェイの接続テーブルを読み、tcpdump でリンクを観察し、ほかをすべて破棄するファイアウォールを広げすぎずに転送された通信だけ通し、再起動しても残るようにルールを保存します。

トポロジーと課題

ポート80で Web ページ、ポート8081で非公開のページを出す LAN のホスト、両側に1本ずつケーブルがあるゲートウェイ、ポート8000の外側のサーバーです。いまのゲートウェイは、LAN から始まる接続を通し、ほかは破棄します。生徒は、LAN のホストがゲートウェイの外側のアドレスとして外側のサーバーに届くようにし、次に LAN の Web ページを外側からポート8080で届くようにします。それ以外は開けません。アドレスは、ラボがホームフォルダーに置く README にあります。README にはやることが書かれていて、答えは書かれていません。

ブラウザーで動かす

VM ラボはモジュールにラボ課題として追加し、サンプルはラボのページにあります。

  1. ラボを追加する. 自分が教えるモジュールで課題を追加し、「Ubuntu VM ラボ」のカードを選びます。ページにはcompose ファイルの代わりにマシンの短い記述が表示されます。
  2. サンプルから始める. ページには、そこから始められるサンプルが用意されています。NAT gateway: masquerade and port forwarding を選びます。サンプルを使うとテキストが置き換わりますが、「元に戻す」で自分のテキストに戻せます。
  3. 公開して自分のコピーを起動する. 「公開」してから「起動」を押します。VM の初回起動時に、ラボ自身の setup スクリプトが Ubuntu のアーカイブから nftables といくつかのネットワークツールをインストールし、3台のマシンを作ります。所要時間は約10秒です。
  4. ターミナルを開く. ターミナルを開き、ホームフォルダーの README.md を読みます。やることが書かれていて、答えは書かれていません。netlab status でマシンの一覧、netlab shell gw でゲートウェイのシェルを開けます。

このラボの基本レッスン

NAT Basics は、このラボで進める小さなレッスンです。このラボは Ubuntu VM で、各手順に説明と、マシンのターミナルにコマンドを入力して出力を表示する「実行」ボタンが付いています。生徒はマシンを確認し、外側のサーバーにページを要求してタイムアウトするのを見て、外側のサーバーの経路にプライベートアドレス宛てのものがないことを確かめ、ゲートウェイのルールにアドレスを変換するものがないことを読み取ります。

生徒は見て回るだけで、動かすというラボ本来の課題は生徒に任せるので、レッスンは答えを教えません。無料の個人アカウントには、ホームにある Basics モジュールで配布されます。どの学校もライブラリの Basics フォルダから自分のモジュールにコピーでき、新しい学校ではサンプルモジュールの Networking Basics (Sample) に入っています。意図的に小さくしてあり、ラボで進めるレッスンとは何かを教員に見せるためのもので、残りはラボが担います。変更したい場合は、自分のモジュールにコピーしてください。

採点の仕組み

ラボにはチェックがあります。新しく起動し直した、保存されたマシンのコピーで実行されるため、生徒が /etc/nftables.conf に保存した内容だけが見えます。採点するのはルールの書き方ではなく、ネットワークの実際の動きです。LAN のホストからのリクエストが外側のサーバーに届き、サーバーがゲートウェイの外側のアドレスを見ていること。外側からポート8080へのリクエストがLAN のページに届き、ページがクライアント自身のアドレスを見ていること(ゲートウェイ上のプロキシでは合格しません)。非公開のページとほかのポートは閉じたままで、ゲートウェイは許可されていないものを引き続き破棄していること。動いているゲートウェイに入力しただけで保存していないルールは合格にならず、チェックの出力の1行目にその理由が出ます。

  1. 配布する. ほかの課題と同じようにラボを配布します。期限を付けることもできます。各生徒には専用の VM が渡され、セッションをまたいで保持されます。
  2. チェックを実行する. クラス一覧の生徒の行で「チェックを実行」を押します。保存されたマシンのコピーが(元には保存されない形で)起動し、ラボのチェックスクリプトが root で実行されて、合格したか、何を出力したか、いつかが表示されます。結果は生徒には知らされません。
  3. 採点する. チェックの出力を読みます。生徒が VM を停止すると、クラス一覧にインストールしたパッケージや書いたファイルなどの変更内容も表示されるので、VM を起動せずに採点できます。足りない場合は理由を書いて差し戻します。

GitHub の定義ファイル

このファイルがラボの定義のすべてで、プラットフォームが実行するのと同じテキストです。サイズ、setup スクリプト、トポロジー、README、チェックが入っています。必要なのは CPU 1つと 1 GB です。コピーして書き換えれば自分のラボになります。

よくある質問

外側は本物のインターネットですか?
いいえ。外側は生徒の VM の中のネットワーク名前空間で、ドキュメント用に確保された範囲の 203.0.113.0/24 を使います。VM 自体が届くのは Ubuntu のパッケージアーカイブ、PyPI、npm、GitHub だけなので、ラボをインターネット上のホストに向けることはできません。
生徒は本物の Linux コマンドを使えますか?
はい。それが狙いです。sudo ip netns exec gw nft list ruleset や sudo ip netns exec gw conntrack -L はそのまま使え、netlab shell gw は近道です。
マスカレードとポートフォワードの違いは何ですか?
マスカレードはプライベートネットワークから出ていくものの送信元アドレスを書き換えるので、LAN のホストが外のサーバーに届きます。ポートフォワードは入ってくるものの宛先を書き換えるので、外からプライベートホストの1つのサービスに届きます。このラボは両方を求め、フォワードはポート 8080 です。