[solved] DHCP on VLAN interfaces

HI,

I'm running in to an issue while trying to set up VLANs with DHCP.
I have two OpenWrt instances, owrt1 and owrt2, that I want to communicate over VLAN 20.
I created two VLAN interfaces on each instance with DHCP server enabled on owrt1, DHCP client on owrt2. When bringing the interfaces up, owrt2 never receives the DHCP reply from owrt1. I confirmed with tcpdump that owrt1 is indeed receiving the request and replying, but somehow the reply evaporates into the ether.

Setting a static IP on owrt2 works fine and the hosts are able to communicate.
I'm using dnsmasq as the DHCP server, and udhcpc as the client.

tcpdump from owrt1 (server):

06:17:35.876824 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto UDP (17), length 328)
    0.0.0.0.68 > 255.255.255.255.67: [udp sum ok] BOOTP/DHCP, Request from 9c:eb:e8:xx:xx:xx, length 300, xid 0xb4c6c90f, secs 1018, Flags [none] (0x0000)
	  Client-Ethernet-Address 9c:eb:e8:32:58:ca
	  Vendor-rfc1048 Extensions
	    Magic Cookie 0x63825363
	    DHCP-Message Option 53, length 1: Discover
	    MSZ Option 57, length 2: 576
	    Parameter-Request Option 55, length 8: 
	      Subnet-Mask, Default-Gateway, Domain-Name-Server, Hostname
	      Domain-Name, BR, NTP, Classless-Static-Route
	    Vendor-Class Option 60, length 12: "udhcp 1.30.1"
	    Hostname Option 12, length 7: "openwrt"
06:17:35.888133 IP (tos 0xc0, ttl 64, id 4679, offset 0, flags [none], proto UDP (17), length 328)
    192.168.20.2.67 > 192.168.20.155.68: [bad udp cksum 0xab33 -> 0xb68a!] BOOTP/DHCP, Reply, length 300, xid 0xb4c6c90f, secs 1018, Flags [none] (0x0000)
	  Your-IP 192.168.20.155
	  Server-IP 192.168.20.2
	  Client-Ethernet-Address 9c:eb:e8:xx:xx:xx
	  Vendor-rfc1048 Extensions
	    Magic Cookie 0x63825363
	    DHCP-Message Option 53, length 1: Offer
	    Server-ID Option 54, length 4: 192.168.20.2
	    Lease-Time Option 51, length 4: 3600
	    RN Option 58, length 4: 1800
	    RB Option 59, length 4: 3150
	    Subnet-Mask Option 1, length 4: 255.255.255.0
	    BR Option 28, length 4: 192.168.20.255
	    Default-Gateway Option 3, length 4: 192.168.20.2
	    Domain-Name-Server Option 6, length 4: 192.168.20.2
	    Domain-Name Option 15, length 2: "pi"

tcpdump from owrt2 (client):

09:17:29.806599 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto UDP (17), length 328)
    0.0.0.0.68 > 255.255.255.255.67: [udp sum ok] BOOTP/DHCP, Request from 9c:eb:e8:xx:xx:xx, length 300, xid 0xb4c6c90f, secs 1012, Flags [none] (0x0000)
	  Client-Ethernet-Address 9c:eb:e8:xx:xx:xx
	  Vendor-rfc1048 Extensions
	    Magic Cookie 0x63825363
	    DHCP-Message Option 53, length 1: Discover
	    MSZ Option 57, length 2: 576
	    Parameter-Request Option 55, length 8: 
	      Subnet-Mask, Default-Gateway, Domain-Name-Server, Hostname
	      Domain-Name, BR, NTP, Classless-Static-Route
	    Vendor-Class Option 60, length 12: "udhcp 1.30.1"
	    Hostname Option 12, length 7: "openwrt"

These messages repeat every 3 seconds endlessly.

The one thing that sets off an alarm is the bad udp cksum message on the reply. What might be causing that? Could it be the reason the packet is dropped?

This seems to me like a layer 2 issue (not firewall related). Any help would be appreciated.

Thanks

How are they connected? Directly or through a switch (managed or unmanaged)?

Post your config files for each
Network
Firewall
Dhcp

1 Like

They are connected directly to one another via Ethernet.
I set up VLAN sub-interfaces with id 20 on both ends. I tried to do this via UCI and also manually (ip link set link eth1 name eth1.20 type vlan id 20; ...), with the same results.

owrt1:

network
root@openwrt:~# uci export network
package network

config globals 'globals'
	option ula_prefix 'fd99:1234::/48'

config interface 'loopback'
	option ifname 'lo'
	option proto 'static'
	option ipaddr '127.0.0.1'
	option netmask '255.0.0.0'

config interface 'lan'
	option type 'bridge'
	option proto 'static'
	option ipaddr '192.168.18.2'
	option netmask '255.255.255.0'
	option ip6assign '64'
	option ifname 'eth0'

config interface 'wan'
	option ifname 'eth1'
	option proto 'dhcp'

config interface 'wan6'
	option ifname 'eth1'
	option proto 'dhcpv6'

config interface 'vlan20'
	option ifname 'eth1.20'
	option proto 'static'
	option ipaddr '192.168.20.2'
	option netmask '255.255.255.0'
firewall
root@openwrt:~# uci export firewall
package firewall

config defaults
	option syn_flood '1'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'REJECT'

config zone
	option name 'lan'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'ACCEPT'
	option network 'lan vlan20'

config zone
	option name 'wan'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	option masq '1'
	option mtu_fix '1'
	option network 'wan wan6'

config forwarding
	option src 'lan'
	option dest 'wan'

config rule
	option name 'Allow-DHCP-Renew'
	option src 'wan'
	option proto 'udp'
	option dest_port '68'
	option target 'ACCEPT'
	option family 'ipv4'

config rule
	option name 'Allow-Ping'
	option src 'wan'
	option proto 'icmp'
	option icmp_type 'echo-request'
	option family 'ipv4'
	option target 'ACCEPT'

config rule
	option name 'Allow-IGMP'
	option src 'wan'
	option proto 'igmp'
	option family 'ipv4'
	option target 'ACCEPT'

config rule
	option name 'Allow-DHCPv6'
	option src 'wan'
	option proto 'udp'
	option src_ip 'fc00::/6'
	option dest_ip 'fc00::/6'
	option dest_port '546'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-MLD'
	option src 'wan'
	option proto 'icmp'
	option src_ip 'fe80::/10'
	list icmp_type '130/0'
	list icmp_type '131/0'
	list icmp_type '132/0'
	list icmp_type '143/0'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-ICMPv6-Input'
	option src 'wan'
	option proto 'icmp'
	list icmp_type 'echo-request'
	list icmp_type 'echo-reply'
	list icmp_type 'destination-unreachable'
	list icmp_type 'packet-too-big'
	list icmp_type 'time-exceeded'
	list icmp_type 'bad-header'
	list icmp_type 'unknown-header-type'
	list icmp_type 'router-solicitation'
	list icmp_type 'neighbour-solicitation'
	list icmp_type 'router-advertisement'
	list icmp_type 'neighbour-advertisement'
	option limit '1000/sec'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-ICMPv6-Forward'
	option src 'wan'
	option dest '*'
	option proto 'icmp'
	list icmp_type 'echo-request'
	list icmp_type 'echo-reply'
	list icmp_type 'destination-unreachable'
	list icmp_type 'packet-too-big'
	list icmp_type 'time-exceeded'
	list icmp_type 'bad-header'
	list icmp_type 'unknown-header-type'
	option limit '1000/sec'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-IPSec-ESP'
	option src 'wan'
	option dest 'lan'
	option proto 'esp'
	option target 'ACCEPT'

config rule
	option name 'Allow-ISAKMP'
	option src 'wan'
	option dest 'lan'
	option dest_port '500'
	option proto 'udp'
	option target 'ACCEPT'

config include
	option path '/etc/firewall.user'
dhcp
root@openwrt:~# uci export dhcp
package dhcp

config dnsmasq
	option domainneeded '1'
	option localise_queries '1'
	option local '/pi/'
	option domain 'pi'
	option expandhosts '1'
	option authoritative '1'
	option readethers '1'
	option leasefile '/tmp/dhcp.leases'
	list server '192.168.16.2'
	option rebind_protection '0'
	option localservice '1'

config dhcp 'lan'
	option interface 'lan'
	option start '100'
	option limit '150'
	option leasetime '12h'
	option dhcpv6 'server'
	option ra 'server'
	option ndp 'hybrid'
	option ra_management '1'

config dhcp 'wan'
	option ignore '1'
	option interface 'wan'
	option dhcpv6 'relay'
	option ra 'relay'
	option ndp 'relay'
	option master '1'

config odhcpd 'odhcpd'
	option maindhcp '0'
	option leasefile '/tmp/hosts/odhcpd'
	option leasetrigger '/usr/sbin/odhcpd-update'
	option loglevel '4'

config dhcp 'vlan20'
	option interface 'vlan20'
	option start '100'
	option limit '150'
	option leasetime '1h'

owrt2:

network
root@openwrt:~# uci export network
package network

config globals 'globals'
	option ula_prefix 'fd64:5c0d:ebc2::/48'

config interface 'loopback'
	option ifname 'lo'
	option proto 'static'
	option ipaddr '127.0.0.1'
	option netmask '255.0.0.0'

config interface 'lan'
	option type 'bridge'
	option proto 'static'
	option ipaddr '192.168.16.2'
	option netmask '255.255.255.0'
	option ip6assign '64'
	option ifname 'eth0 ethusb'

config interface 'wan'
	option ifname 'eth1'
	option proto 'dhcp'

config interface 'wan6'
	option ifname 'eth1'
	option proto 'dhcpv6'
	option reqaddress 'try'
	option reqprefix 'auto'

config interface 'vlan20'
	option ifname 'ethusb.20'
	option proto 'dhcp'
firewall
root@openwrt:~# uci export firewall
package firewall

config defaults
	option syn_flood '1'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'REJECT'

config zone 'lan'
	option name 'lan'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'ACCEPT'
	list device 'tun0'
	option network 'lan vlan20'

config zone 'wan'
	option name 'wan'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	option masq '1'
	option mtu_fix '1'
	option network 'wan wan6'

config forwarding 'lan_wan'
	option src 'lan'
	option dest 'wan'

config rule
	option name 'Allow-DHCP-Renew'
	option proto 'udp'
	option dest_port '68'
	option target 'ACCEPT'
	option family 'ipv4'
	option src 'wan'

config rule
	option name 'Allow-Ping'
	option src 'wan'
	option proto 'icmp'
	option icmp_type 'echo-request'
	option family 'ipv4'
	option target 'ACCEPT'

config rule
	option name 'Allow-IGMP'
	option src 'wan'
	option proto 'igmp'
	option family 'ipv4'
	option target 'ACCEPT'

config rule
	option name 'Allow-DHCPv6'
	option src 'wan'
	option proto 'udp'
	option src_ip 'fc00::/6'
	option dest_ip 'fc00::/6'
	option dest_port '546'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-MLD'
	option src 'wan'
	option proto 'icmp'
	option src_ip 'fe80::/10'
	list icmp_type '130/0'
	list icmp_type '131/0'
	list icmp_type '132/0'
	list icmp_type '143/0'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-ICMPv6-Input'
	option src 'wan'
	option proto 'icmp'
	list icmp_type 'echo-request'
	list icmp_type 'echo-reply'
	list icmp_type 'destination-unreachable'
	list icmp_type 'packet-too-big'
	list icmp_type 'time-exceeded'
	list icmp_type 'bad-header'
	list icmp_type 'unknown-header-type'
	list icmp_type 'router-solicitation'
	list icmp_type 'neighbour-solicitation'
	list icmp_type 'router-advertisement'
	list icmp_type 'neighbour-advertisement'
	option limit '1000/sec'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-ICMPv6-Forward'
	option src 'wan'
	option dest '*'
	option proto 'icmp'
	list icmp_type 'echo-request'
	list icmp_type 'echo-reply'
	list icmp_type 'destination-unreachable'
	list icmp_type 'packet-too-big'
	list icmp_type 'time-exceeded'
	list icmp_type 'bad-header'
	list icmp_type 'unknown-header-type'
	option limit '1000/sec'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-IPSec-ESP'
	option src 'wan'
	option dest 'lan'
	option proto 'esp'
	option target 'ACCEPT'

config rule
	option name 'Allow-ISAKMP'
	option src 'wan'
	option dest 'lan'
	option dest_port '500'
	option proto 'udp'
	option target 'ACCEPT'

config include
	option path '/etc/firewall.user'

config rule 'ovpn'
	option dest_port '1194'
	option proto 'udp'
	option name 'Allow-OpenVPN'
	option src 'wan'
	option target 'ACCEPT'

config nat 'ovpn_nat'
	option target 'MASQUERADE'
	option src '*'
	option name 'OpenVPN-NAT'
	option src_ip '169.254.11.0/29'

config rule
	option dest_port '22'
	option src 'wan'
	option name 'Allow-WAN-SSH'
	option target 'ACCEPT'
	list proto 'tcp'
	option enabled '0'

config redirect
	option dest_port '22'
	option src 'wan'
	option name 'SSH-22522'
	option src_dport '22522'
	option target 'DNAT'
	option dest_ip '192.168.16.2'
	option dest 'lan'
	list proto 'tcp'
dhcp
root@openwrt:~# uci export dhcp
package dhcp

config dnsmasq
	option domainneeded '1'
	option localise_queries '1'
	option local '/home/'
	option domain 'home'
	option expandhosts '1'
	option authoritative '1'
	option readethers '1'
	option leasefile '/tmp/dhcp.leases'
	option localservice '0'
	list server '208.67.222.222'
	option serversfile '/tmp/adb_list.overall'
	option rebind_protection '0'
	option dhcpscript '/usr/sbin/iptmon'
	option confdir '/tmp/dnsmasq.d'

config dhcp 'lan'
	option interface 'lan'
	option start '100'
	option limit '150'
	option dhcpv6 'server'
	option ra 'server'
	option ra_management '1'
	option leasetime '4h'

config dhcp 'wan'
	option interface 'wan'
	option ignore '1'
	option dhcp 'relay'
	option ra 'relay'
	option ndp 'relay'
	option master '1'

config odhcpd 'odhcpd'
	option maindhcp '0'
	option leasefile '/tmp/hosts/odhcpd'
	option leasetrigger '/usr/sbin/odhcpd-update'
	option loglevel '4'

OK, after some further investigation (and reading the tcpdump man page again) it appears that the packet is being corrupted somehow - like the VLAN tag is not being identified properly, the packet is not interpreted as a DHCP reply, and the requests continue going out.
Here is what the server sends out:

tcpdump -Xevnni eth1 vlan 20
19:12:07.567831 02:42:ac:12:00:02 > 9c:eb:e8:32:58:ca, ethertype 802.1Q (0x8100), length 346: vlan 20, p 0, ethertype IPv4, (tos 0xc0, ttl 64, id 9401, offset 0, flags [none], proto UDP (17), length 328)
    192.168.20.2.67 > 192.168.20.155.68: BOOTP/DHCP, Reply, length 300, xid 0x8aeecb24, secs 581, Flags [none]
	  Your-IP 192.168.20.155
	  Server-IP 192.168.20.2
	  Client-Ethernet-Address 9c:eb:e8:32:58:ca
	  Vendor-rfc1048 Extensions
	    Magic Cookie 0x63825363
	    DHCP-Message Option 53, length 1: Offer
	    Server-ID Option 54, length 4: 192.168.20.2
	    Lease-Time Option 51, length 4: 3600
	    RN Option 58, length 4: 1800
	    RB Option 59, length 4: 3150
	    Subnet-Mask Option 1, length 4: 255.255.255.0
	    BR Option 28, length 4: 192.168.20.255
	    Default-Gateway Option 3, length 4: 192.168.20.2
	    Domain-Name-Server Option 6, length 4: 192.168.20.2
	    Domain-Name Option 15, length 2: "pi"
	0x0000:  45c0 0148 24b9 0000 4011 aa3e c0a8 1402  E..H$...@..>....
	0x0010:  c0a8 149b 0043 0044 0134 ab33 0201 0600  .....C.D.4.3....
	0x0020:  8aee cb24 0245 0000 0000 0000 c0a8 149b  ...$.E..........
	0x0030:  c0a8 1402 0000 0000 9ceb e832 58ca 0000  ...........2X...
	0x0040:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x0050:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x0060:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x0070:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x0080:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x0090:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x00a0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x00b0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x00c0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x00d0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x00e0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x00f0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x0100:  0000 0000 0000 0000 6382 5363 3501 0236  ........c.Sc5..6
	0x0110:  04c0 a814 0233 0400 000e 103a 0400 0007  .....3.....:....
	0x0120:  083b 0400 000c 4e01 04ff ffff 001c 04c0  .;....N.........
	0x0130:  a814 ff03 04c0 a814 0206 04c0 a814 020f  ................
	0x0140:  0270 69ff 0000 0000                      .pi.....

But here is what the client receives:

tcpdump -Xevnni ethusb vlan 20
22:12:07.565406 02:42:ac:12:00:02 > 9c:eb:e8:32:58:ca, ethertype 802.1Q (0x8100), length 346: vlan 20, p 0, LLC, dsap Unknown (0x44) Group, ssap Unknown (0xc0) Command, ctrl 0x4801: Supervisory, Receiver Ready, rcv seq 36, Flags [Command], length 328
	0x0000:  24b9 6980 4011 aa3e c0a8 1402 c0a8 149b  $.i.@..>........
	0x0010:  0043 0044 0134 ab33 0201 0600 8aee cb24  .C.D.4.3.......$
	0x0020:  0245 0000 0000 0000 c0a8 149b c0a8 1402  .E..............
	0x0030:  0000 0000 9ceb e832 58ca 0000 0000 0000  .......2X.......
	0x0040:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x0050:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x0060:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x0070:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x0080:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x0090:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x00a0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x00b0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x00c0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x00d0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x00e0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
	0x00f0:  0000 0000 0000 0000 0000 0000 0000 b4ca  ................
	0x0100:  0000 0000 6382 5363 3501 0236 04c0 a814  ....c.Sc5..6....
	0x0110:  0233 0400 000e 103a 0400 0007 083b 0400  .3.....:.....;..
	0x0120:  000c 4e01 04ff ffff 001c 04c0 a814 ff03  ..N.............
	0x0130:  04c0 a814 0206 04c0 a814 020f 0270 69ff  .............pi.
	0x0140:  0000 0000                                ....

I haven't tried any other type of traffic to see what happens, but as stated before assigning static IPs and sending ICMP packets in either direction works fine.

It doesn't appear to be an MTU issue as the packets are on the order of 300 bytes long.

Any help would be much appreciated!

I managed to find what was causing the issue.

It's related to the fact that UDP checksumming is disabled on virtual interfaces by default (I am using macvlan interfaces in addition to VLAN tagging). DHCP clients like dhcpcd reject UDP packets with bad or missing checksums. So I installed iptables-mod-checksum and added the following iptables rule to the DHCP host:

iptables -A POSTROUTING -t mangle -p udp --dport 68 -j CHECKSUM --checksum-fill

This fixed the problem.

3 Likes

If your problem is solved, please consider marking this topic as [Solved]. See How to mark a topic as [Solved] for a short how-to.

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.