MikroTik Guide
An isometric three-antenna router sits on a dark circuit-board platform with glowing pink cables branching to multiple connected network nodes.
Configuration

RouterOS DHCP Server Setup for VLANs

RouterOS DHCP server setup covers address pools, network entries, per-VLAN interfaces, static leases, options, and troubleshooting checks.

By MikroTik Guide Editorial · · 6 min read

A RouterOS DHCP server setup is three objects, not one: an /ip pool that holds the addresses, an /ip dhcp-server that listens on an interface, and an /ip dhcp-server network that tells clients their gateway, DNS and options. The setup wizard hides that split, which is fine for a flat 192.168.88.0/24 and wrong the moment you add an IoT VLAN. This guide builds it by hand for a router with a VLAN-filtered bridge, then covers the settings people copy without reading: lease-time, authoritative, add-arp, static leases, option 121 and the rogue-server alert.

The three objects and how they find each other

MikroTik’s DHCP documentation gives the minimal flat-network example, and it is worth reading as a dependency chain rather than a recipe:

/ip pool add name=dhcp_pool0 ranges=192.168.88.2-192.168.88.254
/ip dhcp-server network add address=192.168.88.0/24 dns-server=192.168.88.1 gateway=192.168.88.1
/ip address add address=192.168.88.1/24 interface=bridge1 network=192.168.88.0
/ip dhcp-server add address-pool=dhcp_pool0 disabled=no interface=bridge1 name=dhcp1

The server is bound to an interface. The interface must carry an IP address. The network entry is matched by that address falling inside address=, and the pool is whatever address-pool= points at. Nothing links the network to the server by name; it is purely the subnet that ties them. If the interface has no address in the subnet, the server shows as invalid in /ip dhcp-server print and answers nobody.

One hard constraint from the same page: “DHCP server requires a real interface to receive raw ethernet packets. If the interface is a Bridge interface, then the Bridge must have a real interface attached as a port.” A bridge with no ports is a valid place for an IP address and a useless place for a DHCP server.

/ip dhcp-server setup asks six questions (interface, network, gateway, pool, DNS servers, lease time) and creates the same three objects. Use it once to see the shape, then stop, because it cannot express per-VLAN options or static leases.

VLAN plan: one server per VLAN interface

On a bridge with vlan-filtering=yes, the DHCP server does not run on bridge1. It runs on a /interface vlan child of the bridge, one per segment, and each of those VLAN interfaces carries the gateway address for its subnet. The bridge itself must be a tagged member of each VLAN in /interface bridge vlan, which the Bridge VLAN Table page shows as tagged=bridge1,ether3 vlan-ids=99 for the management case. Miss that and the VLAN interface exists but never sees a frame.

VLANNameCIDRDHCP rangeGatewayLease
10lan192.168.10.0/24.100 to .199192.168.10.11d
20iot192.168.20.0/24.100 to .199192.168.20.11d
30guest192.168.30.0/24.50 to .250192.168.30.12h
/interface bridge vlan
add bridge=bridge1 tagged=bridge1,ether2 vlan-ids=10
add bridge=bridge1 tagged=bridge1,ether2 vlan-ids=20
/interface vlan
add name=vlan10-lan interface=bridge1 vlan-id=10
add name=vlan20-iot interface=bridge1 vlan-id=20
/interface list member
add list=LAN interface=vlan10-lan
add list=LAN interface=vlan20-iot
/ip address
add address=192.168.10.1/24 interface=vlan10-lan
add address=192.168.20.1/24 interface=vlan20-iot
/ip pool
add name=pool-lan ranges=192.168.10.100-192.168.10.199
add name=pool-iot ranges=192.168.20.100-192.168.20.199
/ip dhcp-server network
add address=192.168.10.0/24 gateway=192.168.10.1 dns-server=192.168.10.1
add address=192.168.20.0/24 gateway=192.168.20.1 dns-server=192.168.20.1
/ip dhcp-server
add name=dhcp-lan interface=vlan10-lan address-pool=pool-lan lease-time=1d disabled=no
add name=dhcp-iot interface=vlan20-iot address-pool=pool-iot lease-time=1d disabled=no

Guest (VLAN 30) is the same seven lines with 30, 192.168.30.x and lease-time=2h; ether2 is the trunk to the switch or AP.

The /interface list member lines matter because the default firewall’s input chain drops anything not arriving from the LAN list, and a DHCP request to UDP 67 is input traffic. The RouterOS firewall rules post walks that chain; the VLAN filtering post covers the bridge side, including why you build the VLAN table before flipping vlan-filtering=yes, since the docs warn it “might make you lose access to the device.”

The most common failure here is not the bridge at all. In a 2023 forum thread on exactly this design, the poster’s fix was their own: “I didn’t assign any ip address to that interface.” The VLAN interface needs the gateway address before the server bound to it becomes valid.

Lease time and authoritative, read against the RFC

RouterOS defaults lease-time to 30 minutes, and the docs describe the client behaviour plainly: “The client will try to renew this address after half of this time and will request a new address after the time limit expires.” That is RFC 2131 timers T1 and T2: renewal by unicast to the issuing server at 50% of the lease, then broadcast rebinding at 87.5%. Thirty minutes means every laptop unicasts a renewal every fifteen, which is harmless on a hEX, but on the LAN VLAN one day is more sensible: a client that sleeps overnight gets the same address back. Keep guest short, because guest pools fill with phones that visited once.

authoritative defaults to yes, which means the server sends DHCPNAK to a client requesting an address this server cannot give, so a device arriving from another network drops its stale lease immediately instead of timing out. no makes the server silently ignore such requests. after-2sec-delay and after-10sec-delay apply the no behaviour to requests whose secs field is below the threshold, giving another server first claim. Leave it at yes unless two servers genuinely share a segment.

conflict-detection=yes (default) probes an address before offering it. add-arp=yes makes the server write a dynamic ARP entry for each lease; pair it with arp=reply-only on the VLAN interface and a device that sets a static IP outside its lease loses connectivity, which is the cheapest anti-squatting control MikroTik ships. client-mac-limit caps leases per MAC, with the docs noting it “should not be used in relay setups.”

Static leases, options and option 121

/ip dhcp-server lease make-static converts a dynamic lease into a fixed MAC-to-IP binding. Add rate-limit= to a static lease and RouterOS creates a dynamic simple queue for that address, per the RouterOS manual; it is the one-line way to throttle a single misbehaving IoT camera.

Options beyond gateway and DNS go through /ip dhcp-server option. Codes are the RFC 2132 registry: 3 router, 6 DNS, 15 domain name, 42 NTP, 51 lease time, 66 TFTP server name, 67 bootfile. The value field has its own encoding rules, quoted from the manual: 'test' is ASCII to hex, '10.10.10.10' is an IP to 4 bytes, s'160' forces the string form, '10' is decimal to a single byte, and 0x... is raw. Get the quoting wrong and the client receives a plausible-looking option with the wrong length.

Option 121 is the one worth learning. RFC 3442 defines it as a list of prefix-length byte, the significant destination octets, then the gateway. A route to 10.50.0.0/16 via 192.168.10.2 is 0x10 0A32 C0A80A02. The catch is the same RFC’s rule that when both option 121 and the Router option are present “the DHCP client MUST ignore the Router option,” so the default route goes inside 121 too, as prefix length 00 with no destination octets:

/ip dhcp-server option
add name=routes-lan code=121 value=0x100A32C0A80A0200C0A80A01
/ip dhcp-server network
set [find address=192.168.10.0/24] dhcp-option=routes-lan

Rogue servers

A second DHCP server on a segment, usually a consumer router someone plugged in LAN-side, hands out its own gateway and DNS and wins whichever race it is first to answer. RouterOS has a built-in detector: /ip dhcp-server alert add interface=vlan20-iot valid-server=D4:CA:6D:11:22:33 alert-timeout=1h logs any DHCP server MAC not in valid-server, and on-alert= runs a script. The docs describe it as the tool “to find any rogue DHCP servers as soon as they appear in your network.” It is the same class of LAN-side attack that keeps showing up in incident reporting, and on the IoT VLAN the alert costs nothing.

Things to test before you call it done

On the router:

/ip dhcp-server print detail
/ip dhcp-server network print
/ip pool used print
/ip dhcp-server lease print where status=bound
/system logging add topics=dhcp action=memory
/log print where topics~"dhcp"

No server should carry the invalid flag. On a client in each VLAN, force a fresh lease and read back what arrived: ipconfig /release then ipconfig /renew on Windows, ipconfig getpacket en0 on macOS, nmcli device show eth0 on Linux. Then ping 192.168.20.1, dig @192.168.20.1 example.com to prove the DNS you handed out resolves, and mtr 1.1.1.1 to prove the gateway you handed out routes.

If a segment still gets nothing, capture. The Wireshark wiki gives the capture filter port 67 or port 68; the display filter is dhcp on current builds, bootp on old ones. A DISCOVER with no OFFER means the frame never reached a valid server: check the VLAN table, the interface address, and the LAN list, in that order.

Sources

  1. DHCP - RouterOS Documentation (help.mikrotik.com)
  2. DHCP - RouterOS Manual (manual.mikrotik.com)
  3. Bridge VLAN Table - RouterOS Documentation
  4. RFC 2131: Dynamic Host Configuration Protocol
  5. RFC 2132: DHCP Options and BOOTP Vendor Extensions
  6. RFC 3442: The Classless Static Route Option for DHCPv4
  7. DHCP - Wireshark Wiki
  8. DHCP server on vlan - MikroTik community forum

Related