DHCP client doesn't work on VLAN

Hello!

I once again kindly request your help.

I have a Raspberry Pi 4B router with:

  • LAN on eth0 with VLANs via a TP Link SG105E switch.
  • WAN on eth1 via a TP Link Ue300 USB adapter.

All works fine with this setup.

I'm trying to get rid of the USB adapter and the limitations it comes with. But when I move the ISP cable to the switch and WAN to eth0.99, the router stops receiving DHCP configuration.

Connectivity is fine, though, everything works if I use static address with IP I get on eth1.

Configuration

/etc/config/network

/etc/config/network

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

config globals 'globals'
	option packet_steering '0'
	option dhcp_default_duid '*'

config device
	option name 'br-lan'
	option type 'bridge'
	list ports 'eth0'

config interface 'lan'
	option device 'br-lan'
	option proto 'static'
	option ipaddr '10.0.1.1'
	option netmask '255.255.255.0'
	option multipath 'off'

config interface 'wan'
	option proto 'static'
	option device 'eth0.99'
	option ipaddr '*'
	option netmask '255.255.254.0'
	option gateway '*'
	option multipath 'off'


config interface 'vpn'
*

config interface 'guest'
	option proto 'static'
	option device 'eth0.50'
	option ipaddr '10.0.50.1'
	option netmask '255.255.255.0'
	option multipath 'off'

config interface 'media'
	option proto 'static'
	option device 'eth0.40'
	option ipaddr '10.0.40.1'
	option netmask '255.255.255.0'
	option multipath 'off'

config wireguard_vpn
*

config device
	option type '8021q'
	option ifname 'eth0'
	option vid '99'
	option name 'eth0.99'
	option macaddr '*'

/etc/config/dhcp

config dnsmasq
	option domainneeded '1'
	option localise_queries '1'
	option rebind_protection '1'
	option rebind_localhost '1'
	option local '/lan/'
	option domain 'lan'
	option expandhosts '1'
	option cachesize '1000'
	option authoritative '1'
	option readethers '1'
	option leasefile '/tmp/dhcp.leases'
	option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
	option localservice '0'
	option ednspacket_max '1232'
	list server '10.0.1.1'

config dhcp 'lan'
	option interface 'lan'
	option start '100'
	option limit '150'
	option leasetime '12h'
	option dhcpv4 'server'

config dhcp 'wan'
	option interface 'wan'
	option ignore '1'
	option leasetime '12h'
	option start '100'
	option limit '150'

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

config dhcp 'guest'
	option interface 'guest'
	option start '100'
	option limit '150'
	option leasetime '12h'
	option dhcpv4 'server'

config dhcp 'media'
	option interface 'media'
	option start '100'
	option limit '150'
	option leasetime '12h'
	option dhcpv4 'server'

/etc/config/firewall

config defaults
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	option synflood_protect '1'
	option software_flow_offloading '0'
	option hardware_flow_offloading '0'
	option flow_offloading '0'
	option flow_offloading_hw '0'

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

config zone
	option name 'wan'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	option masq '1'
	option mtu_fix '1'
	list network '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 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-IPSec-ESP'
	option src 'wan'
	option dest 'guest'
	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 rule
	option name 'Allow-ISAKMP'
	option src 'wan'
	option dest 'guest'
	option dest_port '500'
	option proto 'udp'
	option target 'ACCEPT'

config zone
	option name 'vpn'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	option masq '1'
	option mtu_fix '1'
	list network 'vpn'

config zone
	option name 'guest'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	list network 'guest'

config forwarding
	option src 'guest'
	option dest 'vpn'

config rule
	option name 'Allow-Guest-DNS'
	option src 'guest'
	option dest_port '53'
	option proto 'tcp udp'
	option target 'ACCEPT'

config rule
	option name 'Allow-Media-DNS'
	option src 'media'
	option dest_port '53'
	option proto 'tcp udp'
	option target 'ACCEPT'

config forwarding
	option src 'lan'
	option dest 'vpn'

config rule
	option src 'guest'
	option name 'Allow-Guest-DHCP'
	list proto 'udp'
	option dest_port '67 68'
	option target 'ACCEPT'

config rule
	option src 'media'
	option name 'Allow-Media-DHCP'
	list proto 'udp'
	option dest_port '67 68'
	option target 'ACCEPT'

config zone
	option name 'media'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	list network 'media'

config forwarding
	option src 'media'
	option dest 'vpn'

config rule
	option src 'lan'
	option dest 'media'
	option name 'Allow-Lan-to-Media'
	option target 'ACCEPT'

Troubleshooting

This is what I get when trying to get a DHCP configuration:

logread -f

daemon.notice hostapd: Set MLD config: [ ]
daemon.notice hostapd: Reload all interfaces
daemon.notice netifd: Interface 'vpn' is setting up now
daemon.notice wpa_supplicant[901]: Set MLD config: [ ]
daemon.notice hostapd: Reloaded settings for phy phy0
daemon.notice netifd: wan (22457): udhcpc: received SIGTERM
daemon.notice netifd: wan (22457): udhcpc: entering released state
daemon.notice netifd: wan (22457): Command failed: ubus call network.interface notify_proto { "action": 0, "link-up": false, "keep": false, "interface": "wan" } (Permission denied)
daemon.notice netifd: Interface 'wan' is now down
daemon.notice netifd: Interface 'wan' is setting up now
daemon.notice netifd: wan (22866): udhcpc: started, v1.37.0
daemon.notice netifd: wan (22866): udhcpc: broadcasting discover
daemon.notice netifd: wan (22866): udhcpc: broadcasting select for ***, server ***
daemon.notice netifd: Interface 'vpn' is now down
daemon.info dnsmasq[1]: read /etc/hosts - 12 names
daemon.info dnsmasq[1]: read /tmp/hosts/dhcp.cfg01411c - 6 names
daemon.info dnsmasq-dhcp[1]: read /etc/ethers - 0 addresses
daemon.notice netifd: wan (22866): udhcpc: broadcasting select for ***, server ***

tcpdump -epni eth0.99 port 67 or port 68 -vvv

tcpdump: listening on eth0.99, link-type EN10MB (Ethernet), snapshot length 262144 bytes
tcpdump: pcap_loop: The interface disappeared
0 packets captured
0 packets received by filter
0 packets dropped by kernel
root@OpenWrt:~# tcpdump -epni eth0.99 port 67 or port 68 -vvv
tcpdump: listening on eth0.99, link-type EN10MB (Ethernet), snapshot length 262144 bytes
23:30:18.586783 ***MAC*** > ff:ff:ff:ff:ff:ff, ethertype IPv4 (0x0800), length 360: (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto UDP (17), length 346)
    0.0.0.0.68 > 255.255.255.255.67: [udp sum ok] BOOTP/DHCP, Request from ***MAC***, length 318, xid 0xc22c787f, secs 6, Flags [none] (0x0000)
	  Client-Ethernet-Address ***MAC***
	  Vendor-rfc1048 Extensions
	    Magic Cookie 0x63825363
	    DHCP-Message (53), length 1: Request
	    Requested-IP (50), length 4: ***.200.193
	    Server-ID (54), length 4: ***.89.57
	    MSZ (57), length 2: 576
	    Parameter-Request (55), length 8: 
	      Subnet-Mask (1), Default-Gateway (3), Domain-Name-Server (6), Hostname (12)
	      Domain-Name (15), BR (28), NTP (42), Classless-Static-Route (121)
	    Hostname (12), length 7: "OpenWrt"
	    Vendor-Class (60), length 12: "udhcp 1.37.0"
	    Client-ID (61), length 23: hardware-type 255, ***
	    END (255), length 0 23:30:42.046778 ***MAC*** > ff:ff:ff:ff:ff:ff, ethertype IPv4 (0x0800), length 354: (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto UDP (17), length 340)
    0.0.0.0.68 > 255.255.255.255.67: [udp sum ok] BOOTP/DHCP, Request from ***MAC***, length 312, xid 0x5759474, secs 30, Flags [none] (0x0000)
	  Client-Ethernet-Address ***MAC***
	  Vendor-rfc1048 Extensions
	    Magic Cookie 0x63825363
	    DHCP-Message (53), length 1: Discover
	    Requested-IP (50), length 4: ***.200.193
	    MSZ (57), length 2: 576
	    Parameter-Request (55), length 8: 
	      Subnet-Mask (1), Default-Gateway (3), Domain-Name-Server (6), Hostname (12)
	      Domain-Name (15), BR (28), NTP (42), Classless-Static-Route (121)
	    Hostname (12), length 7: "OpenWrt"
	    Vendor-Class (60), length 12: "udhcp 1.37.0"
	    Client-ID (61), length 23: hardware-type 255, ***
	    END (255), length 0
23:30:42.053253 d4:c1:c8:1b:1b:77 > ***MAC***, ethertype IPv4 (0x0800), length 351: (tos 0x0, ttl 255, id 37560, offset 0, flags [none], proto UDP (17), length 337)
    ***.200.1.67 > ***.200.193.68: [udp sum ok] BOOTP/DHCP, Reply, length 309, xid 0x5759474, Flags [none] (0x0000)
	  Your-IP ***.200.193
	  Client-Ethernet-Address ***MAC***
	  Vendor-rfc1048 Extensions
	    Magic Cookie 0x63825363
	    DHCP-Message (53), length 1: Offer
	    Subnet-Mask (1), length 4: 255.255.254.0
	    Default-Gateway (3), length 4: ***.200.1
	    Domain-Name-Server (6), length 8: ***.6,***.7
	    Domain-Name (15), length 17: "***"
	    Lease-Time (51), length 4: 1814400
	    RB (59), length 4: 1587600
	    RN (58), length 4: 296041
	    Server-ID (54), length 4: ***.89.57
	    END (255), length 0

This is an entry level switch and it has some major issues with respect to the firmware implementation. Specifically, it does not allow you to set the management VLAN and is therefore accessible from all VLANs (this is a major security vulnerability). It also has a tendency to take the ISP issued DHCP lease for itself (because of the fact that you cannot specify the management VLAN), which means that in the case of a DHCP wan, it can prevent normal operation from the router.

With that said, get a better switch before you try to integrate the wan into a single trunk cable.

Set the SG105 to have a static IP. That is the only way to prevent it from requesting DHCP on every VLAN. In the default DHCP mode setting, the SG105 is in a race to take the one IP the ISP gives you before your router can.

Also it is recommended to set LAN to tagged with some number (other than 99) rather than mixing tagged and untagged on the trunk cable.

Your problem may have something to do with you setting up a bridge on eth0, but then also creating a vlan interface off eth0.

Maybe you have vlan filtering turned on ? Try turning it off. Or for a quick check try

  • enabling bridge filtering for br-lan
  • create id 99 eth0 Tagged local ticked (and the 40 and 50 ?)
  • delete your eth0.99 device (and the 40 and 50 ?)
  • set your wan device to br-lan.99 (and br-lan.40 / 50 etc for the other ones)

Neither of these apply here. The config itself is fine.

usb ethernet can sometimes be weird ? i dunno (pi 4 ethernet is usb)

I guess, but that's not what's happening here. The problem is the switch.

Because the Pi doesn't have a built-in switch, the fact that there is a bridge containing eth0 (used by the lan) and then other interfaces using device eth0.x is entirely valid.

You also mentioned bridge-VLANs -- this method is not required and it is not being used here (per the config). It can be used, but the direct dotted notation (eth0.x) is preferred for devices like the Pi, especially because the wifi chipset only supports a single SSID and therefore doesn't benefit from any additional bridges (regardless if they are individual bridges or bridge-vlans).

I have the same problem on 25.12.4 with my R7800. If you try with 24.10 and it works, it’s probably/might be the same bug.

I recommend that you create a new thread with your own problem so it can get the proper attention.
In this new thread describe the problem and also provide your configs, for that please connect to your OpenWRT device using ssh and copy the output of the following commands and post it here using the "Preformatted text </> " button
Remember to redact keys, passwords, MAC addresses and any public IP addresses you may have but do not redact private RFC 1918 IP addresses (192.168.X.X, 10.X.X.X and 172.16-32.X.X) as that is not needed:

ubus call system board
cat /etc/config/network
cat /etc/config/wireless
cat /etc/config/dhcp
cat /etc/config/firewall

Relax. I’m not asking for help in this thread. I was referencing my own experiences, in case it could be of help.