Skip to content

Trying to get 'kasa discovery' to work across subnets -- both from the CLI and in Home Assistant TP-Link Integration #1431

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
puterboy opened this issue Jan 7, 2025 · 8 comments · Fixed by #1437

Comments

@puterboy
Copy link

puterboy commented Jan 7, 2025

I have my home server as well as my HA device on my primary 192.168.1.x network.
My kasa devices are on my IOT 192.168.100.x subnet.

I would would like to discover the Kasa devices on the IOT subnet (br1, vlan3) from my primary 192.168.1.x subnet (br0) -- whether via HA or via the CLI kasa discover

In the HA TP-Link integration, I can manually discover individual devices across subnets if I give the host IP -- but not if I leave the host blank and seek to "auto-discover".

Similarly, direct host addressing using CLI kasa --target 192.168.100.144 discover works (where 192.168.100.144 is a Kasa device on my IOT network). Though strangely kasa --host 192.168.100.144 discover returns after a second but without any discovery data suggesting that it connects but somehow returns no data.

In contrast, "auto discovery" using kasa discover' or even 'kasa --target 192.168.100.255 times out after ten seconds, returning:

Discovering devices on 192.168.100.255 for 10 seconds
Found 0 devices

I assume that the problem is that "auto" discovery is using broadcast (255.255.255.255) on ports 9999 and 20002 -- but of course broadcast messages are not forwarded across subnets, i.e, from 192.168.1.x (br0) to 192.168.100.x (br1) whereas specifying a specific host IP just sends the discovery packet directly to the host IP address on ports 9999 and 2002.

Indeed tcpdump confirms the broadcast originating on br0:

# tcpdump  -i br0 \( udp port 9999 or \udp port 20002 \)
...
11:34:02.081514 IP homeassistant.mydomain.35965 > 255.255.255.255.9999: UDP, length 29
11:34:02.081539 IP homeassistant.mydomain.35965 > 255.255.255.255.20002: UDP, length 501
11:34:03.749051 IP homeassistant.mydomain.35965 > 255.255.255.255.9999: UDP, length 29
11:34:03.749076 IP homeassistant.mydomain.35965 > 255.255.255.255.20002: UDP, length 501
11:34:05.416139 IP homeassistant.mydomain.35965 > 255.255.255.255.9999: UDP, length 29
11:34:05.416165 IP homeassistant.mydomain.35965 > 255.255.255.255.20002: UDP, length 501

but tcpdump -i br1 \( udp port 9999 or \udp port 20002 \) doesn't show any traffic.

So to summarize, my questions are:

  1. Why does kasa --target 192.168.100.144 discover succeed while, kasa --host 192.168.100.144 discover fails?
  2. Is there any way to get kasa --target 192.168.100.255 discover working where the target is on a different subnet?
  3. More generally, how can I get auto-discovery (without specifying the host IP) to work across subnets -- both in the CLI and in the HA TP-Link integration?
    This is particularly important to me in HA since I would rather not have to type in each IP individually - plus presumably the IP address can change.

Note I am using version python-kasa-0.8.1

@puterboy
Copy link
Author

puterboy commented Jan 7, 2025

Note for both kasa --target 192.168.100.144 discover and kasa --host 192.168.100.144 discover, tcpdump seems to show that the message is received by the Kasa device on br1 and that it responds: e.g.,

# tcpdump  -i br1 \( udp port 9999 or \udp port 20002 \)
...
13:21:38.615129 IP myserver.mydomain.43297 > 192.168.100.144.9999: UDP, length 29
13:21:38.615654 IP myserver.mydomain.43297 > 192.168.100.144.20002: UDP, length 501
13:21:38.640749 IP 192.168.100.144.20002 > myserver.mydomain.43297: UDP, length 422

But again '--hostdoesn't return any data while--target` does.

@sdb9696
Copy link
Collaborator

sdb9696 commented Jan 7, 2025

  1. The target parameter with a full ip specified effectively send the packet direct to the device avoiding the issues with multicast across subnets. kasa --host 192.168.100.144 discover failing appears to be a bug that I will take a look at.
  2. I don't believe so, the multicast packets don't cross the subnets afaia.
  3. Are you able to assign another nic with the address of the other subnet to the HA device? I believe that would be the only way.

@puterboy
Copy link
Author

puterboy commented Jan 7, 2025

Just to make sure I am following as I am a newbie here, I assume you mean broadcast as 192.168.x.255 and 255.255.255.255 are broadcast addresses, not multicast.
If it were multicast, it would be easier to forward :) as broadcast can't be forwarded without special relays -- and I am beyond my scope there...

Regarding #3, my HA device is a RPi for now so only one nic :(

Also, one related question...
If I am manually assigning hosts by IP in the HA integration, what happens if the kasa device is offline for a while and then is assigned another IP when it comes up again? It would seem that the HA integration would not be able to find it again without "auto" discovery which won't work across subnets, right? Or can it find it again via mdns?
If not, is it important to use static dhcp to assign a fixed ip address based on the kasa device MAC?

@sdb9696
Copy link
Collaborator

sdb9696 commented Jan 8, 2025

Yes apologies I meant broadcast.

The HA tplink integration handles ip changes via 20002/9999 discovery and dhcp discovery. Both of these won't work across subnets by default, so unless you're able to setup some sort of relay 😬 assigning static ips or perhaps using dns names is the way to go.

@puterboy
Copy link
Author

puterboy commented Jan 8, 2025

It's a shame that there is no good solution for discovery across subnets as it is increasingly common and recommended to run your IoT devices on a separate subnet given that so many devices are made in China, require cloud access, and have dubious security and/or privacy guarantees. At the same HA is "trusted" and should run on your primary network so it has access to necessary resources.

In particular, I wish there were simpler ways to selectively relay broadcast messages across subnets -- but at least with my dd-wrt router, it seems like standard iptables rules don't work for broadcast.

@puterboy
Copy link
Author

puterboy commented Feb 13, 2025

OK, I finally go it to work by compiling and installing udp-broadcast-relay on my dd-wrt router.
I then ran:

udp-broadcast-relay -f 1 9999 br1 br0
udp-broadcast-relay -f 2 20002 br1 br0

And added the following iptables rules on the router:

iptables -I FORWARD -d myserver.mydomain -i br1 -p udp -m udp --sport 9999 -j ACCEPT
iptables -I FORWARD -d myserver.mydomain -i br1 -p udp -m udp --sport 20002 -j ACCEPT

Note: where:

  • myserver.mydomain is the machine and br0 is the network bridge where I am running kasa discover (or if using homeassistant, substitute the name or ip address of your homeassistant installation, typically homeassistant)
  • br1 is the IoT network bridge where my kasa devices are installed

Note that udp-broadcast-relay is a small, easy to compile program. I just had to run 'make' to get it to compile under dd-wrt (where I have gcc installed via entware)

@puterboy
Copy link
Author

@rytilahti if you want, you might want to add or reference this solution to the "bug report" that I filed but is now closed under homeassistant/core so I can't add to it. TP-LINK: Can't auto-discover devices on a separate IOT subnet #132654

I also added the solution to the parallel community discussion Auto-Discovery for TP-Link/Kasa devices on separate IOT network

@rytilahti
Copy link
Member

@puterboy glad that you got it working for your setup. I added a brief comment to link the issues 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants