DHCPのクライアントIDオプション
DHCPのちょっと深いお話しです。
DHCPのオプション61(Client Identifier:クライアントID)について
DHCPの基本的な仕様はRFC2131にまとめられています。この中で、「クライアントID」に関して次のような記述があります。
A DHCP server needs to use some unique identifier to associate a
client with its lease. The client MAY choose to explicitly provide
the identifier through the 'client identifier' option. If the client
supplies a 'client identifier', the client MUST use the same 'client
identifier' in all subsequent messages, and the server MUST use that
identifier to identify the client. If the client does not provide a
'client identifier' option, the server MUST use the contents of the
'chaddr' field to identify the client. It is crucial for a DHCP
client to use an identifier unique within the subnet to which the
client is attached in the 'client identifier' option. Use of
'chaddr' as the client's unique identifier may cause unexpected
results, as that identifier may be associated with a hardware
interface that could be moved to a new client. Some sites may choose
to use a manufacturer's serial number as the 'client identifier', to
avoid unexpected changes in a clients network address due to transfer
of hardware interfaces among computers. Sites may also choose to use
a DNS name as the 'client identifier', causing address leases to be
associated with the DNS name rather than a specific hardware box.
要するに、クライアントからのリクエストに「クライアントID」が指定されていたら、サーバは「クライアントID」でクライアントを識別し、指定されていなければ「クライアントハードウェアアドレス:MACアドレス」で識別しなさいと言っています。「クライアントID」の存在理由はネットワークボードを交換しても同じ払い出しを受けられるから、という感じですが、その代わり、「クライアントID」はサブネット内でユニークでなければならないとあります。
実際のDHCPクライアントは、ほとんどが「クライアントID」に、「0x01+MACアドレス」を指定してきます。先頭の0x01は種別がMACアドレスだという識別の値です。この状態で運用している限りは、「クライアントID」といってもMACアドレスでクライアントを識別しているのと同じことであり、ほとんどの人の認識通り「DHCPはMACアドレスとIPアドレスなどの紐付けを行うためのもの」という動きになります。
ところが・・・MacOSXでは誰でも簡単に触ることができるところで「クライアントID」を自分で指定できるようになっています。
op=1:BOOTREQUEST
htype=1:HTYPE_ETHER
hlen=6
hops=0
xid=1896074777
secs=0
flags=0
ciaddr=192.168.0.88
yiaddr=0.0.0.0
siaddr=0.0.0.0
giaddr=0.0.0.0
chaddr=84:38:35:4d:89:46
sname=
file=
options
53:DHCP message type:1:3:DHCPREQUEST
55:parameter request list:9:1,3,6,15,119,95,252,44,46
57:maximum DHCP message size:2:1500
61:client-identifier:7:01:84:38:35:4D:89:46
51:IP address lease time:4:7776000
12:hostname:12:komata-Air-3
255:end
オプション61には「0x01+MACアドレス」が指定されてリクエストが飛びます。
ここに自分で値を指定すると、
op=1:BOOTREQUEST
htype=1:HTYPE_ETHER
hlen=6
hops=0
xid=2487258444
secs=0
flags=0
ciaddr=0.0.0.0
yiaddr=0.0.0.0
siaddr=0.0.0.0
giaddr=192.168.0.254
chaddr=84:38:35:4d:89:46
sname=
file=
options
53:DHCP message type:1:3:DHCPREQUEST
55:parameter request list:9:1,3,6,15,119,95,252,44,46
57:maximum DHCP message size:2:1500
61:client-identifier:5:00:74:65:73:74
50:requested IP address:4:192.168.0.88
51:IP address lease time:4:7776000
12:hostname:12:komata-Air-3
255:end
オプション61には「0x00+指定した値」が使われます。
このように、MacOSX端末では、1セグメント内で「クライアントID」に同じ値を指定することは簡単にできてしまうということになります。
RFC2131の動きに従うと、「クライアントID」が同じリクエストには同じものを払い出すという動きになります。実際に、ISCのDHCPサーバを使ってシミュレータを使ってやってみると、
MACアドレス:02:00:00:00:00:00に10.19.254.74を払い出し
「
Oct 22 19:01:51 test: dhcpd: DHCPDISCOVER from 02:00:00:00:00:00 via 10.19.254.254
Oct 22 19:01:52 test: dhcpd: DHCPOFFER on 10.19.254.74 to 02:00:00:00:00:00 (dhcpclient) via 10.19.254.254
Oct 22 19:01:52 test: dhcpd: DHCPREQUEST for 10.19.254.74 (10.9.48.13) from 02:00:00:00:00:00 (dhcpclient) via 10.19.254.254
Oct 22 19:01:52 test: dhcpd: DHCPACK on 10.19.254.74 to 02:00:00:00:00:00 (dhcpclient) via 10.19.254.254
」
リリースせずに、MACアドレス:02:00:00:00:00:01で同じ「クライアントID」を指定して要求
「
Oct 22 19:02:18 test: dhcpd: DHCPDISCOVER from 02:00:00:00:00:01 (dhcpclient) via 10.19.254.254
Oct 22 19:02:18 test: dhcpd: DHCPOFFER on 10.19.254.74 to 02:00:00:00:00:01 (dhcpclient) via 10.19.254.254
Oct 22 19:02:18 test: dhcpd: DHCPREQUEST for 10.19.254.74 (10.9.48.13) from 02:00:00:00:00:01 (dhcpclient) via 10.19.254.254
Oct 22 19:02:18 test: dhcpd: DHCPACK on 10.19.254.74 to 02:00:00:00:00:01 (dhcpclient) via 10.19.254.254
」
異なるMACアドレスのリクエストに対して、リース中のIPアドレスを払い出すのです。しかも、標準状態では「クライアントID」はログに出ませんので、このログだけを見ていると、「リース中のIPアドレスが他のMACアドレスに払い出されるのはなぜ?」となってしまいます。
私はProDHCPを長年、開発・販売してきましたが、クライアントIDをRFC2131が意図したように「MACアドレスに依存しないクライアントの識別」に使っている運用には出会ったことがありません。実はProDHCPはRFC2131のこの部分を無視していて、「クライアントID」は払い出しのキーとして使っていません(match ifなどで条件には使えます)。この方が安全だと考えるということもあるのですが、そもそも必要なケースに出会っていないためです。IPv6版のDHCPではDUID(DHCP Unique Identifier)を識別のキーとすると明言されているのですが、IPv4のDHCPではMACアドレスがキーだと考えて運用しているのがほとんどでしょう。
それどころか・・・ある運用では不正端末を簡易的に排除するために「クライアントID」が所定のものかどうかというので払い出しを制御しているケースもあります(ProDHCP使用。ISC-DHCPサーバでは無理です)。MacOSXでは「クライアントID」だけが簡単に指定できるから、という理由でした。
Option DHCPDISCOVER DHCPREQUEST DHCPDECLINE,
DHCPINFORM DHCPRELEASE
------ ------------ ----------- -----------
Requested IP address MAY MUST (in MUST
(DISCOVER) SELECTING or (DHCPDECLINE),
MUST NOT INIT-REBOOT) MUST NOT
(INFORM) MUST NOT (in (DHCPRELEASE)
BOUND or
RENEWING)
IP address lease time MAY MAY MUST NOT
(DISCOVER)
MUST NOT
(INFORM)
Use 'file'/'sname' fields MAY MAY MAY
DHCP message type DHCPDISCOVER/ DHCPREQUEST DHCPDECLINE/
DHCPINFORM DHCPRELEASE
Client identifier MAY MAY MAY
・・・
そもそもこのように「クライアントID」は「MAY」ですから、それをキーというのはどうなのかという感じもします。
さて、最後に、運用する上で「クライアントID」に関して注意することをまとめておきましょう。
●ISCのDHCPサーバ
・RFC2131通りに動きますので、「クライアントID」が同じならMACアドレスが違うリクエストでも同じものがリース中であっても払い出されます。
・なぜか、「クライアントID」をリクエストに含めないで与えると、動きがとても遅くなります。この場合は「0x01+MACアドレス」で自動で『クライアントID」が付与されます。
●ProDHCP
・「クライアントID」はmatch ifやclassなどで明示的に条件として記述しない限りはキーとして使いません。
・1セグメント内で同じ「クライアントID」を複数の端末が指定しても問題ありません。