« テスラコイルは分布定数回路 | トップページ | 「100円均一商品の実力(1)電球型蛍光灯」の続き »

2012年11月22日 (木)

Ubuntu desktop 12.04のdhclientのバグ?

ヤマハ製ルーターにDHCP予約アドレスを設定した。Windowsやゲーム機、家電製品などでは問題なく働くのだが、Xubuntu 10.04.4とUbuntu 12.04はうまくいかない。調べたらRed Hat Bugzillaにdhclientのバグだと言うスレッドが見つかった。

現象的に一致する部分があるし、提案されている対策が効いた。しかしもう少し詳しく調べると、dhclientのバグだと言い切れないのではないかと考えるべき理由が見つかってしまった。

/*******  *******/

DHCPサーバーはどうやってクライアントを見分けているのか

良く見かける説明は「MAC(L2またはイーサネット)アドレスに対してIPを割り当てる」というもの。私も、今回調べるまでは概念的にそういうものだと思っていた。これは多くの場合結果的に正しいのだが、仕組み的には少し違っている。

MACアドレスで見分けると言った場合、イーサネットヘッダーの送信元アドレスを見ていると思い浮かべる人が多いだろう。

1_2

しかし、これだとDHCPリレーエージェントが成立しない場合が出てくる。

2_2

実際にはDHCPメッセージ部分にCHADDR (Client Hardware ADDRess)フィールドがあり、そこにDHCPクライアントがMACアドレスを設定している。こうなっているのでFig. 2のように実装されたリレーエージェントを通じてDHCPが働くことが可能になっているのだ。

ここまでの説明はインターネット上で見つけることができるが、これは一世代古いRFC1541(1993年)に則った動作である。現行RFC2131(1997年)でこの部分の動作が変更になったが、これについてちゃんと説明している日本語のWebページは見つからなかった。

RFC2131ではオプションフィールドにClient IDオプションが設定されていたら、そちらをCHADDRフィールドの内容よりも優先して使うことになったのだ。MACアドレス以外をClient IDオプションに設定するのも可能である。RFC2131のPage 8に;

The 'client identifier' is an opaque key, not to be interpreted by the server; for example, the 'client identifier' may contain a hardware address, identical to the contents of the 'chaddr' field, or it may contain another type of identifier, such as a DNS name.

'client identifier'は特別な意味の無いキーであって、サーバーにより意味を解釈されるべきものではない; 例えば、'client identifier'に'chaddr'フィールドの内容と全く同じハードウエアアドレスを設定してもかまわないし、あるいはDNS名(訳注: ホスト名)のような異なるタイプの識別子でもかまわない。

とある通りだ。またRFC2132の「9.14. Client-identifier (Page 29)」では;

The client identifier MAY consist of type-value pairs similar to the 'htype'/'chaddr' fields defined in [3]. For instance, it MAY consist of a hardware type and hardware address. In this case the type field SHOULD be one of the ARP hardware types defined in STD2 [22].  A hardware type of 0 (zero) should be used when the value field contains an identifier other than a hardware address (e.g. a fully qualified domain name).

'client identifier'にはRFC951(Bootstrap Protocol)で定義されている'htype'/'chaddr'フィールドのようなタイプ-値のペアを設定してもかまわない。つまり、ハードウエアタイプとハードウエアアドレスを設定してもかまわない、と言うこと。その場合タイプフィールドには、RFC1700に定義されたARPハードウエアタイプのどれかを設定すべきである。値フィールドにハードウエアアドレス以外の識別子(例えばFQDN)を設定する場合は、ハードウエアタイプを0(ゼロ)に設定すべきである。

とあり、設定方法の詳細が示されている。

3_2

なおオプションフィールドは可変長で、RFC2939IANAで定義されたオプションを複数格納することができる。

ディフォルト設定のWindowsを始めとする大多数のDHCPクライアントはClient IDオプションにMACアドレスを設定するようにしているため、結果的にMACアドレスでクライアントを見分けていることになる。またDHCPクライアントがClient IDオプションを設定することは必須ではない。設定されていない場合サーバーはCHADDRフィールドの内容を代わりに使わなければならないと規定されている。

 

MACアドレス以外をClient IDに設定する場合

Linuxではdhclient.confファイルに記述したり、GUIのNetwork Managerで指定したりすることで任意のClient IDを設定できる。

4_3

Windowsの場合、レジストリを編集することで4バイトの値を設定できるとか、ipconfigコマンドで任意の文字列が設定できるとかの記述が見受けられる。ただしインターネットで確認できたのはXPまでで、Vista以降もこの機能がサポートされているか不明である。実際にipconfig /setclassidコマンドによる方法をVista Ultimate SP2上で試したところ、コマンドは受け付けられるがipconfig /showclassidコマンドの結果に反映されない。またDHCPサーバーには設定したつもりのClient IDが送られていない模様で、これを見る限りサポートされていない可能性が高い。

冷静に考えると、MACアドレス以外をClient IDに設定しなければならない状況はあまり無さそうである。逆に任意の値を設定してしまうと、他のクライアントと重複したり、DHCPサーバーがサポートしていなかったり、問題を生じるおそれの方が高いかもしれない。その意味では、Fig. 4のように手軽に設定できるようにする必要があったのか、疑問である。

MACアドレス以外の、本質的にユニークなClient IDを設定すべきだと言う話もある。

RFC4361(2006年)で新たなClient IDの標準が提案されている。これはIPv6との整合性を保つためだと思われるが、これが採用されても無視してしまうDHCPサーバーが少なからず出てきそうである(特にコンシューマー向けルーター組み込みのもの:詳細後述)。そのためか、(少なくとも日本のコンシューマーマーケットでは)実際に使われている例は見られず、前述のMACアドレスを設定する方式が事実上の標準(de facto standard)になっているようだ。

 

今回の解決策

Red Hat Bugzillaで提案されていた、dhclient.confに一行追加する方法を採用した。

send dhcp-client-identifier = hardware;

send dhcp-client-identifierが指定されていないとdhclientはClient IDを設定しないので、DHCPサーバーはCHADDRに設定された値に応じてIPアドレスを割り振るが、これでディフォルト設定のWindowsと同じ動作になる。RFC4361に則った動作も可能だ。

send dhcp-client-identifier = concat(03:00:01, suffix(hardware, 6));

これをヤマハ製ルーター(RT58i firmware Rev.9.01.51)は正しく識別した。MACアドレスがClient IDに設定された場合と異なるDHCP予約アドレスを設定しておけば、正しくそのIPアドレスを割り当ててくれる。またホスト名をClient IDとして用いるなら、次のように設定することができる。

send host-name "<hostname>";
send dhcp-client-identifier = concat(00, config-option host-name);

1行目はインストールした状態のdhclient.confに既に設定されているもので、2行目が追加したものである。試していないが、上と逆の順番だとうまく動かないのではないかと思う。

 

ヤマハ製ルーターのコマンドについて

DHCP予約アドレスはdhcp scope bindコマンドを用いて設定するが、dhcp server rfc2131 compliantコマンドによる設定内容に影響を受けるので注意が必要である。また今回の記事に書いてきたRFC2131に則ったDHCPサーバーの挙動を予め理解していないと、コマンドリファレンスの内容はかなり理解し辛い。「この通りにやればOK」と言う意味では、FAQの説明の方が分りやすいかもしれない。

今回の対策の後の、最終的なDHCP設定は以下の様になった。

dhcp service server
dhcp server rfc2131 compliant except remain-silent
dhcp scope 1 xxx.xxx.xxx.xxx-xxx.xxx.xxx.xxx/24
dhcp scope bind 1 xxx.xxx.xxx.xxx ethernet xx:xx:xx:xx:xx:xx
(以下必要なだけdhcp scope bindを繰り返す)

2行目にexcept remain-silentが入っているのは、これが無いと一部のDHCPクライアントがリースの更新に失敗する場合が考えられるためである。DHCP予約アドレスがうまく働かないことについてはUbuntuの方で対策を行い、dhcp scope bindコマンドはClient IDを設定する場合の方式に統一した。

なおClient IDを設定する場合に対応したdhcp scope bindコマンドによる設定は、以下の指定とともにdhcp server rfc2131 compliantコマンドが実行される時に削除されるはずなので、注意が必要である。

  • off
  • exceptが無くfunctionのリストにuse-clientidが含まれない
  • exceptに続くfunctionのリストにuse-clientidが含まれる

今回のようにUbuntu側で対策を行う代わりに、当該ホストだけ以下の形式のdhcp scope bindコマンドで設定を行えば、同じように当初の目的は達成できる。

dhcp scope bind 1 xxx.xxx.xxx.xxx xx:xx:xx:xx:xx:xx

どちらを採るか方針の問題かもしれない。しかしリスクに関する以下の理由から今回のような対策を行った。

  • 今後dhclient関連パッケージのアップデートでClient IDを設定するように修正されるかもしれない
  • Network Managerなど他のパッケージがClient IDを設定するような構成情報を追加するかもしれない
  • 今回の対応はde facto standardに合わせているので、アップデートなどで違う動作に変更される可能性が低い

 

他のブロードバンドルーター組み込みDHCPの挙動

メルコ/BUFFALOのBLR3-TX4とPLANEXのBRC-14VGについて調べた。どちらも古い製品だが、発売当時は各社のコンシューマー向けハイエンドに位置づけられた製品である。

結果はどちらも同じで、Client IDオプションに何を設定しても反映されない。常にMACアドレスに応じてIPを割り振っている。これはRFC1541に則りCHADDRフィールドに設定された内容でクライアントを識別しているようだが、もしかすると本当にイーサネットヘッダーの送信元MACアドレスを見ている場合があるかもしれない。これはテスト用に修正・ビルドしたdhclientを使えば確かめられるはずだが、ちょっとそれは勘弁、である。

現実的に考えると、これは最も安全な実装だと言えそうだ。CHADDRに設定されるのはMACアドレスに決まっているが、Client IDには何が設定されるか分らない。多くの場合にソツなく働くには圧倒的に有利だ。またMACアドレスに対してIPを割り振ると言う「世間の常識」に合っている方が利用者にも分り易い製品だと言えるだろう。従って、最新の製品も同じような挙動を示すものが多いのではないかと考えられる。

これじゃあRFC4361など新しい標準が浸透するのはかなり難しいだろう。また一部の仮想化ツールなどはClient IDを変化させたDHCP要求を送ることで複数のIPアドレスを得ている様なので、期待通り動かない場合があるかもしれない。

 

これはdhclientのバグか?

私が読み間違えていなければ、Red Hat Bugzillaエントリー冒頭の「Description of problem」の記述は以下の様になっているはずだ。

  • イーサネットとWifi装備のWindows 7を用意する
  • WifiでDHCPサーバーのあるネットワークに接続する
  • イーサネットでFedora workstationと接続する
  • WifiとイーサネットをNDISミニポートブリッジで接続する
  • Fedora workstationからDHCP要求を送っても、ブリッジがイーサネットヘッダーの送信元MACアドレスを書き換えてしまうので、応答が戻ってこない
  • ブリッジにより書き換えられないClient IDを設定するように変更すべきである

今まで見てきたDHCPの仕組みと照らし合わせると、上記のシナリオはおかしい。ブリッジがCHADDRフィールドの内容も書き換えるとは考えにくい。ある程度知識のある人がスレッドに書かれていることだけでも通して読めば、このおかしさに気付くはずだと思う。

もしかすると、たまたま使ったDHCPサーバーがイーサネットヘッダーの送信元MACアドレスを見る実装だった、と言うオチかもしれない。

私の見立てでは、dhclientそのものに問題は無さそうだ。今回の私の問題はRFC2131の範囲内でルーターの設定を変えることでも対応できたので、dhclientの問題ではない。もちろんde facto standardに合わせておいてもらった方が、多少なりとも手間が省けて助かったと言う事はある。

 

今回のまとめ

ヤマハ製ルーターは企業向け製品としては比較的低価格だが、高機能である。そのため、適切に構成コマンドを使うことで、あまり一般的ではない状況にも対応できる。しかし、正しくそういったことを行うには関連する仕組みの理解を深める必要がある。こういった機会に手を抜かずに資料を読んでおくと、また何かの時に役に立つ場合があるはずだ。

Xubuntu、Ubuntu、その他多くのLinuxディストリビューションに含まれるディフォルト設定のdhclientは、Client IDオプションを設定していないDHCP要求を送るようだ。このままでもほとんどの場合問題なく動作するはずだが、dhclient.confに1行加えるだけでWindowsなどと同じde facto standardの動作をするようにできる。またRFC4361に則ったDHCP要求を送るようにすることも可能だが、サーバー側で無視される場合が少なくないと考えられ、活用できる場面は限られるだろう。

|

« テスラコイルは分布定数回路 | トップページ | 「100円均一商品の実力(1)電球型蛍光灯」の続き »

パソコン・インターネット」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/543745/56166469

この記事へのトラックバック一覧です: Ubuntu desktop 12.04のdhclientのバグ?:

« テスラコイルは分布定数回路 | トップページ | 「100円均一商品の実力(1)電球型蛍光灯」の続き »