As @CGGXANNX mentioned the DHCP rule in the Mikrotik documentation is a poor example. I would also add - it creates more confusion.
Next, it is worth mentioning that accepting a packet in the /ip firewall raw table does not mean the packet is accepted. It literally means "stop processing this packet in the raw table, and send it to the connection tracker". The packet must be accepted (dropped or rejected) by some rule in your /ip firewall filter.
Now, to your question... You may need to add your VLAN interfaces as members of the LAN interface-list. Another reason that DHCP may not be passing through is most likely because this condition is too narrow:
dst-address=255.255.255.255 dst-port=67 src-address=0.0.0.0 src-port=68
It does accept DHCP discovery packets, but it will not match the DHCP renewal packets. When a host sends DHCP renewal request it already has a valid IP address assigned to it (during initial discovery stage), so the DHCP renewal packet not be matched by the above condition. Moreover, the DHCP renewal request does not use broadcast IP as its destination; instead it is sent to a (known) unicast IP address of the DHCP server.
The problem can be solved in two ways:
Option 1. Add another rule that specifically accepts DHCP renewal requests (in addition to discovery):
in-interface-list=LAN protocol=udp \
dst-address=255.255.255.255 dst-port=67 src-address=0.0.0.0 src-port=68 \
comment="accept DHCP discover"
in-interface-list=LAN protocol=udp \
dst-address-type=local dst-port=67 src-address-type=unicast src-port=68 \
comment="accept DHCP renewals"
OR
Option 2. Use a simple rule that captures both discovery AND renewal requests:
(Here, by omitting the 'src=address' and 'dst-address' we cover all DHCP scenarios: discovery and renewals. This is a preferred way of allowing DHCP traffic.)
in-interface-list=LAN protocol=udp src-port=68 dst-port=67
As an example, below are DHCP rules that I use in my firewall:
(Note: The only reason I have these rules in the â/ip firewall rawâ table is to hide all DHCP traffic in the connection tracker. This it is done with action use âaction=notrackâ.)
# DHCP Server (LAN) - discovery and renewal requests from clients
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# (host 0.0.0.0 -> router 255.255.255.255) - IP discover
# (host x.x.x.x -> router x.y.z.a ) - IP renewal
/ip firewall raw
add action=notrack chain=prerouting in-interface-list=LAN \
protocol=udp src-port=68 dst-port=67 \
comment="DHCP: [LAN->Router] Untrack discovery/renew requests"
# The *next* rule is accurate but invisible to RouterOS firewall; it can safely be removed.
# Why: When a host requests a new IP address lease, the DHCP server must use Raw Sockets.
# This is a low-level mode to bypass standard IP firewall hooks and send packets to clients
# that do not have an IP address yet. When Mikrotik DHCP server sends a reply, it builds the
# packet and sends it directly to the network interface driver. Because the DHCP server
# operates at a low-level for these specific packets, it isn't "untracking" anything. The
# DHCP traffic is already bypassing the connection tracker because it is a Raw Socket process.
# As a result the packet counter stays at zero, so this rule can be removed.
# DHCP Server (LAN) - router's own replies
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/ip firewall raw
add action=accept chain=output out-interface-list=LAN protocol=udp \
src-port=67 dst-port=68 comment="DHCP: [Router->LAN] Untrack router's own reply"
The next two rules capture all DHCP traffic on the WAN port (discovery/renewal from your ISP):
# DHCP Client (WAN) - router's own discovery and renewal requests
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/ip firewall raw
# (router 0.0.0.0 -> ISP 255.255.255.255) - IP discover
# (router x.x.x.x -> ISP a.b.c.d ) - IP renewal
add action=notrack chain=output out-interface-list=WAN protocol=udp \
src-port=68 dst-port=67 comment="DHCP: [Router->WAN] Untrack router's own DHCP discovery/renew requests"
# DHCP Client (WAN) - ISP reply
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
/ip firewall raw
# ( ISP a.b.c.d -> router 255.255.255.255) - ISP reply (discovery)
# ( ISP a.b.c.d -> router x.x.x.x) - ISP reply (renewal)
add action=notrack chain=prerouting in-interface-list=WAN protocol=udp \
src-port=67 dst-port=68 comment="DHCP: [WAN->Router] Untrack ISP reply"
And finally, I use a specific rule to explicitly accepts DHCP packets coming from LAN:
/ip firewall filter
add action=accept chain=input in-interface-list=LAN protocol=udp \
src-port=68 dst-port=67 comment="Accept local DHCP IP discovery/renew"
P.S.
Since in your case VLANs are not part of list=LAN, what you can add your VLANs to a list.
For example:
/interface list member
add list=ALL_LOCAL interface=vlan10_lan comment="workstations"
add list=ALL_LOCAL interface=vlan20_srv comment="servers"
add list=ALL_LOCAL interface=vlan30_iot comment="IoT devices"
add list=ALL_LOCAL interface=vlan50_guest comment="guests"
and then accept DHCP traffic from all your VLANs with this rule:
/ip firewall filter
add action=accept chain=input in-interface-list=ALL_LOCAL protocol=udp \\
src-port=68 dst-port=67 comment="Accept DHCP IP discovery/renew requests from all local subnets"