メインコンテンツへスキップ
  1. ネットワーク 記事一覧/
  2. IPv4記事一覧/

DHCPリレーエージェント

目次

DHCPリレーエージェントとは

DHCPのDISCOVERは宛先IPアドレスを 255.255.255.255、宛先MACアドレスをブロードキャストとして送信されます。ルータはブロードキャストを転送しないため、クライアントとDHCPサーバーが別のセグメントにいる場合、そのままではDISCOVERがサーバーに届きません

セグメントごとにDHCPサーバーを設置すれば解決しますが、拠点やVLANの数だけサーバーが必要になり現実的ではありません。そこで、クライアント側のセグメントに接続しているルータがブロードキャストを代理で受け取り、ユニキャストに変換して別セグメントのDHCPサーバーへ転送します。この機能をDHCPリレーエージェントと呼びます。

リレーエージェントの動作はRFC 2131で規定されており、BOOTPリレーとしての詳細な要件はRFC 1542で定義されています。DHCPがBOOTPのメッセージフォーマットを引き継いでいるのと同様に、リレーの仕組みもBOOTPリレーエージェントから引き継いだものです。

リレーエージェントはL3の機能であり、ブロードキャストをそのまま別セグメントへ流す「ブロードキャストフォワーディング」とは異なります。リレーエージェントは受け取ったDHCPメッセージを新しいユニキャストのIPパケットとして作り直してサーバーへ送るため、途中の経路にブロードキャストが漏れることはありません。

giaddrの役割

リレーエージェントの動作を理解する鍵が、DHCPメッセージgiaddr(Gateway IP Address)フィールドです。

フィールドクライアントが送信した時点リレーエージェント通過後
giaddr0.0.0.0リレーエージェントがクライアント側インターフェースのIPアドレスを書き込む
hops0リレーエージェントを経由するたびに1ずつ加算される
宛先IPアドレス255.255.255.255DHCPサーバーのIPアドレス(ユニキャスト)
送信元IPアドレス0.0.0.0リレーエージェントのIPアドレス

giaddrは単なる「経由地の記録」ではなく、サーバーがどのプールからアドレスを払い出すかを決めるための情報です。サーバーは受け取ったメッセージのgiaddrを見て、そのアドレスが含まれるサブネットに対応するプールを選びます。リレーエージェントのクライアント側インターフェースが 192.168.20.1/24 であれば、giaddrにはこの値が入るため、サーバーは 192.168.20.0/24 のプールからアドレスを割り当てます。

また、サーバーからの応答(OFFER・ACK)はgiaddr宛てにユニキャストで返されます。リレーエージェントはそれを受け取り、クライアントへ転送します。サーバーはクライアントの位置を知る必要がなく、giaddrだけを見て応答を返せばよいという設計になっています。

hopsはリレーを経由した回数で、ループ防止のために使われます。RFC 1542はリレーエージェントに対し、hopsが4を超えたメッセージを破棄することを推奨しています。通常の構成でリレーを何段も経由することはないため、この値は1のままであることがほとんどです。

リレー経由時のパケットの流れ

クライアント(192.168.20.0/24)、リレーエージェントR1、DHCPサーバー(10.1.2.2)という構成でDORAが行われる場合の流れです。

sequenceDiagram
    participant C as クライアント
192.168.20.0/24 participant R as R1(リレー)
Gi1: 192.168.20.1
Gi2: 10.1.2.1 participant S as DHCPサーバー
10.1.2.2 C->>R: ① DISCOVER(ブロードキャスト)
宛先: 255.255.255.255
giaddr = 0.0.0.0、hops = 0 Note over R: giaddrに192.168.20.1を書き込み
hopsを1に加算
ユニキャストへ変換 R->>S: ② DISCOVER(ユニキャスト)
10.1.2.1 → 10.1.2.2
giaddr = 192.168.20.1、hops = 1 Note over S: giaddrが192.168.20.1なので
192.168.20.0/24のプールを選択 S->>R: ③ OFFER(ユニキャスト)
宛先: giaddr = 192.168.20.1
yiaddr = 192.168.20.101 R->>C: ④ OFFER(ブロードキャスト)
クライアント側セグメントへ転送 Note over C,S: REQUEST / ACK も同じ経路をたどる
  1. クライアントは通常どおりDISCOVERをブロードキャストで送信する。リレーエージェントがいることをクライアントは意識しない。
  2. R1はGigabitEthernet1でこれを受信し、giaddrに受信インターフェースのIPアドレス(192.168.20.1)を書き込み、hopsを1に加算したうえで、ip helper-addressで指定されたサーバーへユニキャストで転送する。
  3. サーバーはgiaddrから要求元のセグメントを判断し、対応するプールからアドレスを選んでOFFERをgiaddr宛てにユニキャストで返す。
  4. R1はOFFERを受け取り、クライアント側セグメントへ転送する。クライアントはアドレスをまだ持たないため、通常はブロードキャストで転送される。

REQUESTとACKも同じ経路をたどります。クライアントとサーバーのどちらもリレーの存在を特別扱いしておらず、giaddrというフィールド1つで成り立っている点がこの仕組みの要です。

リース更新(T1満了時のRENEWING)では、クライアントは既にサーバーのIPアドレスをOption 54で知っているため、サーバー宛てに直接ユニキャストでREQUESTを送ります。この場合はブロードキャストではないので通常のルーティングでサーバーに届き、リレーエージェントを経由しません。リレーが関与するのは、ブロードキャストで送られる新規取得時とREBINDING時です。

ip helper-address による設定

Cisco IOS / IOS XEでは、クライアント側のインターフェースip helper-addressを設定してリレーエージェントを有効にします。サーバー側のインターフェースではない点に注意が必要です。

リレーエージェントの設定例
interface GigabitEthernet1
 description to client segment
 ip address 192.168.20.1 255.255.255.0
 ip helper-address 10.1.2.2

DHCPサーバーが複数ある環境では、ip helper-addressを複数行書くことですべてのサーバーへ転送できます。

サーバー側には、クライアントのセグメント宛ての戻り経路が必要です。OFFERやACKはgiaddr(192.168.20.1)宛てに返されるため、サーバーがそのアドレスへ到達できなければリレーは成立しません。

ip helper-addressはDHCP以外のUDPブロードキャストも転送します。 Cisco IOSは既定で次の8つのサービスを転送対象としています。

ポートサービス
37TIME
49TACACS
53DNS
67BOOTP / DHCP サーバー
68BOOTP / DHCP クライアント
69TFTP
137NetBIOS ネームサービス
138NetBIOS データグラムサービス

DHCPだけを転送したい場合は、不要なものをno ip forward-protocol udp <ポート番号>で個別に無効化します。意図せずDNSやNetBIOSのブロードキャストまで別セグメントへ転送してしまうと、不要なトラフィックやセキュリティ上の問題につながります。

Option 82(Relay Agent Information)

Option 82は、リレーエージェントがDHCPメッセージに付加する情報で、RFC 3046で定義されています。「どのリレーエージェントの、どのポート(回線)から来た要求か」をサーバーに伝えるためのもので、内部にサブオプションを持ちます。

サブオプション名称内容
1Circuit ID要求を受け取った回線の識別子。物理ポート番号やVLAN IDなど
2Remote IDリレーエージェント自身の識別子。MACアドレスやホスト名など

リレーエージェントはクライアントからのメッセージを転送する際にOption 82を挿入し、サーバーからの応答を受け取るとクライアントへ転送する前にOption 82を取り除きます。そのためクライアントはOption 82の存在を知りません。

サーバー側では、この情報を使って「特定のポートに接続された機器にだけ特定のアドレスを割り当てる」といったポリシーや、アドレス払い出しの監査ログに利用します。またスイッチのDHCP Snoopingと組み合わせることで、バインディングテーブルにポート情報を持たせられます。

Cisco IOS / IOS XEでは次のように設定します。

Option 82 の設定
(リレーエージェント側)
ip dhcp relay information option

(DHCPサーバー側:giaddrが0のOption 82付きパケットも受け入れる場合)
ip dhcp relay information trust-all
既定では、DHCPサーバーはgiaddr0.0.0.0 のままOption 82が付いているメッセージを不正とみなして破棄します。これはリレーエージェントを経由していないのにOption 82が付いている、つまり詐称の可能性があるためです。スイッチのDHCP Snoopingがgiaddrを書き換えずにOption 82だけを挿入する構成では、サーバー側でip dhcp relay information trust-allが必要になります。

実機での検証

R3(クライアント)・R1(リレーエージェント)・R2(DHCPサーバー)を別セグメントに分けて接続し、リレー経由でのアドレス取得を実機で確認しました。ルータはいずれもCisco IOS XE 17.03.08a(csr1000v)です。

キャプチャーを2箇所で同時に取得している点がこの検証の要です。同じメッセージがリレーの前後でどう変わるかを突き合わせられます。

R2(サーバー)には次のプールと戻り経路を設定しています。戻り経路が無いとOFFERをgiaddrへ返せず、リレーは成立しません。

R2(DHCPサーバー)の設定
ip dhcp excluded-address 192.168.20.1 192.168.20.100
!
ip dhcp pool LAN20
 network 192.168.20.0 255.255.255.0
 default-router 192.168.20.1
 dns-server 10.1.2.2
 domain-name kazulog.example
 lease 0 0 2
!
ip route 192.168.20.0 255.255.255.0 10.1.2.1

R1(リレー)はクライアント側のGigabitEthernet1にip helper-addressを設定しています。

R1(リレーエージェント)の設定
interface GigabitEthernet1
 description to R3 Gi1 (client segment / capture A)
 ip address 192.168.20.1 255.255.255.0
 ip helper-address 10.1.2.2

検証の流れとサーバー側カウンタの推移

STEP操作R3のGi1DISCOVER受信OFFER送信REQUEST受信ACK送信
0初期状態(R3のGi1はshutdownunassigned0000
1R3のGi1をno shutdown192.168.20.1021111
2T1(60秒)の発火を2回待つ192.168.20.1021133
3R1からip helper-addressを削除しreleaserenewunassigned1133
4ip helper-addressを戻してrenew192.168.20.1032255
5Option 82を有効化してreleaserenew192.168.20.1043377

STEP 3に注目してください。 クライアントはアドレスを取得できずunassignedのままで、サーバー側のDISCOVER受信カウンタも1から動いていません。ip helper-addressを外したことで、DISCOVERがサーバーまで届かなくなったことが数字で確認できます。

同じDISCOVERがリレーの前後でどう変わるか

STEP 1で発生したDORAを、2つのキャプチャーで並べます。まずクライアント側です。

キャプチャーA(R3 - R1間):クライアント側から見たDORA
    1   0.000000      0.0.0.0 → 255.255.255.255 DHCP 357 DHCP Discover - Transaction ID 0x26d1
    2   0.021989 52:54:00:86:de:30 → Broadcast    ARP 60 Who has 192.168.20.102? Tell 192.168.20.1
    3   2.051454 192.168.20.1 → 255.255.255.255 DHCP 372 DHCP Offer    - Transaction ID 0x26d1
    4   2.057779      0.0.0.0 → 255.255.255.255 DHCP 375 DHCP Request  - Transaction ID 0x26d1
    5   2.070234 192.168.20.1 → 255.255.255.255 DHCP 372 DHCP ACK      - Transaction ID 0x26d1
このNo.1〜No.5(クライアント側のDORA)だけを抜き出したもの

続いてサーバー側です。同じTransaction ID 0x26d1のやり取りですが、すべてユニキャストになっています

キャプチャーB(R1 - R2間):サーバー側から見た同じDORA
    1   0.000000 192.168.20.1 → 10.1.2.2     DHCP 357 DHCP Discover - Transaction ID 0x26d1
    2   2.038251     10.1.2.2 → 192.168.20.1 DHCP 372 DHCP Offer    - Transaction ID 0x26d1
    3   2.053646 192.168.20.1 → 10.1.2.2     DHCP 375 DHCP Request  - Transaction ID 0x26d1
    4   2.060189     10.1.2.2 → 192.168.20.1 DHCP 372 DHCP ACK      - Transaction ID 0x26d1
このNo.1〜No.4(サーバー側のDORA)だけを抜き出したもの

DISCOVERの中身を比較すると、リレーエージェントが書き換えたフィールドがはっきりします。左がクライアント側、右がサーバー側です。

キャプチャーA No.1:クライアントが送信したDISCOVER
    Source Address: 0.0.0.0
    Destination Address: 255.255.255.255
Dynamic Host Configuration Protocol (Discover)
    Message type: Boot Request (1)
    Hops: 0
    Transaction ID: 0x000026d1
    Bootp flags: 0x8000, Broadcast flag (Broadcast)
    Client IP address: 0.0.0.0
    Your (client) IP address: 0.0.0.0
    Next server IP address: 0.0.0.0
    Relay agent IP address: 0.0.0.0
    Client MAC address: 52:54:00:49:49:5a (52:54:00:49:49:5a)
キャプチャーB No.1:リレーが転送した同じDISCOVER
    Source Address: 192.168.20.1
    Destination Address: 10.1.2.2
Dynamic Host Configuration Protocol (Discover)
    Message type: Boot Request (1)
    Hops: 1
    Transaction ID: 0x000026d1
    Bootp flags: 0x8000, Broadcast flag (Broadcast)
    Client IP address: 0.0.0.0
    Your (client) IP address: 0.0.0.0
    Next server IP address: 0.0.0.0
    Relay agent IP address: 192.168.20.1
    Client MAC address: 52:54:00:49:49:5a (52:54:00:49:49:5a)
フィールドクライアント側サーバー側
送信元IPアドレス0.0.0.0192.168.20.1(リレーのアドレス)
宛先IPアドレス255.255.255.25510.1.2.2(サーバーのアドレス)
Hops01
Relay agent IP address(giaddr)0.0.0.0192.168.20.1
Transaction ID0x000026d10x000026d1(同じ)
Client MAC address52:54:00:49:49:5a52:54:00:49:49:5a(同じ)

前述のとおり、リレーエージェントはIPパケットとしては新しく作り直しつつ、DHCPメッセージの中身はgiaddrhops以外そのまま引き継いでいますTransaction IDClient MAC addressが変わらないため、サーバーはクライアントを正しく識別でき、応答もクライアントに対応付けられます。

クライアント側から見ると、OFFERとACKの送信元は192.168.20.1、つまりリレーエージェントです。クライアントにとってはリレーがDHCPサーバーのように見えている一方、クライアントが受け取ったOption 54(Server Identifier)は実際のサーバーのアドレスになっています。

R3 show dhcp lease
R3#show dhcp lease
Temp IP addr: 192.168.20.102  for peer on Interface: GigabitEthernet1
Temp  sub net mask: 255.255.255.0
   DHCP Lease server: 10.1.2.2, state: 5 Bound
   DHCP transaction id: 26D1
   Lease: 120 secs,  Renewal: 60 secs,  Rebind: 105 secs
Temp default-gateway addr: 192.168.20.1
   Next timer fires after: 00:00:17
   Retry count: 0   Client-ID: cisco-5254.0049.495a-Gi1
   Hostname: R3

DHCP Lease serverが自セグメント外の10.1.2.2default-gatewayがリレー側の192.168.20.1と、参照先が分かれている点がリレー構成ならではです。

リース更新はリレーを経由しない

T1(60秒)の満了で行われた更新です。添付のクライアント側キャプチャーのNo.10・No.11にあたります。

キャプチャーA No.10・No.11:T1満了によるリース更新
   10  66.279226 192.168.20.102 → 10.1.2.2     DHCP 363 DHCP Request  - Transaction ID 0x26d1
   11  66.285223     10.1.2.2 → 192.168.20.102 DHCP 372 DHCP ACK      - Transaction ID 0x26d1
このNo.10・No.11(リース更新)だけを抜き出したもの

送信元はクライアント自身の192.168.20.102、宛先はサーバーの10.1.2.2です。リレーエージェントのアドレスは現れません。この2パケットはgiaddr0.0.0.0のままで、hops0です。前述のとおり、更新はブロードキャストではなくサーバー宛てのユニキャストなので、リレーの処理を通らず通常のルーティングでR1を通過していることが確認できます。

同じパケットはサーバー側のキャプチャーにも現れます。リレーが転送しているのではなく、R1がルータとして中継しているだけです。

ip helper-address を外すとどうなるか

STEP 3でR1のGigabitEthernet1からip helper-addressを削除し、R3でアドレスを取り直させました。

キャプチャーA No.16〜No.18:応答が返らないDISCOVER
   16 179.110077      0.0.0.0 → 255.255.255.255 DHCP 357 DHCP Discover - Transaction ID 0x1439
   17 182.335039      0.0.0.0 → 255.255.255.255 DHCP 357 DHCP Discover - Transaction ID 0x1439
   18 186.335474      0.0.0.0 → 255.255.255.255 DHCP 357 DHCP Discover - Transaction ID 0x1439
このNo.16〜No.18(応答の無いDISCOVER)だけを抜き出したもの

クライアントは同じxidで3回再送し、その後xidを変えてさらに繰り返しています。クライアント側キャプチャーにはこれらのDISCOVERが9パケット記録されている一方、サーバー側キャプチャーには1パケットも現れません。

キャプチャーSTEP 3のDISCOVER(xid 0x1439 / 0x143a / 0x143b)
A(クライアント側)9パケット
B(サーバー側)0パケット

このときR1ではshow ip helper-addressの一覧が空になっています。

R1 show ip helper-address(STEP 3)
R1#show ip helper-address
Interface                  Helper-Address  VPN VRG Name             VRG State

リンクはupのままなのにアドレスが取得できず、サーバー側のカウンタも動かない。ブロードキャストがルータを越えていないことが、この3点から確認できます。STEP 4でip helper-addressを戻すと、DISCOVER受信カウンタが1から2に増えて復旧しました。

Option 82 の実際

STEP 5でR1にip dhcp relay information option、R2にip dhcp relay information trust-allを設定し、アドレスを取り直しました。サーバー側のキャプチャーではパケットが大きくなっています。

キャプチャーB No.21〜No.24:Option 82 付きのDORA
   21 387.544996 192.168.20.1 → 10.1.2.2     DHCP 373 DHCP Discover - Transaction ID 0xfb5
   22 389.551056     10.1.2.2 → 192.168.20.1 DHCP 388 DHCP Offer    - Transaction ID 0xfb5
   23 389.561390 192.168.20.1 → 10.1.2.2     DHCP 391 DHCP Request  - Transaction ID 0xfb5
   24 389.567012     10.1.2.2 → 192.168.20.1 DHCP 388 DHCP ACK      - Transaction ID 0xfb5
このNo.21〜No.24(Option 82付きのDORA)だけを抜き出したもの

DISCOVERは373バイトで、Option 82が無いSTEP 1のDISCOVER(357バイト)より16バイト大きくなっています。中身は次のとおりです。

キャプチャーB No.21 の Option 82
    Option: (82) Agent Information Option
        Length: 14
        Option 82 Suboption: (2) Agent Remote ID
            Length: 12
            Agent Remote ID: 020a0000c0a8140100000000
    Option: (255) End
この構成で挿入されたのはRemote ID(サブオプション2)だけで、Circuit ID(サブオプション1)は入りませんでした。 Remote IDの値020a0000c0a8140100000000のうちc0a81401はリレーエージェントのインターフェースアドレス192.168.20.1です。Option 82に何を入れるかは実装と構成に依存し、スイッチのDHCP Snoopingのようにポートによる区別がある環境ではCircuit IDも挿入されます。ルータ間のリレーでは区別すべき「回線」が無いため、Remote IDのみになったと考えられます。

一方、同じやり取りをクライアント側のキャプチャーで見るとOption 82は現れません

キャプチャーA No.42〜No.46:同じDORAをクライアント側で見たもの
   42 387.547323      0.0.0.0 → 255.255.255.255 DHCP 357 DHCP Discover - Transaction ID 0xfb5
   43 387.559201 52:54:00:86:de:30 → Broadcast    ARP 60 Who has 192.168.20.104? Tell 192.168.20.1
   44 389.562682 192.168.20.1 → 255.255.255.255 DHCP 372 DHCP Offer    - Transaction ID 0xfb5
   45 389.566898      0.0.0.0 → 255.255.255.255 DHCP 375 DHCP Request  - Transaction ID 0xfb5
   46 389.577910 192.168.20.1 → 255.255.255.255 DHCP 372 DHCP ACK      - Transaction ID 0xfb5
このNo.42〜No.46(クライアント側から見た同じDORA)だけを抜き出したもの

DISCOVERは357バイトのままで、OFFERとACKも372バイトです。リレーエージェントがクライアントへ転送する前にOption 82を取り除いているため、クライアントはOption 82の存在を知りません。前述の説明どおりの動作が、パケットサイズの差としてそのまま観測できます。

キャプチャーA(クライアント側)の全体をダウンロード

キャプチャーB(サーバー側)の全体をダウンロード

検証Configおよびshow結果

各STEPでR1・R2・R3から、次の3種類をルータごとに分けて取得しています。検証Configはこの..._run.txtです(最終状態はSTEP 5のもの)。

ファイル内容
..._show.txtshow version / show interfaces description / show ip interface brief / show ip route / show arp / show ip helper-address / show ip dhcp pool / show ip dhcp binding / show ip dhcp server statistics / show ip dhcp conflict / show ip dhcp relay information trusted-sources / show dhcp lease
..._log.txtそのSTEPの範囲だけに絞ったshow logging。各STEPの開始時にsend logでマーカーを入れ、その文字列をshow logging | beginに指定して取得したもの
..._run.txtそのSTEP時点のshow running-config(=そのSTEPの検証Config)

STEP 0:初期状態(R3のGi1はshutdown

ノードshow出力syslogrunning-config
R1(リレー)showlogrun
R2(サーバー)showlogrun
R3(クライアント)showlogrun

STEP 1:R3のGi1をno shutdownし、リレー経由でアドレスを取得した状態

ノードshow出力syslogrunning-config
R1(リレー)showlogrun
R2(サーバー)showlogrun
R3(クライアント)showlogrun

STEP 2:T1の満了によりリースが2回更新された状態

ノードshow出力syslogrunning-config
R1(リレー)showlogrun
R2(サーバー)showlogrun
R3(クライアント)showlogrun

STEP 3:R1からip helper-addressを削除し、アドレスを取得できなくなった状態

ノードshow出力syslogrunning-config
R1(リレー)showlogrun
R2(サーバー)showlogrun
R3(クライアント)showlogrun

STEP 4:ip helper-addressを戻して復旧した状態

ノードshow出力syslogrunning-config
R1(リレー)showlogrun
R2(サーバー)showlogrun
R3(クライアント)showlogrun

STEP 5:Option 82を有効化した状態(最終状態)

ノードshow出力syslogrunning-config
R1(リレー)showlogrun
R2(サーバー)showlogrun
R3(クライアント)showlogrun

参考

RFCタイトル概要
RFC 2131Dynamic Host Configuration Protocolgiaddrhopsの扱い、リレーエージェントの基本動作を定義。
RFC 1542Clarifications and Extensions for the Bootstrap ProtocolBOOTPリレーエージェントの詳細な要件。hopsの上限などを規定。
RFC 3046DHCP Relay Agent Information OptionOption 82とサブオプション(Circuit ID / Remote ID)を定義。

関連記事