Wake on LAN の記事 (2014-06-02) で “ブロードキャスト通信” を少しばかりメモしましたが、もう少しコレを肌で感じておいても損はないような気がした今日この頃。
ではさっそくブロードキャスト通信の検証を行おう……と思いましたが、そもそもブロードキャスト通信を検証するに一番適したプロトコルってなんじゃい。 そう思って一番最初に思い浮かんだのが “
DHCP はわりと身近にあるプロトコルで、このブログでも何度かメモしてきましたが、よく考えたら Wireshark を使って DHCP のパケットを解析したことはありませんでした。 じゃぁこの機会を逃すわけにはイカン!! ――と無能なのに欲張りな僕は、DHCP とブロードキャスト通信の理解を一気にやってしまおうと思い、今回の記事を書くことにしました。
検証環境 今回の検証環境はとてもシンプル。
DHCP クライアントには Windows マシンを使い、DHCP サーバにはソフトウェアルータの “
Vyatta 6.6 ” を使いました。 当初は Linux に DHCP パッケージを導入して、それを DHCP サーバにする予定でしたが、
諸事情 により Vyatta を DHCP Server に採用しました。
↑図1:シンプルな検証環境。 けど vyatta の設定に苦戦した。。
検証環境のネットワークアドレスは 10.1.1.0/24 で、DHCP Server には 10.1.1.254 を設定し、DHCP Client には 「10.1.1.100 - 10.1.1.110」 までの10個の IP アドレスが自動で割り当てられる設定にしました。
以下、上記の内容を Vyatta に設定するコマンドです。
# set service dhcp-server { shared-network-name DHCP01 { subnet 10.1.1.0/24 { default-router 10.1.1.254 start 10.1.1.100 { stop 10.1.1.110 } } } }
では、上記のシンプルな検証環境から DHCP メッセージを理解していきます。
DHCP フォーマット その前に理解しておくべき “フォーマット” についてメモします。
DHCP は 「Discover → Offer → Request → ACK 」 といった処理を順に行ったのちに IP アドレスを DHCP クライアントに割り当てる仕組みであることは、過去の記事でも書いてきたと思います。 そんな DHCP の基本フォーマットは以下のような形になっています。
↑図2:DHCP の基本フォーマット
まず基本フォーマットで意識するべきフィールドは "
Your (Client) IP Address (yiaddr) " だと思います。 このフィールドに DHCP サーバがクライアントへ割り当てる IP アドレスが格納されるからです。
あと "Message Type" フィールドも知っておいて損はなさそうです。 DHCP メッセージには前述した 「Discover / Offer / Request / ACK」 があり、その他にもいくつかの種類がありますが、それらをざっくり分けると 「サーバの通信」 と 「クライアントの通信」 の2つに分けられます。 Message Type フィールドは、それらの判別に使われるようです。
Message Type: Boot Request (1) → DHCP クライアントの通信
Message Type: Boot Reply (2) → DHCP サーバの通信
ちなみに上記の Message Type は DHCP 基本フォーマットの先頭8ビットにあるもので、DHCP メッセージの詳細が記された "
Option " の "DHCP Message Type" とは違います。 これら Option の詳細に関しては、後ほどメモしていく予定です。
DHCP Discover ここでは DHCP クライアントが IP アドレスを取得するまでの流れをパケット解析レベルで追っていきます。 パケットを解析する順番は 「L2 - L4 ヘッダー」 → 「DHCP 基本フォーマット」 → 「DHCP Option」 の順です。
DHCP Discover メッセージは DHCP クライアントが 「DHCP サーバを探す動作」 を行うときに使われます。
IP アドレスを持ってないクライアントが DHCP サーバが稼働しているネットワークに接続すると、IP アドレスを持っていないためにクライアントは IP レベルの通信ができません。 そこでクライアントは IP アドレスをもらうために DHCP サーバを探す必要があります。
↑図3:DHCP Discover メッセージ
このときやり取りされる DHCP Discover メッセージに付加された、各種レイヤーのヘッダー情報は以下の通りです。
↑図4:DHCP Discover - L2 ~ L4 まで
Layer 2:
L2 では Source Address にクライアントの MAC アドレスが指定されますが、Destination Address には DHCP サーバの MAC アドレスが分からないため ff:ff:ff:ff:ff:ff のブロードキャストアドレスが指定されます。
Layer3:
L3 の Source Address にはクライアントの IP アドレスが無いため 0.0.0.0 が指定され、Destination Address には DHCP サーバの IP アドレスが分からないために 255.255.255.255 が指定されます。 このブロードキャストはネットワークセグメントに関係ない Limited Broadcast でしたね。
Layer4:
クライアントの通信には "68"、DHCP サーバの通信には "67" が使われます。 また DHCP パケットは基本的に UDP データグラムを使いますので、L3 の "Protocol" フィールドにも UDP (0x11) が書かれているのが分かります。
次に DHCP Discover の基本フォーマット情報は以下の通りです。
↑図5:DHCP Discover - 基本フォーマット
図5 を見ると IP アドレスが記されたフィールドに目が行きがちですが、その前にちょっと気になったのが "Bootp flags" でした。 DHCP Discover メッセージはブロードキャスト通信なのに、なぜ Bootp flags には "Unicast" が指定されているのかが分かりませんでした。
けれどもこのフラグは DHCP クライアントに IP アドレスが割り当てられる前に 「クライアントがユニキャストを受け取れるか否か」 を意味しているようです (RFC2131 参考)。 細かな動作までは分かりませんが、とりあえずはスルーしても問題なさそうですね。
それでは IP アドレスについて読んでいきます。
DHCP の基本フォーマットの中身は 図5 に描いた通りですが、重要なフィールドは以下の4つだと思います。
Client IP address
Your (Client) IP address
Next Server IP address
Relay agent IP address
Client IP address:
DHCP クライアントが IP アドレスを
既に所持しているとき に指定されます。いわゆるクライアントが [ ipconfig /renew ] などの動作を行って、DHCP サーバから IP アドレスを再取得するときなどですね。 クライアントが IP アドレスを所持していない場合は、このフィールドには 0.0.0.0 が指定されます。
Your (Client) IP address:
DHCP クライアントへ割り当てられる、または割り当てられた IP アドレスが格納されます。
Next Server IP address:
DHCP Server として動作しているサーバの IP アドレスが指定されます。
Relay agent IP address:
DHCP リレーエージェントのアドレスが指定されます。
さて、ここからが本題。
DHCP メッセージの Option について追究します。
Option は基本フォーマットとは違って可変長なので、DHCP メッセージの種類によって内容が異なるようです。 たとえば今回キャプチャした DHCP Discover メッセージの Option は以下のような感じ。
↑図6:DHCP Discover - Option フォーマット
ただ、ここで注意すべきなのが
OS による Option フォーマットの違いです 。
今回の検証ではDHCP クライアントに Windows 7 を使っていましたが、なんとなく気まぐれで Ubuntu 12.04 の DHCP Discover をキャプチャしたところ、なんと Option フォーマットが違っていました。 たとえば Windows 7 には存在した "Client identifier (61)" フィールドが Ubuntu 12.04 では存在しませんでした。
よって Option フォーマットに関しては Windows 7 をベースで理解し、特記すべき項目などがあれば Ubuntu 12.04 での情報も書いていこうと思います。
DHCP Message Type (53):
DHCP メッセージの種類を意味しています。 この Type には 「1~7」 までの段階があり、今回の DHCP Discover メッセージは1段階目、よって Value 01 が指定されます。
Client identifier (50):
DHCP クライアントの識別子のようです。 図6ではクライアントの MAC アドレスが指定されていますが、もしかすると任意の文字列などが扱えるかもしれませんね。
Host Name (12):
DHCP クライアントの PC 名が指定されます。
Vendor class identifier (60):
ベンダークラスの識別子のようです。 Ubuntu 12.04 ではこのフィールドは存在しませんでした。
Parameter Request List (55):
DHCP サーバに対して要求したいパラメータの一覧で、DHCP クライアントのみ使われる Option です。 一見すると要求しているパラメータが多いですが、よく見てみると "
Subnet Mask " や "
Domain Name " といった見慣れた項目であることが分かりますので、ここの詳細を追う必要はなさそうですね。 また、このパラメータリストの項目も Windows 7 と Ubuntu 12.04 では異なる個所があったので、忘れずメモしておきます。
以上のような情報が凝縮したパケットをブロードキャスト通信させて DHCP サーバへ送る。 この動作が DHCP Discover の役割であることが分かりました。
DHCP Offer DHCP Discover メッセージを受け取った DHCP サーバは "DHCP Offer" メッセージをクライアントへ投げ返します。 この投げ返した DHCP Offer メッセージは 「DHCP クライアントへ
仮 IP アドレス を渡す動作」 を行うときに使われるものです。
ってかどうして仮 IP アドレスなんぞ渡すのか、のっけから本番 IP アドレスを渡せばいいじゃん、と無知なワタクシは思うのですが、その疑問を追究していくうちに理解できていくのでしょうね。 そういった疑問を持っていた方が、追究が楽しくなるってもんですね。 とりあえず現時点では 「DHCP サーバの通知、仮 IP アドレスを渡す」 ためのメッセージだと認識しておきます。
↑図7:DHCP Offer メッセージ
また、このときやりとりされる DHCP Offer メッセージの L2 ~ L4 ヘッダー情報は以下の通りです。
↑図8:DHCP Offer - L2 ~ L4 まで
Layer 2:
DHCP Discover メッセージに対するレスポンスメッセージのため、アドレス情報は Source / Destination Address がそっくり入れ替わる形になります。 このときサーバはクライアントの MAC アドレスを把握していますので、Destination Address にはブロードキャストアドレスは入りません。
Layer 3:
ここで注目すべきところは Destination Address に
仮 IP アドレスが指定されている点 です。 この時点ではクライアントは IP アドレスを割り当てられていませんので、Destination Address に仮 IP アドレスが指定されていても、実際の通信は Layer2 で行われていることが分かります。
Lyaer 4:
今回は Source がサーバになりますので、Source Port には "67" が指定され、Destination Port には "68" が指定されます。 このあたりは DHCP Discover と正反対ですね。
次に DHCP Offer の基本フォーマットは以下の通りです。
↑図9:DHCP Offer - 基本フォーマット
DHCP Offer メッセージの基本フォーマットで特記すべき点は "Your (Client) IP address" フィールドが埋まったことです。
vyatta で指定したリース範囲は 10.1.1.100 - 10.1.1.110 の合計10個なので、その先頭アドレスとなる 10.1.1.100 がこの yiaddr に指定されました。 なるほど、リースされる IP アドレスはこういう指定のされ方なんですねぇ。
また一つ賢くなった気がする!! ……と思っても、まぁ仕事に役立つかといえば、激しく疑問なのですけど。 (´・ω・`)
というわけで、以下は Option フォーマットになります。
↑図10:DHCP Offer - Option フォーマット
DHCP Message Type (53):
DHCP Offer メッセージは 1~7 段階の2段階目に当てはまりますので Value 02 が指定されます。
DHCP Server Identifier (54):
DHCP サーバの IP アドレスが指定されました。
IP Address Lease Time (51):
IP アドレスのリース期間を指定します。 "1 day" とありますので IP アドレスのリース期間は1日となりますが、基本的に DHCP の IP アドレスは 「リース期間の半分」 に差し掛かると、クライアントは DHCP サーバに
リースの更新 を行ないます。 これに関しては後ほど追究していきます。
Subnet Mask (1):
リースされた仮 IP アドレスのサブネットマスクを意味します。 いやもしかするとネットワークセグメントのサブネットマスクかもしれませんが、そのあたりは追及しなくてもいいっすね。
Router (3):
セグメント内のルータの IP アドレスが指定されました。 今回は DHCP サーバがルータの役割を担っているため、DHCP サーバと同じ IP アドレスが指定されました。 同一セグメント内に DHCP サーバとルータが別々に存在するときは GW がルータになりますので、ここのフィールドにはルータのインターフェースアドレスが指定されます。
以上のようなメッセージを受け取ったクライアントは、基本フォーマットの yiaddr から仮 IP アドレスを認識します。 これが DHCP Offer であることが分かりました。
DHCP Request DHCP Request メッセージはクライアントがサーバに対し 「仮 IP アドレスを本番 IP アドレスとして貸し出してください」 と要求するときに行う動作です。 DHCP Discover / Offer が DHCP サーバを探し出す動作が主だとすれば、Request / ACK は IP アドレスを貰う動作が主だと言えるでしょうね。
↑図11:DHCP Request メッセージ
次に、おなじみの L2 ~ L4 までのヘッダー情報は以下の通りです。
↑図12:DHCP Request - L2 ~ L4 まで
Layer 2:
DHCP Discover メッセージと同じです。 DHCP Offer メッセージに DHCP サーバの MAC アドレスが格納されていましたので、Destination Address にはそれが指定されると思っていましたが、どうやらそうではないようです。 ということは、ここでもブロードキャスト通信を行っていることになりますね。
Layer 3:
同じく DHCP Discover メッセージと同じで、Destination Address には 255.255.255.255 の Limited Broadcast が指定されています。 また、Source Address には 0.0.0.0 が指定されていることから、DHCP Offer メッセージから得た仮 IP アドレスは、あくまで 「仮」 であることが見て取れますね。
Layer 4:
特になしだべよw
こうやって DHCP Request メッセージを覗いてみると、DHCP Discover メッセージ (図4) とヘッダー情報が
全く同じ であることが分かります。
では DHCP プロトコル内ではどうなっているのか、以下は基本フォーマットです。
↑図13:DHCP Request - 基本フォーマット
ここも同じく DHCP Discover と特に変わっていませんね。
では早々と Option フィールド内を覗いてみようと思います。
↑図14:DHCP Request - Option フォーマット
DHCP Discover の Option フォーマット (図6) と比べて、多少の差異があります。 それは "DHCP Message Type (53)" と "
Requested IP Address (50) " と "Client Fully Qualified Domain Name (81)" の3つです。 差異のあったこの3フィールドのみ、以下に詳細を記していきます。
DHCP Message Type (53):
DHCP Request は3段階目のため Value 03 が指定されます。
Requested IP Address (50):
クライアントが要求したい IP アドレスです。
このフィールドが DHCP の要 ですね。 DHCP Offer の yiaddr に指定された仮 IP をクライアントが使いたい場合にこの IP アドレスが指定されます。
Client Fully Qualified Domain Name (81):
Fully Qualified Domain Name、この名前から分かるようにクライアントの FQDN ですね。 図14では vm7 と表示されていますが、クライアント PC が Active Directory のドメインに属している場合は
genPC.genchan.com みたいな FQDN が Client name に指定されます。 ちなみに Ubuntu 12.04 ではこのフィールドは表示されませんでした。
やったら長い書き方をしましたが、要点だけ書くのなら 「リースを希望する IP アドレスは DHCP Request の Requested IP Address フィールドに格納される」 と言ったところでしょうか。 調べれば調べるほど、こういうプロトコルを考えた人は凄いと思う NE w (^ω^*)
DHCP ACK DHCP Request メッセージを受け取った DHCP サーバは、Requested IP Address フィールドで指定された IP アドレスを正規な IP アドレスとして "DHCP ACK" メッセージに格納した上で、クライアントへ投げ返します。 DHCP ACK メッセージは 「DHCP クライアントへ正規な IP アドレスを渡す動作」 を行うときに使われます。
↑図15:DHCP ACK メッセージ
このときやりとりされる DHCP ACK メッセージの L2 ~ L4 ヘッダー情報は以下の通りです。
↑図16:DHCP ACK - L2 ~ L4 まで
DHCP ACK メッセージの L2 ~ L4 までのヘッダーは、基本的に DHCP Offer メッセージと変わりません。 MAC アドレス、IP アドレスには DHCP Request メッセージの Source / Destination を入れ替え、ポートには Source に 67 を、destination には 68 を指定しています。 こうやって見ると、ヘッダーをレイヤーごとに分ける意味が理解できる気がしますね。
次に DHCP ACK の基本フォーマットは以下の通りです。
↑図17:DHCP ACK - 基本フォーマット
基本フォーマットに関しても L2 ~ L4 と同様に、DHCP Offer メッセージと特に変わりはありません。 yiaddr にはクライアントに割り当てる IP アドレスが指定されているところに同じく注目する程度でいいと思います。
そして以下は Option フォーマットです。
↑図18:DHCP ACK - Option フォーマット
Option フォーマットに関しても DHCP Offer メッセージとほぼ同じでした。 違う点といえば DHCP Message Type (50) が "DHCP ACK" が指定されているだけで、大して変わりはないようです。
以上が DHCP の動作をパケットレベルで解析したメモでした。
ここまで解析してみての感想ですが、(これ解析する意味あったのか?) といった気持ちが
やったら強い ですが、その辺は気にしてはイケマセン。 いつだったかのメモでも書きましたが 「パケット解析に慣れるまで」 は続けていくつもりでございます。 code reading ならぬ packet reading みたいな。。
DHCP Realy ここでは DHCP Relay についてメモしていきます。
DHCP Relay とは、DHCP クライアントとサーバが
セグメントをまたいで属しているとき に使われる技術です。 WOL のメモでも書きましたが、ブロードキャスト通信 (Limited Broadcast) は基本的に別セグメントへパケットを飛ばすことができません。 DHCP でいう Boot Request は、同一セグメント内しか DHCP パケットを飛ばすことができないのです。
それでは非常に使いづらいネットワークになってしまいますので "
DHCP Relay " という仕組みを使ってこの問題を解消します。 ちなみに DHCP Relay と "
DHCP Relay Agent " の違いについては、前者が名称、後者が総称なのだそうです。 へぇへぇー、ですよねw (独習 TCP/IP p294 参考)
↑図19:DHCP Relay
このとき DHCP Realy 機能を持たせた Vyatta の Config を以下にメモします。
# set service dhcp-relay { interface eth0 interface eth1 server 20.1.1.1 }
DHCP サーバの config は 「検証環境」 のメモで残したものを流用しています。 あの config ではネットワークアドレスが 10.1.1.0/24 でしたが、今回はそれを 20.1.1.0/24 に書き換えただけですので割愛。。
この環境でクライアントから DHCP Discover メッセージをブロードキャストしますと、DHCP Relay ルータは eth0 から受け取った DHCP Discover を eth1 へ転送します。 このときの Discover メッセージは図5と同じものですが、ルータが DHCP Relay を処理した後の Discover メッセージの “Relay agent IP address” には DHCP Relay の IP アドレスが指定されます。
↑図20:DHCP Relay された Discover メッセージ
※上図の画像では DHCP Server のアドレスが訳あって 20.1.1.111 になっております。 本来は 20.1.1.1 のため、脳内変換をお願いいたしますw また、このとき Discover メッセージの
宛先アドレスがユニキャスト になっている点も注目です。 これはルータが Discover メッセージの宛先アドレスを書き換えていることを意味しています。 Discover メッセージは基本的には Limited Broadcast ですが、DHCP Relay されたパケットもブロードキャストなわけではないようですね。
UDP Helper Address Vyatta では DHCP Relay を実現させるコマンドが [ service dhcp-relay ] でした。
では Cisco ルータではどのように DHCP Relay を実現させているのだろう? そう疑問に思って調べてみたところ、どうやら [
ip helper-address ] というコマンドを使って DHCP Relay を実現させているようです。
(ってかヘルパーアドレスってなんだ?)
今まで聞いたことがなかったこの用語。 やや興味を抱きながら調べたところ、これは 「ブロードキャストデータグラムをルータ越えさせる仕組み」 だということが分かりました。 どうやら DHCP Relay 専用の技術ではなく、ブロードキャストをフォワードさせる “
UDP Helper Address ” という仕組みで DHCP Relay を応用的に実現させているようです。
………えっ!? ちょ、ちょ待ち。。。
ここで少し不安になってしまいました。
WOL のメモでブロードキャスト通信について触れましたが、あのときは
Limited Broadcast はセグメント越えできない と書きました。 けれども UDP Helper Address の仕組みを使うことで、今回それが実現可能になっています。 Boot Request メッセージがセグメント越えできたのは、DHCP Relay という
特別な技術を使うことで例外的に実現できている ものだと思い込んでいただけに、UDP Helper Address の登場により、僕の知っているブロードキャスト通信の概念が混乱してしまいました。
ということで、誤った知識を身に着けてしまわないように GNS3 を使って以下のような環境を作りました。
↑図21:なんだかんだ、初めて GNS3 で作ったテスト環境
Config は以下のものを使いました。
Vyatta の DHCP Relay もこちらの Config を参考にしましたので、興味がありましたらご参考に。
参考:OpenManiak.com
http://openmaniak.com/vyatta_case_dhcp.php
図21の環境と上記 URL の Config を書いたところ、無事に DHCP Relay が成功してくれました。 今回は Discover メッセージでしたが、これは他の Limited Broadcast のデータグラムでもフォワードされると思うので、DHCP Relay 以外の Limited Broadcast がセグメント越えできたという意味になります。
でも…… Limited Broadcast がフォワードできたといっても、よく考えたらこれは
ユニキャストの転送 になるため、ブロードキャストの転送ではありません。 では Limited Broadcast を Limited Broadcast のまま転送させるにはどうすればよいのでしょうか?
その方法を調べたところ……
分かりませんでした。 セグメント越えできないのでしょう。。(たぶん)
けれどもブロードキャストをセグメント越えさせるには Directed Broadcast があります。 Cisco ルータの場合はブロードキャストを転送させる側のインターフェースに [ ip directed-broadcast ] コマンドを設定してあげることで、ブロードキャストの転送ができました。
ちなみに、このとき [ no ip broadcast-address ] から IP アドレスの指定を消すと、なぜか 255.255.255.255 宛のデータグラムが飛んできます。 Cisco の仕様なのかは分かりませんが、こういう結果が出ると Directed Broadcast って色々便利そうです。
まとめ: Directed Broadcast をブロードキャスト通信としてルータ越えさせることはできない (よかったw)。
最後に 仕事の休憩時間に Wireshark を使って DHCP パケットを解析していたときのこと。
僕のもとに昔のプロジェクトリーダーがやってきて、
「おっ、なんか面白そうなのやってるじゃん」 と話しかけてくれました。
GEN 『Wireshark を使ってパケットを解析しておりまする』
リダ 「へぇー。 これは DHCP かな?」
GEN 『あ、はい。 よく分かりましたね。 DHCP を解析したことありますか?』
リダ 「いや、ないけれど大体わかるよ。 ここのオプションは――って意味っしょ?」
GEN 『おぉ! 詳しいっすね!!!』
リダ 「いやいや、基本的にはどれも一緒だからねw」
聞くところリーダーさんは、開発でソケットまわりを担当したことがあるようでした。
だからこんなに詳しかったのですね。
この会話でパケット解析について、色々と学ぶことができました。
けれどもそれ以上の収穫は 「
実践と経験は大切 」 ということを改めて感じたことでしょうか。
今回、僕は DHCP に関して色々なことを追究してきましたが、
リーダーさんは DHCP を解析したことがないのに、僕以上に内部フォーマットの意味と動きを理解されてました。
やはり本職の人は違いますね。
テキストを読んでも理解はできますが、それだけじゃ実務経験者(現役者)には敵わない。
実践と経験を積まなければ、更に深いところまで見えてきません。
僕もインフラまわりのプロを目指すためにも、更なる経験を積まなければなりません。
最近気持ちがたるんできたので、改めて気持ちを引き締め直した、そんなリーダーとのお話でした。
スポンサーサイト