nikp123 / wake-on-arp

An commandline daemon that wakes up a device on the local network when accessed
GNU General Public License v3.0
74 stars 4 forks source link

Does it solve the broadcast problem? #1

Closed Falcosc closed 3 years ago

Falcosc commented 3 years ago

Thank you for this project! Because my NIC does not support Wake on ARP, I did search how to monitor ARP with a low powered device and translate these ARP requests into Magic packages.

I have multiple questions:

  1. Is it possible to monitor ARP requests from other devices? (Are ARP requests broadcasted to any network device) Because it would be cool to install a single Raspberry Pi in a network which handles all the ARP to WOL translations.
  2. If you have a NIC with Wake on ARP support, you still have trouble with this feature because multicast broadcast could wake up your device even if it wasn't requested by another client. To solve this, you would need a switch with IGMP snooping. Does your solution avoid this issue? If not, could this package type field help to indicate the correct ARP request? https://github.com/nikp123/wake-on-arp/blob/d141c8673325bbe6530cdcd135d48722427663f8/src/main.c#L141-L143
  3. Is this tool designed to be installed on each client? Because this looks like the package was send from the executing host: https://github.com/nikp123/wake-on-arp/blob/d141c8673325bbe6530cdcd135d48722427663f8/src/main.c#L181
nikp123 commented 3 years ago
  1. I'm far from a professional on my topic but during my debugging it seems that ARP requests from other devices DO show up on the network, however I think the current implementation ignores them entirely in order to focus on the packets coming from the device itself (filtered by MAC address i believe). This is an easy change to make.
  2. I honestly was not aware of that, so I probably guess no (You'll need to describe this in further detail, apologies)
  3. Yes, the idea is that only authorized clients can wake up the target server. If you have any other ideas about how it should work, I'm probably not going to be against them. I've abandoned this concept due to it not scaling well with my use-case so I'm happy to try out something like that, where there's a single "manager" device (Raspberry Pi) which just wake other sleeping devices on demand.
Falcosc commented 3 years ago

I did read a bit about ARP, yes it is Broadcast. A central ARP to Magic Package translator device attached to the network should work. We only need to extend the source IP check from "allow my ip as source ip" to "allow other local source IPs" https://github.com/nikp123/wake-on-arp/blob/d141c8673325bbe6530cdcd135d48722427663f8/src/main.c#L181

For my use case I would only check the first 3 blocks of the IP Address, because of my 255.255.255.0 subnet. But I am not sure if the router IP needs to be excluded because most routers communicate with all clients for monitoring reasons.

nikp123 commented 3 years ago

possibly add a subnet = 24 then in the code !memcmp(m.eth_ip, sa, subnet/8)

nikp123 commented 3 years ago

actually let me do that right now, its not a bad idea

Falcosc commented 3 years ago

Thank you, but don't forget to extend the example config. That's the reason why I could not create a pull request by myself.

By the way, where will the logs be placed? I don't know Linux well enough to know where the console outputs are written to.

I will check if small networks have the mentioned broadcast issue. So in long term we need a log for each magic package creation with time and source IP. Maybe protocol as well if you are not sure because of TODO: Research packet types for ARP

For deeper checks, I can just use a sniffing tool, but for trouble like "why did the server wake up at 4 AM?" I would need to know about where the log output is places. Maybe a word about the log would be great in the readme because unexpected ARP wakeups are very common. Would be nice if you could extend your logging to cover this. Thank you

nikp123 commented 3 years ago

The logs are written to stdout for now. No log file support. Although you can just redirect the output in your shell to achieve the same thing or just use systemd's built in logging feature.

nikp123 commented 3 years ago

For deeper checks, I can just use a sniffing tool, but for trouble like "why did the server wake up at 4 AM?" I would need to know about where the log output is places. Maybe a word about the log would be great in the readme because unexpected ARP wakeups are very common. Would be nice if you could extend your logging to cover this.

Regarding this, I could implement a way to show which device requested the wakeup.

Falcosc commented 3 years ago

So, your tool is started by systemd, maybe mention this if you want to tell the users how to monitor the outputs. I guess on most linux distros you can check the magic package delivery reason with journalctl?

Would be nice if you could add the magic package delivery reason in your output. Maybe it should be standard output and not hidden behind the DEBUG build, because this is very essential? Or do you expect to many ARP requests/minute? I didn't fire up a sniffer yet, but if there are ARPs for each connection establishment, then this tool may need a delay.

I would just put the tool to sleep for a configured number of seconds after each magic package delivery to reduce the CPU load.

nikp123 commented 3 years ago

Yeah, you're right. I put that behind a DEBUG builtd because the log messages can get pretty heavy, although I can see that they're essential in debugging broadcast issues.

nikp123 commented 3 years ago

" I didn't fire up a sniffer yet, but if there are ARPs for each connection establishment, then this tool may need a delay." I actually was thinking about this when I initially wrote this.

Falcosc commented 3 years ago

We are talking about embedded devices with sub 500mW peak power consumption, so this could be very usefull.

I plan to run it on a Raspberry PI 1

Falcosc commented 3 years ago

Yeah, you're right. I put that behind a DEBUG builtd because the log messages can get pretty heavy, although I can see that they're essential in debugging broadcast issues.

Ok, that's a good argument, logging should only be used in combination with a delay.

Falcosc commented 3 years ago

Currently I monitor SMBClient connection errors on each windows client via the event monitoring. This is good enogh for me, but in the unraid community there are many people looking for ARP wake up. And even more people which are using a plugin to conditional put the server to sleep, who have trouble with wake up and don't even know about ARP.

The benefits of your project is that it can be extended to be much more then a simple ARP to magic package translator, to handle alot of wake on ARP issues.

nikp123 commented 3 years ago

for some reason this doesn't work on my machine

maybe the networks changed or i forgot how to use this thing :confused:

ps: somethings broken

update: going afk

Falcosc commented 3 years ago

Yes, we need a source IP filter. My router does send ARPs from time to time without any reason.

If you prefer a solution without complex parameters, on simple networks it would be enough to allow all source IPs from the current subnet but exclude the gateway.

Edit: Something made my router really upset, it is really trying to find the missing host by sending ARP requests for the affected target IP every 3-5 minutes. Now I understand the issue mentioned in https://forums.unraid.net/topic/6455-how-to-wake-on-arp-unraid-also-wake-from-pch-c-200-apple-pcs-etc/?tab=comments#comment-64062

So yes, after excluding the gateway IP, your project should solve the main wake-on-ARP issue.

nikp123 commented 3 years ago

dont ask why it took over 3 hours

Falcosc commented 3 years ago

I don't regret being on the lazy side of the git issue conversation after seeing get_gateway_ip.c Thank you, my sub 1 watt Raspberry Pi 1 should arrive the day after tomorrow.

There is even a suspicious smiley face in the get gateway ipv4 comment, like you would never underestimate such a "simple" task ;)

nikp123 commented 3 years ago

also this monstrosity

Falcosc commented 3 years ago

This method is incomplete. The question about what is true and what is false has to be answered with philosophy in mind. 😋

Falcosc commented 3 years ago

@nikp123 something is wrong with your data parsing. source ip and target ip is random, it changes after each run but is always the same during execution. And of course, it isn't an ip of my network.

src and target address are borked.

    if(type == NS_ARP_REQUEST) {
        // if source matches to host
        // and if target matches send magic
        unsigned int eth_ip = *((unsigned int*)&m.eth_ip);
        unsigned int src_ip = *((unsigned int*)&sa);
        unsigned int gateway_ip = *((unsigned int*)&m.gate_ip);
        unsigned int ta_ip = *((unsigned int*)&ta);

        printf("ARP2 send By '");
        print_ip(src_ip);
        puts("'");
        printf("ARP to '");
        print_ip(ta_ip);
        puts("'");

But eth and gateway ip are correct. Which means there is an issue in the ARP package parsing.

Falcosc commented 3 years ago

Here is an ARP from 192.168.1.112 to 192.168.1.70

ff ff ff ff ff ff XX XX XX XX XX XX 08 06 00 01 08 00 06 04 00 01 XX XX XX XX XX XX c0 a8 01 70 00 00 00 00 00 00 c0 a8 01 46 '
ARP send By '116.142.131.1'
ARP to '126.142.131.1'

I have replaced my mac with XX to make it more obvious where the ip is stored

Src should be c0 a8 01 70 Target should be c0 a8 01 46

As it turns out, your parsing is correct. But this is broken:

unsigned int src_ip = *((unsigned int*)&sa);

It turns c0 a8 01 70 into random data, I bet you got the pointer address instead of the data in that call.