TT Lab
はじめる
学ぶ 学習パス コース

アドレス・サブネット・ゲートウェイ

アドレスを計算する道具を作る

TT Labで続きを見る

目標

アドレスとマスクを受け取って、ネットワークアドレス・ブロードキャスト・使える範囲・ホスト数を計算するツールをPythonで作り、そのツールで、同じサブネットかどうかの判定、アドレス範囲の分類、重なりの検査を行います。最後に、要求されたホスト数に合うプレフィックスを選んで、設計メモを残します。

なぜ重要なのか

ファイアウォールのルールも、ネットワークポリシーも、VPCの設計も、すべてこの計算の上に成り立っています。ところが、手で繰り返すと、いつか必ず間違え、間違いはたいてい障害が起きたあとで表に出ます。そのため、1回作っておいて使い続けるほうがよいのです。

特に/31と/32が重要です。ホスト数を「全体から2を引く」とだけ書いておくと、この2つで0と-1が出ますが、ツールは何のエラーも出さず、その値をそのまま返します。チェッカーが見つけてくれない種類のウソなので、例外を知っている人だけが避けられます。

ステップ

  1. 3つのアドレス範囲を手で計算し、/root/cidr/01-hand.txtファイルに1行ずつ書いてください。アドレス範囲は192.168.40.130/26、10.10.6.75/20、172.20.200.9/23で、各行にCIDR・ネットワークアドレス・ブロードキャスト・最初のホスト・最後のホスト・ホスト数がすべて入っている必要があります。
  2. /root/cidr/subnet.pyファイルを作成してください。python3 subnet.py 203.0.113.77/28とpython3 subnet.py 203.0.113.77 255.255.255.240が同じ答えを出す必要があり、出力はprefix= network= broadcast= first= last= hosts=の6行です。2回実行した結果を、/root/cidr/02-tool.txtファイルに保存してください。
  3. ツールが/31と/32を正しく扱うように直してください。この2つはbroadcast=noneで、/31は2つのアドレスがどちらもホスト(hosts=2)、/32は自分自身1つ(hosts=1)です。10.0.0.5/31と10.0.0.5/32を実行した結果と、なぜそうなるのかを、/root/cidr/03-edge.txtファイルに書いてください。
  4. /root/cidr/same.pyファイルを作成してください。python3 same.py <주소/프리픽스> <상대주소>(プレースホルダーはアドレス/プレフィックスと相手のアドレスです)が、sameまたはdifferentの一語だけを出力します。5組を実行し、/root/cidr/04-same.txtファイルに주소/프리픽스 상대주소 판정(プレースホルダーはアドレス/プレフィックス、相手のアドレス、判定です)として保存してください。
  5. /root/cidr/classify.pyファイルを作成してください。python3 classify.py <주소>(プレースホルダーはアドレスです)が、private link-local loopback cgnat multicast publicのうち1つを出力します。9個のアドレスを実行し、/root/cidr/05-class.txtファイルに주소 분류(プレースホルダーはアドレスと分類です)として保存してください。
  6. 10.60.8.0/22を/24の4つに分割し、/root/cidr/06-split.txtファイルに1行に1つずつ、네트워크/24 first= last= hosts=(プレースホルダーはネットワークです)の形式で書いてください。
  7. 既存の4つのアドレス範囲と重なるかを判定し、/root/cidr/07-overlap.txtファイルに書いてください。重なるなら후보 overlap=겹치는대역、重ならないなら후보 freeです(プレースホルダーは、候補と、重なっているアドレス範囲です)。
  8. /root/cidr/08-report.mdファイルに、設計メモを書いてください。要求ホスト数3つ(120台・600台・30台)に合う最小のプレフィックス、アドレス範囲を連続して配置すると何が得なのか、/31と/32をいつ使うかが入っている必要があります。

参考

3つのアドレス範囲を手で計算する

プレフィックスが8の倍数でないときが、ミスの出る場所です。ブロックサイズ(2のホストビット乗)を求め、その倍数のうちアドレスが入るものを見つければ、それがネットワークアドレスです。

例えば/26はブロックサイズが64なので、境界は0、64、128、192です。130は128のブロックに入ります。

検算はpython3 -c "import ipaddress; n=ipaddress.ip_network('192.168.40.130/26', strict=False); print(n.network_address, n.broadcast_address, n.num_addresses-2)"で行います。

計算ツールを作る

/26と255.255.255.192は同じ意味です。引数が2つで来たら、주소/마스크(プレースホルダーはアドレスとマスクです)の形でつないで、同じ関数に渡せばよいです。

ipaddress.ip_network("203.0.113.77 255.255.255.240".replace(' ', '/'), strict=False)のようにです。

出力のキー名(prefix= network= broadcast= first= last= hosts=)は、採点ツールがそのまま探すので、変えないでください。ホスト数は、全アドレス数から、ネットワークアドレスとブロードキャストアドレスの2つを引いた値です。

/31と/32の例外を扱う

num_addresses - 2は、/31では0、/32では-1になります。ツールはエラーを出さずにその値をそのまま返すので、例外を知っている人だけが避けられます。

プレフィックスが31以上なら、別の分岐に送ってください。その分岐では、ブロードキャストアドレスを置かず(broadcast=none)、最初のホストはネットワークアドレスそのまま、最後のホストはアドレス範囲の最後のアドレス、ホスト数は全アドレス数です。

説明ファイルには、どのRFCが、どんなリンクに限ってこれを許可したかを書いてください。

同じサブネットかを判定する

判定は1行で終わります。相手のアドレスが自分の範囲の中にあるか。ipaddress.ip_address(other) in ipaddress.ip_network(mine, strict=False)です。

最初の2組は、アドレスが同じで、マスクだけが違います。マスクを1つ間違えると、隣の席のコンピューターが地球の反対側になることが、ここでわかります。

出力は、sameまたはdifferentの一語でなければなりません。採点ツールが、指示文にない組でも、もう一度聞いてきます。

アドレス範囲の性格を分類する

ルールの一覧を作って、上から合うものを探し、どこにも当てはまらなければpublicです。

必要な範囲は次のとおりです。ループバック127.0.0.0/8、リンクローカル169.254.0.0/16、CGNAT100.64.0.0/10、マルチキャスト224.0.0.0/4、プライベート10.0.0.0/8・172.16.0.0/12・192.168.0.0/16。

172.32.0.1と100.100.5.5が落とし穴です。172のプライベート範囲は/12なので172.16から172.31までで、100.64.0.0/10は通信事業者が加入者に割り当てるアドレスなので、プライベートでもグローバルでもありません。

アドレス範囲を細かく分ける

/22を/24で切ると、2の(24-22)乗、つまり4つになります。ipaddress.ip_network("10.60.8.0/22").subnets(new_prefix=24)が、その4つを順に返します。

各行に、ネットワーク(プレフィックス込み)・最初のホスト・最後のホスト・ホスト数を入れてください。分割したアドレス範囲ごとに、ホストは254個です。

アドレス範囲が重なるかを見る

重なりは目で見ると必ず間違えます。ipaddressのoverlaps()が、2つの範囲が1つでもアドレスを共有しているかを教えてくれます。

172.17.0.0/16が一覧にあるのには理由があります。Dockerの標準ブリッジがその範囲なので、社内ネットワークが172.17を使っていると、コンテナから社内サーバーに行けません。

重なるなら후보 overlap=겹치는대역、重ならないなら후보 freeと書いてください(プレースホルダーは、候補と、重なっているアドレス範囲です)。

設計メモを残す

必要なホスト数に2を足した値が入る、最も小さい2の累乗を探せばよいです。120台なら122以上が必要なので128、つまりホストビット7個で、プレフィックスは/25です。

連続配置の話は、隣接するアドレス範囲を1つにまとめてアドバタイズできるということです。それが、クラスが消えた実質的な理由でもあります。

クラウドでは、予約アドレスをさらに引く必要があることも、一緒に書いておくとよいです。