Noobie needs help with IoT network DHCP

I'm trying to set up a wireless IoT network isolated from both lan and internet (I plan to selectively allow specific devices/ports internet access as needed). So far it seems that everything is working except for DHCP. I am able to connect to the wireless network if I set a static IP, but not when the device is configured to use DHCP. Please help!

Based on other forum posts, I ran the following commands and included the output here (with pw and public IP's replaced with "<REDACTED>":

bus call system board;
uci export network;
uci export wireless;
uci export dhcp; uci export firewall;
head -n -0 /etc/firewall.user;
iptables-save -c;
ip -4 addr ; ip -4 ro li tab all ; ip -4 ru;
ls -l /etc/resolv.* /tmp/resolv.* /tmp/resolv.*/* ; head -n -0 /etc/resolv.* /tmp/resolv.* /tmp/resolv.*/*

Output:

root@OpenWrt:~# ubus call system board;
; uci export firewall;
head -n -0 /etc/firewall.user;
iptables-save -c;
ip -4 addr ; ip -4 ro li tab all ; ip -4 ru;
ls -l /etc/resolv.* /tmp/resolv.* /tmp/reso{
        "kernel": "6.6.119",
        "hostname": "OpenWrt",
        "system": "ARMv8 Processor rev 4",
        "model": "GL.iNet GL-MT6000",
        "board_name": "glinet,gl-mt6000",
        "rootfs_type": "squashfs",
        "release": {
                "distribution": "OpenWrt",
                "version": "24.10.5",
                "revision": "r29087-d9c5716d1d",
                "target": "mediatek/filogic",
                "description": "OpenWrt 24.10.5 r29087-d9c5716d1d",
                "builddate": "1766005702"
        }
lv./ ; head -n -}
0 /etc/resolv.* /tmp/resolv.* /troot@OpenWrt:~# uci export network;
package 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 ula_prefix 'fdd2:6a0c:63e1::/48'
        option packet_steering '1'

config device
        option name 'br-lan'
        option type 'bridge'
        list ports 'lan1'
        list ports 'lan2'
        list ports 'lan3'
        list ports 'lan4'
        list ports 'lan5'

config interface 'lan'
        option device 'br-lan'
        option proto 'static'
        option ipaddr '192.168.8.1'
        option netmask '255.255.255.0'
        option ip6assign '60'

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

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

config interface 'iot'
        option proto 'static'
        option ipaddr '10.10.3.1'
        option netmask '255.255.255.0'
        option device 'br-iot'

config device
        option type 'bridge'
        option name 'br-iot'
        option bridge_empty '1'

root@OpenWrt:~# uci export wireless;
package wireless

config wifi-device 'radio0'
        option type 'mac80211'
        option path 'platform/soc/18000000.wifi'
        option band '2g'
        option channel '1'
        option htmode 'HE20'
        option cell_density '0'

config wifi-iface 'default_radio0'
        option device 'radio0'
        option network 'lan'
        option mode 'ap'
        option ssid 'FernGully'
        option encryption 'sae-mixed'
        option key '<REDACTED>'
        option ocv '0'

config wifi-device 'radio1'
        option type 'mac80211'
        option path 'platform/soc/18000000.wifi+1'
        option band '5g'
        option channel '36'
        option htmode 'HE80'
        option cell_density '0'

config wifi-iface 'default_radio1'
        option device 'radio1'
        option network 'lan'
        option mode 'ap'
        option ssid 'FernGully_5GHz'
        option encryption 'sae-mixed'
        option key '<REDACTED>'
        option ocv '0'

config wifi-iface 'wifinet2'
        option device 'radio0'
        option mode 'ap'
        option ssid 'CrocodileCanyon'
        option encryption 'sae-mixed'
        option isolate '1'
        option key '<REDACTED>'
        option ocv '0'
        option network 'iot'

root@OpenWrt:~# uci export dhcp; uci export firewall;
package dhcp

config dnsmasq
        option domainneeded '1'
        option boguspriv '1'
        option filterwin2k '0'
        option localise_queries '1'
        option rebind_protection '1'
        option rebind_localhost '1'
        option local '/lan/'
        option domain 'lan'
        option expandhosts '1'
        option nonegcache '0'
        option cachesize '1000'
        option authoritative '1'
        option readethers '1'
        option leasefile '/tmp/dhcp.leases'
        option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
        option nonwildcard '1'
        option localservice '1'
        option ednspacket_max '1232'
        option filter_aaaa '0'
        option filter_a '0'

config dhcp 'lan'
        option interface 'lan'
        option start '100'
        option limit '150'
        option leasetime '12h'
        option dhcpv4 'server'
        option dhcpv6 'server'
        option ra 'server'
        list ra_flags 'managed-config'
        list ra_flags 'other-config'

config dhcp 'wan'
        option interface 'wan'
        option ignore '1'

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

config dhcp 'iot'
        option interface 'iot'
        option start '100'
        option limit '150'
        option leasetime '12h'

package firewall

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

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

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

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 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 zone
        option name 'iot'
        option input 'ACCEPT'
        option output 'REJECT'
        option forward 'REJECT'
        list network 'iot'

config forwarding
        option src 'lan'
        option dest 'iot'

config rule
        option src 'iot'
        option name 'IoT DHCP'
        list proto 'udp'
        option dest_port '67 68'
        option target 'ACCEPT'

config rule
        option src 'iot'
        option name 'IoT DNS'
        option dest_port '53'
        option target 'ACCEPT'

root@OpenWrt:~# head -n -0 /etc/firewall.user;
head: /etc/firewall.user: No such file or directory
root@OpenWrt:~# iptables-save -c;
-ash: iptables-save: not found
root@OpenWrt:~# ip -4 addr ; ip -4 ro li tab all ; ip -4 ru;
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
    inet <REDACTED>/22 brd <REDACTED> scope global eth1
       valid_lft forever preferred_lft forever
9: br-iot: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
    inet 10.10.3.1/24 brd 10.10.3.255 scope global br-iot
       valid_lft forever preferred_lft forever
10: br-lan: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
    inet 192.168.8.1/24 brd 192.168.8.255 scope global br-lan
       valid_lft forever preferred_lft forever
default via 71.86.180.1 dev eth1  src <REDACTED>
10.10.3.0/24 dev br-iot scope link  src 10.10.3.1
<REDACTED>/22 dev eth1 scope link  src <REDACTED>
192.168.8.0/24 dev br-lan scope link  src 192.168.8.1
local 10.10.3.1 dev br-iot table local scope host  src 10.10.3.1
broadcast 10.10.3.255 dev br-iot table local scope link  src 10.10.3.1
local <REDACTED> dev eth1 table local scope host  src <REDACTED>
broadcast <REDACTED> dev eth1 table local scope link  src <REDACTED>
local 127.0.0.0/8 dev lo table local scope host  src 127.0.0.1
local 127.0.0.1 dev lo table local scope host  src 127.0.0.1
broadcast 127.255.255.255 dev lo table local scope link  src 127.0.0.1
local 192.168.8.1 dev br-lan table local scope host  src 192.168.8.1
broadcast 192.168.8.255 dev br-lan table local scope link  src 192.168.8.1
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default
root@OpenWrt:~# ls -l /etc/resolv.* /tmp/resolv.* /tmp/resolv./ ; head -n -0 /etc/resolv.* /tmp/resolv.* /tmp/resolv./
ls: /tmp/resolv./: No such file or directory
lrwxrwxrwx    1 root     root            16 Dec 17 21:08 /etc/resolv.conf -> /tmp/resolv.conf
-rw-r--r--    1 root     root            47 Jan  6 22:12 /tmp/resolv.conf

/tmp/resolv.conf.d:
-rw-r--r--    1 root     root           247 Jan  6 22:12 resolv.conf.auto
==> /etc/resolv.conf <==
search lan
nameserver 127.0.0.1
nameserver ::1

==> /tmp/resolv.conf <==
search lan
nameserver 127.0.0.1
nameserver ::1

==> /tmp/resolv.conf.d <==
head: /tmp/resolv.conf.d: I/O error
head: /tmp/resolv./: No such file or directory

You can try removing the lines I selected and replacing them with this:

config rule 'iot_dns_dhcp_ntp'
        option name 'Allow-dns-dhcp-ntp-Iot'
        option src 'iot'
        option dest_port '53 67 123'
        option limit '50/sec'
        option proto 'tcp udp'
        option target 'ACCEPT'
        option family 'ipv4'
1 Like

and these settings to replace:

onfig zone
        option name 'iot'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        list network 'iot'

2 Likes

changing the zone output to "accept" fixed it! maybe I need to do a little research to get a better understanding of why though. Shouldn't the "IoT DCHP" traffic rule have overridden this setting?

No. The rule you created to allow DHCP covers input (i.e. from the zone/network into the firewall/device). But the output rule is what governs the ability for the firewall to send packets out to the zone/network. With that set to REJECT it was essentially able to hear the request (per your DHCP rule) but it couldn't respond.

1 Like

ah I see. So an alternative could be to add an additional traffic rule like this:?

config rule
        option dest 'iot'
        list proto 'udp'
        option src_port '67 68'
        option target 'ACCEPT'
        option name 'IoT DHCP (from router)'

Yeah, that might work.

But there is rarely a reason to set output to anything other than ACCEPT insofar as it is the firewall (which is trusted) allowing (approved) traffic to egress to the zone.

2 Likes