HomeNetwork/docs/shelly-dhcp-investigation.md
2026-04-17 14:08:19 +02:00

12 KiB

Shelly DHCP Investigation

Date: 2026-04-17

Update: the Kea reservation workaround was applied during this pass.

Scope

This document investigates why Shelly-Server is live at 192.168.100.127 even though OPNsense at 192.168.100.254 has a reservation for the device at 192.168.100.75 and is expected to be the only authoritative DHCP server on the LAN.

No destructive changes were made during this pass. All checks were read-only diagnostics.

Executive Summary

The strongest current evidence does not point to a confirmed rogue DHCP server.

It also does not support the idea that OPNsense is holding an old reservation for a replaced Shelly unit.

The stronger explanation is:

  1. Shelly-Server is configured for DHCP, not a static IP.
  2. The device is live and reports itself as 192.168.100.127.
  3. The firewall still has a static reservation for the device's factory MAC 34:94:54:73:E2:28 at 192.168.100.75.
  4. On the LAN, 192.168.100.127 resolves to a different MAC, 02:0F:B5:73:E2:28, not the Shelly factory MAC.
  5. That observed MAC is locally administered and preserves only the last three bytes of the Shelly MAC.

This strongly suggests an intermediate bridge/router/AP behavior that rewrites the client MAC on the wire. If that is true, OPNsense may still be the DHCP server, but the reservation on 34:94:54:73:E2:28 will never match because the DHCP server sees 02:0F:B5:73:E2:28 instead.

If you had replaced the Shelly and forgotten to update the reservation, the reservation MAC and the live device's own reported MAC would differ. In this case they match, so the reservation appears tied to the correct physical Shelly, just not to the effective MAC seen on the LAN.

Confirmed Facts

1. OPNsense LAN identity

  • LAN interface IP in OPNsense config: 192.168.100.254/24
  • The local Windows host on the same subnet has:
    • IPv4 address 192.168.100.134
    • default gateway 192.168.100.254
    • DHCP server 192.168.100.254
    • DNS server 192.168.100.254

This confirms that normal clients on the LAN are getting DHCP from the firewall.

2. Shelly device runtime state

Direct HTTP inspection of the live device at http://192.168.100.127/ returned:

  • device name Shelly-Server
  • device type SHEM / Shelly EM
  • factory MAC 34945473E228
  • Wi-Fi SSID Shellynet
  • IP 192.168.100.127
  • Wi-Fi mode ipv4_method: dhcp
  • MQTT connected true

This rules out a device-side static IP configuration.

3. OPNsense reservation and DNS state

OPNsense config contains a reservation for:

  • IP 192.168.100.75
  • MAC 34:94:54:73:e2:28
  • hostname Shelly-Server

The live Shelly web API reports the same factory MAC, 34:94:54:73:E2:28.

That means the reservation is mapped to the correct Shelly hardware identity.

Firewall DNS answers currently conflict:

  • Shelly-Server.maddo.science -> 192.168.100.75
  • shellyem-34945473E228.maddo.science -> 192.168.100.127
  • reverse lookup of 192.168.100.127 returns shellyem-34945473E228.maddo.science

That means the firewall has both:

  • a static name tied to the reserved IP
  • a learned live record tied to the current IP

4. Local ARP evidence

Known Shelly devices on the same subnet resolve normally to their vendor MACs:

  • 192.168.100.62 -> 24-4C-AB-41-87-35
  • 192.168.100.76 -> 24-4C-AB-41-6D-0C
  • 192.168.100.96 -> 34-94-54-78-06-1B

But the live Shelly-Server IP resolves as:

  • 192.168.100.127 -> 02-0F-B5-73-E2-28

The first octet 02 marks this as a locally administered MAC, not the Shelly factory OUI. The last three bytes 73-E2-28 match the device suffix.

That is the key anomaly in this investigation.

Interpretation

The observed facts fit this model best:

  1. Shelly-Server is connected through something on Shellynet that rewrites or virtualizes the client MAC on the LAN side.
  2. OPNsense may still be handing out the lease, but it is likely handing it to 02:0F:B5:73:E2:28, not to 34:94:54:73:E2:28.
  3. Because the reservation is keyed to the factory MAC, the reservation at 192.168.100.75 is bypassed.
  4. The device then receives a dynamic address inside the general pool, which explains 192.168.100.127.

So the most likely correction is not "replace the old reservation MAC with the new device MAC." The factory MAC already matches. The only MAC mismatch is between the factory MAC and the translated on-wire MAC observed for the live IP.

This explanation is more consistent with the evidence than a rogue DHCP server because:

  • the local host is using 192.168.100.254 as DHCP correctly
  • the firewall DNS has a live learned name for 192.168.100.127
  • the on-wire MAC for 192.168.100.127 does not match the reservation MAC

Alternative Explanation

A second DHCP server is still possible, but current evidence is weaker for that theory.

For a rogue DHCP explanation to fit all observations, one of these would also need to be true:

  • the firewall is somehow learning dynamic DNS records for a lease it did not issue
  • or the second DHCP domain is bridged into the LAN in a way that still produces the rewritten local MAC pattern

That is possible, but it is not the simplest explanation from the data collected so far.

Likely Root Causes

1. Wireless bridge or router mode on the Shellynet path

Examples:

  • Wi-Fi extender in router mode
  • client bridge with MAC NAT
  • WISP mode
  • AP/client isolation feature that synthesizes per-client LAN MACs
  • travel router or embedded bridge in front of the Shelly

2. Reservation keyed to the wrong effective MAC

If the DHCP server sees 02:0F:B5:73:E2:28 on the wire, a reservation for 34:94:54:73:E2:28 will never apply.

3. Stale naming and reservation state on the firewall

The static host entry for Shelly-Server.maddo.science still points to .75, while the firewall also knows a live dynamic name at .127. That split-brain state makes troubleshooting harder even if DHCP itself is still on the firewall.

What I Could Not Prove In This Pass

  • I did not directly read the active DHCP lease database from OPNsense because the available SSH wrapper restricted several generic shell commands.
  • I did not capture a DHCP exchange packet trace from the firewall.
  • I did not inspect the AP/controller behind Shellynet because that system is not exposed through the current toolset.

So the exact point where the MAC changes is still unverified.

Highest value checks

  1. Inspect the device or controller that provides Shellynet.

    • Determine whether it is a pure bridge, router, repeater, WISP client, or extender.
    • Look for features such as MAC NAT, proxy ARP, client isolation, wireless bridge translation, or MAC cloning.
  2. Check the live DHCP lease table on OPNsense for 192.168.100.127.

    • Confirm which MAC the firewall associates with that lease.
    • Check whether the hostname is shellyem-34945473E228.
  3. Run a packet capture during a DHCP renew from the Shelly.

    • Capture on the LAN side of the firewall for UDP 67/68.
    • Confirm whether the DHCP client identifier or source MAC is 34:94:54:73:E2:28 or 02:0F:B5:73:E2:28.

Good follow-up checks

  1. Search the AP client list for both MACs:

    • 34:94:54:73:E2:28
    • 02:0F:B5:73:E2:28
  2. Check whether any other Shelly devices on Shellynet show the same MAC translation pattern.

  3. Verify whether Shellynet is bridged directly onto 192.168.100.0/24 or routed/NATed by an intermediate device.

Proposed Fixes

Plain-English Explanation

The simplest reading of the evidence is this:

  • the Shelly itself is fine
  • OPNsense is probably still the DHCP server
  • the Shellynet extender is likely changing how the Shelly appears on the network
  • because of that, OPNsense does not match the Shelly to its reservation at 192.168.100.75
  • the Shelly then gets a normal dynamic IP instead, currently 192.168.100.127

So the real problem is probably not the Shelly and not Home Assistant.

The likely problem is the Wi-Fi extender path.

The best solution is to stop using the extender path for this Shelly if possible.

Preferred order:

  1. Move Shelly-Server onto a normal Wi-Fi network that is bridged directly to the main LAN.
  2. If that is not possible, reconfigure the extender so it behaves as a simple bridge or access point and does not rewrite client identity.
  3. Only if neither is possible, use a DHCP reservation for the effective MAC currently seen on the LAN as a workaround.

Best Fix

Move the Shelly off Shellynet and onto a normal SSID served directly by the main Wi-Fi infrastructure.

Why this is the best fix:

  • it should let OPNsense see the Shelly's real MAC again
  • it should make the existing reservation at 192.168.100.75 work normally
  • it removes the weird translation behavior from the network path
  • it is simpler and more robust than working around the extender behavior

After moving the Shelly to a normal SSID:

  1. reboot the Shelly or renew its network connection
  2. verify that it takes 192.168.100.75
  3. verify that Shelly-Server.maddo.science resolves correctly
  4. verify that Home Assistant still sees live MQTT updates

Good Workaround

If the extender must stay in place, use the MAC that the LAN is actually seeing for the live IP.

Current observed effective MAC:

  • 02:0F:B5:73:E2:28

That workaround would mean:

  1. update the OPNsense reservation to use 02:0F:B5:73:E2:28 instead of 34:94:54:73:E2:28
  2. keep the reserved IP as 192.168.100.75
  3. reconnect or reboot the Shelly
  4. verify whether it then gets 192.168.100.75

Current state after applying the workaround:

  • reservation IP: 192.168.100.75
  • reserved effective MAC: 02:0F:B5:73:E2:28
  • hostname: Shelly-Server
  • Kea description: Shelly-Server via Shellynet extender workaround; physical MAC 34:94:54:73:e2:28
  • firewall config backup created before change: /conf/config.xml.pre-shellynet-workaround-20260417

This workaround may succeed, but it has a risk:

  • if the extender changes that translated MAC later, the reservation will break again

What I Recommend You Actually Do

If you want the most reliable outcome with the least long-term confusion:

  1. first try to get Shelly-Server off Shellynet
  2. if that is not realistic, reserve 192.168.100.75 for 02:0F:B5:73:E2:28 as a workaround
  3. once it works, keep both MACs documented:
    • physical Shelly MAC: 34:94:54:73:E2:28
    • effective LAN-side MAC through extender: 02:0F:B5:73:E2:28

What Not To Do

  • do not assume the reservation is stale because of a replaced Shelly; the current Shelly reports the same physical MAC stored in OPNsense
  • do not delete historical information about the physical MAC; it is still the real hardware identity of the device
  • do not assume Home Assistant is the problem; it is working correctly because MQTT is working

Preferred fix

Remove the MAC-rewriting hop from the Shelly path.

That means:

  • put the Shelly on a normal bridged SSID
  • or reconfigure the Shellynet infrastructure so the original client MAC reaches the firewall unchanged

If the original MAC reaches OPNsense, the existing reservation at 192.168.100.75 should be able to work as intended.

Acceptable workaround

If the Shellynet path must stay as-is, create the reservation for the effective on-wire MAC actually seen by DHCP, after confirming it is stable.

Based on current evidence, that candidate MAC is:

  • 02:0F:B5:73:E2:28

This is only a workaround. If that translated MAC is generated dynamically by the bridge and can change, it is not a robust long-term fix.

It should not be documented as an "old Shelly MAC." It is better treated as an observed effective LAN-side MAC associated with the current path to Shelly-Server.

Cleanup after the root issue is fixed

  1. Align firewall DNS so there is only one canonical name/IP for this device.
  2. Remove or update stale static entries that still point Shelly-Server at .75 if the intended address changes.
  3. Re-test Home Assistant entity availability and direct web access after the network path is corrected.

Working Conclusion

The current evidence supports this working conclusion:

OPNsense at 192.168.100.254 is still likely the real DHCP authority, but Shelly-Server is probably not presenting its factory MAC to that DHCP server. Instead, something on the Shellynet path appears to be rewriting the MAC to 02:0F:B5:73:E2:28, causing the firewall to hand out a dynamic lease at 192.168.100.127 and bypass the reservation for 192.168.100.75.

That makes this look less like a rogue DHCP server problem and more like a MAC translation or bridging mode problem that breaks DHCP reservations.