惰性で学ぶIPv4

惰性で理解するIPネットワーキング(1)セグメント内通信

普段YouTubeやWEBを閲覧しているときにどうデータがやりとりされているか知っているかい?
「なんかめんどくさそうだな」と思うかもしれないけど、細切れにして理解していくと誰でもわかってしまうくらい簡単だよ。
“基礎”なんて言葉を使うと途端に”お勉強臭”が漂ってくるのでまずは惰性でこのシリーズを読んでみてくれ。

まずはやつの本名から暴露していく。YouTubeやWEBのデータを交換するしきたり、それを”インターネットプロトコル”という。略してIP。聞いたことあるよね。そのIPを使ってデータをやりとりできるようにしたものをIPネットワークと呼ぶ。TMネットワークとは関係ない(はず)。

以後IP、IPと連呼していくぞ。ところでオレはエイ。海底で暮らしている。餌はアレ

IPパケットを送信するまで

さて以下のような単純な構成があったとする。左側のPC1(以降端末と呼ぶ)からなんらかのデータ(WEBでもE-mailでもなんでもよい)を右側の端末PC2にIPをつかって送信する際の出来事を見ていこう。

ちなみに"Switch"と書いてある箱はイーサネットスイッチ(L2スイッチ)と呼ばれるもので複数のPCをネットワークに収容する機器だよ。どこかで見たことあるでしょ? ちなみにスプラトゥーンとかできるやつじゃないから注意して。L2スイッチは(いまのところ)PC1とPC2を接続するための電線と思っていい。

まずはルータが存在しない状況下でのIP通信をみていくぞ

IPパケットの生成(レイヤ3・ネットワーク層)

さてPC1からPC2にデータを送る、という想定だけど最初にデータを送ろうとするのは普通は人間様だ。人間様がその高尚な思想に基づいてGoogle先生とかに「ティアキン 攻略」とか聞きに行くよね。そのときブラウザを使うでしょ? そう最初にPC上でデータを作るのはブラウザとかのアプリケーション。アプリケーションがデータを作り、それをIPスタックというOSの機能をつかって送信する。

アプリケーションからデータを渡されたIPスタックはデータをIPパケットという箱にいれちゃう。箱にはちゃんと伝票(IPヘッダ)が貼ってあって、送信元と送信先のアドレスが書いてある。これがかの有名なIPアドレスというやつだ。

IPネットワークとかいう魔物はこのIPパケットをIPアドレスに基づいて右往左往させる不思議な存在というわけだ。まあ最後には何も不思議じゃ無くなるから心配は要らない。

この「データをアプリケーションからもらってIPパケットに押し込んだり、逆にIPパケットを開梱してデータをアプリケーションに渡す」というお仕事をしてる連中をレイヤ3とかL3とかネットワーク層とかいう。(実際にはアプリケーションとレイヤ3の間にはレイヤ4という層が挟まっているが、かえってわかりづらくなるので今はおいておこう)

IPヘッダには送信元、宛先IPアドレスのほかに上位層(レイヤ4)との連携に関する情報やQoS処理に必要な情報が書いてあるぞ。あ、意味不明な独り言を言ってしまった。。聞き流してくれ

Ethernetフレームの生成(レイヤ2・データリンク層)

IPパケットがわかったのでもう帰り支度をしているとは思うがちょっと待ってほしい。実はIPパケットは自力で移動できない。誰かに運んで貰わないと配達できない。

移動させる手段はいろいろあって、たとえば一般的なのはEthernet(有線LANのこと)と無線LAN。どちらでも好きな方を選べる。

Ethernetを使ってIPパケットを送信したい場合には、そのパケットをIEEE 802.3という規格に基づいたフレームに入れれば良いし、無線LANをつかって送信したいのであればIEEE 802.11という規格を使えば良い。(ネットワーク層でのデータがパケットと呼ばれるのに対し、データリンク層からみたときのデータはフレームと呼ばれる)

重要なのはIPパケットをつくるところまで共通の処理で良いというところ。これがレイヤ3とレイヤ2が別であることのメリット。今回の説明では簡単なEthernetを使ったケースを前提にしていこう。

Ethernetフレームにもヘッダ(MACヘッダ)があり、Ethernetフレーム用のアドレスが記述される。それがMACアドレス。
MACアドレスは6バイト(48ビット)からなり、00:11:22:33:44:55あるいは00-11-22-33-44-55のように表記される。

以下はそのイメージ図。前述のレイヤ3で生成したIPパケットをそのまますっぽりEthernetフレームの箱に入れてしまうと思って良い。

レイヤ2で動作するデバイスはIPパケットは見えない。宛先として確認できるのはMACアドレスだけだ

なのでレイヤ2スイッチはMACアドレスだけを見てフレームの処理を行うよ 。あ、わたしはエンゼル。金なら一枚

Ethernetフレームの送信(レイヤ1・物理層)

こうしてユーザのデータはIPパケットに格納されて、さらにそれがEthernetフレームに格納される。
最終的なフレームフォーマットを示したものが以下の図だ。フレームの最後にはFCSとよばれるチェックサムが付加される。



このフレームを物理的な信号に変換してケーブル等に送出・受信するのがネットワークインターフェイスカード(NIC)の役目だ。これをやる層をレイヤ1とか物理層とかいう。受信側端末のNICではフレームの宛先MACアドレスが自分のものであれば受信し、そうでなければ無視する。そう考えるとNICはレイヤ2にも関与している(だってMACアドレスをもっているぢゃないか)ことになるのだけど、一般論としてNICはレイヤ1で働いている、という。

物理層の選択肢はイーサネットケーブルや光ファイバー、無線などいろいろあるぞ

最近のノートパソコンは無線しかついてないですよね

MACアドレスとは

MACアドレスはいつ誰が設定した?

ところで前述したMACアドレスについてだけど、いつ誰が設定したか知ってる?
IPアドレスの設定はDHCPや手動で設定を行うのを知っている人もいると思う。けどMACアドレスを設定したことがある人はあまりいないと思う。実はMACアドレスはNICが製造されたときにすでにハードウェアに登録されているのでユーザがあらためて設定する必要は無い。

WIFIのUSBドングルやネットに繋がるガジェットに00-11-22-AA-BB-CCのような12桁の記述が書かれているのを見たことはないだろうか? それがその装置のMACアドレスである可能性が高い。

最近のOSではプライバシーの観点から無線LAN用のMACアドレスをランダムに生成するぞ

各OSでのMACアドレスの表示

通常ユーザが端末のMACアドレスを意識する必要は無いが、トラブルシューティングや検証時には重要な情報になる。各OSでのMACアドレス確認方法を記しておく。

各OSでのMACアドレスの表示

> ifconfig en0
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
	options=40b<RXCSUM,TXCSUM,VLAN_HWTAGGING,CHANNEL_IO>
	ether f0:18:98:ec:84:aa
	inet6 fe80::8d3:b5a9:5fc0:1234%en0 prefixlen 64 secured scopeid 0x4
	inet 172.30.80.90 netmask 0xffff0000 broadcast 172.30.255.255
	nd6 options=201<PERFORMNUD,DAD>
	media: autoselect (1000baseT <full-duplex,flow-control,energy-efficient-ethernet>)
	status: active
  • 4行目のether f0:18:98:ec:84:aaがMACアドレス

ubuntu

$ ip address show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether d8:3a:dd:1d:af:aa brd ff:ff:ff:ff:ff:ff
    inet 172.30.98.1/16 brd 172.30.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::da3a:ddff:fe1d:afaa/64 scope link
       valid_lft forever preferred_lft forever
  • 3行目のd8:3a:dd:1d:af:aaがMACアドレス

Windows11

> ipconfig /all
--- 抜粋 ---
イーサネット アダプター External:

   メディアの状態. . . . . . . . . . . .: メディアは接続されていません
   接続固有の DNS サフィックス . . . . .: underwaternotes.net
   説明. . . . . . . . . . . . . . . . .: Realtek PCIe GbE Family Controller
   物理アドレス. . . . . . . . . . . . .: 00-50-43-01-B2-C0
  • 8行目の物理アドレス 00-50-43-01-B2-C0がMACアドレス

どうやって相手のMACアドレスを知る?

MACアドレスはあらかじめハードウェアに設定されているのは良いとして、相手のMACアドレスをどうやって知るのか? 不思議じゃない?


そもそも宛先MACアドレスなんて指定したことある? 人間が宛先としてアプリケーションに与える情報は多くの場合IPアドレス。たとえばwww.underwaternotes.netというのも間接的にはIPアドレス。でもIPアドレスはレイヤ3のアドレスで、レイヤ2のアドレスであるMACアドレスを指定することは無いよね。

実は宛先IPアドレスに対応するMACアドレスを問い合わせる仕組みがある。それがAddress Resolution Protocol (ARP)。

Address Resolution Protocol (ARP)

宛先IPアドレスがわかっているのだけど、そのIPアドレスに到達するMACアドレスがわからないときに端末が使うのがARPというプロトコル。ARP Requestを受け取った端末は自分のMACアドレスを送り返す仕組みになっている。

さてARPは相手のMACアドレスがわからないのに、どうやってその端末にARP Requestを送りつけることができるのか? 端末にEthernetで通信する場合、Ethernetフレームに宛先MACアドレスを指定する必要があるよね? でもそれがわからないんだから。ニワトリとタマゴ。

実はEthernetには”全員宛”という便利なアドレスがある。それがBroadcastアドレス。具体的にはアドレス FF:FF:FF:FF:FF:FFがBroadcastアドレス。このアドレスは”全員”が受け取ることになっているので、誰が目的の端末なのかわからなくてもメッセージを届けることができる。ARPはこのBroadcastアドレスを利用する。

ちなみにBroadcast通信に対してちゃんと個別の端末のMACアドレスを指定する通信をUnicast通信というよ。

Unicast通信とBroadcast通信

Broadcastフレームの波及範囲

”全員宛”といっても、世の中すべての端末に届くわけでは無い。Broadcast通信が届く範囲がある。それをBroadcastドメインというよ。
Broadcast通信が到達する範囲は超簡単に言うとルータまで。ルータはBroadcastフレームを受信はするけど、それを他のポートに転送はしないんだ。(前述したようにスイッチはBroadcastフレームを全ポートに送信するよ)。

ルータで仕切られた範囲のことをセグメントという言い方で呼ぶこともある。セグメントという言葉はいろんな意味があるけど、こういうケースで出てきた場合、それはL2セグメントのことを意味していて、要はEthernetフレームを直接伝達できる範囲のことをいう。そしてこのL2セグメントとBroadcastドメインはイコールになる。

例えば以下の図でPC1からBroadcastフレームが送出されたとすると、その波及範囲はPC2,PC3,Routerまでとなる。この範囲が(左側の)L2セグメントであり、同時にブロードキャストドメイン。Routerにはもう一つポートがついているので右側にも別のL2セグメントがあるけど、左側のセグメントから右側のセグメントの端末へBroadcastフレームを送ることはできない。

ま、今回の前提はルータが存在しない構成だから、このBroadcastドメインの話は一旦忘れてOK。詳しくは次回で説明するよ。

ARPが実現すること

話をARPに戻そう。同一セグメント上のすべての端末がこのパケットを受信するが、ARPパケットの中に記述されているTraget Addressと自分のIPアドレスが一致した場合にのみ返答を返す。そうすることにより送信元の端末は送信先IPアドレスに対応するMACアドレスを知ることができる、というカラクリ。

たとえば病院の待合室等、顔と名前が一致しない状況で特定の人を呼び出したい場合どうする? 大きな声で「○○さん、いらっしゃいますかー?」というよね。この問いは全員に聞こえるように言わないと意味が無い。ARPとはそういうこと。つまり「どなたかIPアドレス192.168.1.1の方いませんかー?」ということ。

ARPのパケットキャプチャー例

実機での通信をキャプチャーしてみたので確認しよう。まず構成はこれだ。

この構成で左のWindows11から右のUbuntuにpingを打ったパケットをキャプチャーしている。

以下に実際のARP RequestとARP Replyのパケットのキャプチャーを示そう。

最初の2発のパケットに注目してほしい。Frame No.1がWindows11がだしたARP Request。No.2がそれへの返信のARP Reply。
それぞれのパケットの詳細を以下に示す。

以下の点に留意してほしい。

  • Typeが0x0806であり、IPではない。ARPはIPスタックの一部だがプロトコルとしては"ARP"である。そのためIPヘッダは無い。つまりARPパケットには宛先IPアドレスは無い
  • Frame1(ARP Request)の宛先はBroadcast(FF:FF:FF:FF:FF:FF)。「おーい○○さーん!」がこれ
  • Frame2(ARP Reply)の宛先はUnicast。そりゃそうよ。返事は絶叫しなくてもいい
  • ARPパケットにはSenderとTargetのMACアドレスとIPアドレスが対で格納されている

RequestにはSenderのIPとMACアドレスが入っているため、受信側の端末は自分からARPをRequestしなくても相手のMACアドレスが入手できる。前述のパケットシーケンスで受信側がARP Requestを出していないのにpingが成立している(No.3-10)のはそのため。(ココ違和感持った人エライ。最初から正解を思いついてたらもっとエライ)

ただし、ARP Requestによって送信者のMACアドレスを得た場合は、そのStateがSTALEで始まるようだ。(この辺の細かい挙動はOSによって異なる)そのため、五秒後にARP RequestをUnicastで送信している。(No.11-12)
この動作に関しては次のセクションで説明するよ。

No.3-10はpingのパケット。これはIPプロトコルなのでIPアドレスが記述されている。当然IPの箱をEthernetフレームの箱に入れているのでMACアドレスも使用されていることに注意。

ARP Cache

毎回「ガラーッ!(ドアを開ける音) どなたかXXなかたいませんかー?」をやられてはうるさくてしょうがないよね。一瞬とはいえ、その部屋の中のすべての人々の会話が止まってしまうんだから。そのため端末はARPの結果をキャッシュし、次回以降はARPを使わずとも宛先MACアドレスを指定できるようにしている。このキャッシュはARP Tableとも呼ばれる。例として以下にLinux(Ubuntu)でのarp cacheの表示例を示すよ。

arp tableの表示 (Ubuntu)

$ ip nei
192.168.70.72 dev ens3  INCOMPLETE
192.168.70.4 dev ens3  FAILED
192.168.70.1 dev ens3 lladdr 00:0c:29:00:00:01 REACHABLE
192.168.70.2 dev ens3 lladdr 00:0c:29:00:00:02 STALE

Ubuntuではip neighでarp cacheが表示できる。(Windows, MacOSは"arp -a"で表示できる)

  • INCOMPLETE(2行目)とFAILED(3行目)はARPで問い合わせたが回答が得られなかったことを意味する。MACアドレスが入手できていないのでこの宛先へは通信できない
  • REACHABLE(4行目)とSTALE(5行目)はMACアドレスが入手できている。なのでこのIPアドレスにフレームを送ることができる

ARP Cacheの鮮度

ところでキャッシュというのはいつか腐る。鈴木さんは家庭の事情で早退したかもしれないし、昨日まで山田さんだった人が今日は吉田さんになっているかもしれない。なのでARPはキャッシュの鮮度を保つ機構を持っている。まあ話は簡単で、ARPで相手のMACアドレスをもらってからある程度時間が経ったら(15秒から45秒)それを“STALE”(古いという意味)という状態(State)にしちゃう。STALEの前のState、つまり新鮮なStateはREACHABLE。REACHABLE状態では普通にキャッシュされたMACアドレスを使える。じゃあSTALEのときはどうすると思う?

実は状態がSTALEのエントリーも普通に使える。何も問題ない。ただSTALEのエントリーを使ったら五秒後にまたARP RequestをエントリーのMACアドレスに向けて出す(前述のパケットキャプチャーのNo.11がそれ)。そこでReplyをもらえればまたStateがREACHABLEに戻る。なので正常なARP CacheエントリーのStateはREACHABLEとSTALEを繰り返す。Requestに応答が無い場合は最終的にFAILEDになる。

ARPがエントリーのStateをREACHABLEに戻すのはARP Replyを貰ったとき以外にもある。賢いことにARPは相手と会話中ならまだ相手は生きている、と考える。そりゃそうだよね。死んでたりいなくなってたら会話が止まっているはずだ。具体的にはエントリーのIPアドレスからTCP ACKと呼ばれるパケットをもらうと、ARPは「相手はまだ生きてるな」と推定し、エントリーのStateをREACHABLEに戻す。

わざわざARP Requestを発行する必要がないのでこの方がネットワーク的に無駄が無い。STALEからARP Requestを出すのに五秒待つのはそのため。この間にTCP ACKをもらうことを期待している。(しかし上記の検証のようにICMPだけで通信している場合は周期的にARP Requestを発行することになる。ICMPは“会話”とは見なされない)

TCPというのはまた今度説明するけど、今はIP通信のモードみたいなものと思っておけばOK

まとめ

この章で説明したことをまとめるよ。

説明したこと
  • IP通信用のデータ(IPパケット)はレイヤ3(ネットワーク層)で生成される
  • それを他の端末に送信する際にはレイヤ2(データリンク層)に渡して(さらにレイヤ1 物理層を経由して)外部に送信する
  • データリンク層のアドレスはIPアドレスではなく、MACアドレスを使う
  • Broadcastフレームは同一セグメント上の全端末が受信するが、ルータでブロックされる
  • 宛先MACアドレスは端末がARPをつかって自動的に入手するので人間が知っている必要は無い
  • ARPにはキャッシュがある

このトピックでは”同一セグメント内でのIP通信”を説明してきたんだ

つまりルータが介在しない状態でのIP通信ですね!
残された謎
  • Broadcastフレームがルータを超えられないのであれば、どうやってルータの先の端末と通信するのか?

この謎については以下の記事で説明するぞ!

惰性で理解するIPネットワーキング(2)セグメント間通信

IPネットワークの動作を誰にでもわかるサイズにほぐして説明していくシリーズ。
Episode2はセグメント間通信。ルータを経由するIP通信が理解できるようになります。
IP通信の基本中の基本が理解できます。

続きを見る


-惰性で学ぶIPv4
-