Skip to content

DHCP Relay Option 82 Deep Dive

DHCP Option 82 (Relay Agent Information) is a DHCP extension defined in RFC 3046 that allows relay agents to insert identifying information into DHCP requests. This is essential for ISP wholesale/retail architectures, cable DOCSIS networks, and any scenario where a DHCP server needs to identify the physical location or network segment of a client.

When a DHCP relay agent intercepts a client’s broadcast DHCP request, it can append Option 82 to the packet before forwarding it to the DHCP server. This option contains two sub-options:

Sub-optionNamePurpose
1Agent Circuit IDIdentifies the circuit/interface the client is connected to
2Agent Remote IDIdentifies the remote client (typically MAC address)

The DHCP server can use this information to:

  • Assign IP addresses from the correct pool based on client location
  • Implement per-customer or per-location policies
  • Track which network segment a client belongs to
  • Enable carrier-grade NAT scenarios

RouterOS implements Option 82 through two relay properties:

Enables insertion of Relay Agent Information into DHCP packets per RFC 3046.

/ip dhcp-relay add name=relay1 interface=ether2 dhcp-server=10.0.0.1 add-relay-info=yes

When enabled, RouterOS adds:

  • Circuit ID (Sub-option 1): Interface name where the request was received
  • Remote ID (Sub-option 2): Client’s MAC address

Allows custom Remote ID string instead of default client MAC address. Useful for:

# Use router's MAC as Remote ID instead of client MAC
/ip dhcp-relay add name=relay1 interface=ether2 dhcp-server=10.0.0.1 \
add-relay-info=yes relay-info-remote-id=00:11:22:33:44:55

Or use a descriptive string:

/ip dhcp-relay add name=relay1 interface=ether2 dhcp-server=10.0.0.1 \
add-relay-info=yes relay-info-remote-id="POP-Coimbatore-01"

This is the most common use case for Option 82. Here’s how it works:

┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Client │ ───▶ │ MikroTik │ ───▶ │ ISP │
│ (Retail) │ │ Relay │ │ DHCP │
│ │ │ (Option 82) │ │ Server │
└─────────────┘ └─────────────┘ └─────────────┘
│ │
┌────┴────┐ ┌────┴────┐
│Wholesale│ │ Retail │
│ Pool │ │ Pool │
└─────────┘ └─────────┘

ISP Router (Relay):

# Configure relay with Option 82 on multiple interfaces
/ip dhcp-relay add name=wholesale-relay interface=ether1 \
dhcp-server=10.0.0.100 add-relay-info=yes
/ip dhcp-relay add name=retail-relay interface=ether2 \
dhcp-server=10.0.0.100 add-relay-info=yes

ISP DHCP Server:

The server uses the Circuit ID to determine which pool to assign from:

# Server sees Option 82 in the request and selects appropriate pool
# Circuit ID "ether1" → Wholesale pool
# Circuit ID "ether2" → Retail pool

When Option 82 is present, you can access it in DHCP server lease scripts through these variables:

VariableDescription
lease-agent-circuit-idThe Circuit ID from Option 82
lease-agent-remote-idThe Remote ID from Option 82
/ip dhcp-server add name=dhcp1 interface=bridge-local address-pool=pool1 \
lease-script={
:if ($bound = 1) do={
:log info "DHCP Lease: IP=$leaseActIP MAC=$leaseActMAC Circuit ID=$lease-agent-circuit-id Remote ID=$lease-agent-remote-id"
}
}

Example: Add Firewall Address List Based on Circuit ID

Section titled “Example: Add Firewall Address List Based on Circuit ID”
/ip dhcp-server add name=dhcp1 interface=bridge-local address-pool=pool1 \
lease-script={
:if ($bound = 1) do={
:if ($lease-agent-circuit-id ~ "vlan10") do={
/ip firewall address-list add list=DHCP-VLAN10 address=$leaseActIP
}
:if ($lease-agent-circuit-id ~ "vlan20") do={
/ip firewall address-list add list=DHCP-VLAN20 address=$leaseActIP
}
} else={
# Clean up on lease release
/ip firewall address-list remove [find list~"DHCP-VLAN" address=$leaseActIP]
}
}

For carrier-grade NAT scenarios, use the Circuit ID to create per-customer NAT mappings:

/ip dhcp-server add name=dhcp1 interface=bridge-local address-pool=cgnat-pool \
lease-script={
:if ($bound = 1) do={
:local cgnat-ip ($leaseActIP)
:local customer-id ($lease-agent-circuit-id)
:log info "CGNAT: Customer $customer-id assigned $cgnat-ip"
# Log mapping for CGNAT tracking (update your mapping table as needed)
/ip firewall address-list add list=CGNAT-customers address=$cgnat-ip comment=$customer-id
}
}
# View relay configuration
/ip dhcp-relay print detail
# Monitor relay traffic
/tool sniffer start filter-ip-protocol=udp filter-port=67,68

When Option 82 is present, it appears in lease details:

# View leases with Option 82 data
/ip dhcp-server lease print detail
# Filter leases by circuit ID
/ip dhcp-server lease print where agent-circuit-id~"vlan10"
  1. Verify add-relay-info=yes is set on the relay
  2. Check that the interface name is correct
  3. Ensure DHCP server is reachable from the relay
  1. NAT Issue: If masquerade is applied to relay traffic, Option 82 gets stripped. Exclude DHCP traffic:
/ip firewall nat add chain=srcnat protocol=udp dst-port=67-68 action=accept
/ip firewall nat add chain=srcnat out-interface=wan action=masquerade
  1. Firewall Blocking: Ensure firewall allows DHCP between relay and server:
/ip firewall filter add chain=forward protocol=udp dst-port=67-68 action=accept

Use packet capture to verify Option 82 is being inserted:

/tool sniffer start filter-ip-protocol=udp filter-port=67,68 file-name=sniff.pcap

Then analyze with Wireshark - look for DHCP Option 82 (Agent Circuit ID / Agent Remote ID).

PropertyDefaultDescription
add-relay-infonoEnable RFC 3046 relay agent info
relay-info-remote-id(client MAC)Custom Remote ID string
local-address(auto)IP used as giaddr
dhcp-server-Target DHCP server(s)
interface-Interface to listen on
VariableDescription
lease-agent-circuit-idCircuit ID from Option 82
lease-agent-remote-idRemote ID from Option 82
leaseBound1 if bound, 0 if released
leaseActIPAssigned IP address
leaseActMACClient MAC address
  1. Use descriptive circuit IDs: Name interfaces clearly (e.g., “vlan10-POP1”, “ether1-BuildingA”)
  2. Document your addressing scheme: Map Circuit IDs to pools in documentation
  3. Test with packet capture: Verify Option 82 is being added before deploying
  4. Handle lease releases: Clean up address lists and mappings when leases expire
  5. Watch for MTU issues: Option 82 adds ~32 bytes; ensure path MTU handles this