3

My home network diagram is simple as below:

internet --> Optical modem --> router --> pc1 ,pc2 111.111.111.111--> 192.168.1.1 -->192.168.31.1 --> 192.168.31.144,192.168.31.173 

The ISP provide a static ip ,supposing it's 111.111.111.111,optical modem's ip address is 192.168.1.1,router's ip address is 192.168.31.1, ip address for pc1 is 192.168.31.144 , ip address for pc2 is 192.168.31.173,the pc1's mac address is xx.xx.xx.xx.

The openwrt is running on my router,adding some port forwarding rules in the router and open firewall:

forwarding rule name protocl outer port inner IP address inner port wakeonwan UDP 9 192.168.31.144 9 ssh TCP and UDP 10000 192.168.31.1 22 

And bind the ip address and mac in openwrt:

ip address mac interface 192.168.31.144 xx.xx.xx.xx ?? 

Which interface to choose from the below options?

enter image description here

Login my router remotely:

ssh [email protected] -p 10000 

Issue wol command from the router:

/usr/bin/wol -i 192.168.31.255 xx.xx.xx.xx 

The pc1 can be waked on from the router!
Turn off pc1,wakeup it from pc2 with the following python code wakeonlan.py:

from wakeonlan import send_magic_packet send_magic_packet('xx.xx.xx.xx') 

Executing the command python3 wakeonlan.py in pc2 can wakeup my pc1 successfully.

Executing the command python3 wakeonwan.py remotely(for example--in my company's pc) can't wakeup my pc1.

cat wakeonwan.py mac = "xx.xx.xx.xx" target_ip = "111.111.111.111" from wakeonlan import send_magic_packet send_magic_packet(mac, ip_address=target_ip,port=9) 

It encounter no error,why pc1 can't wakeup with wakeonwan.py?
Let's do it with a lib--paramiko.

pip install paramiko 

Eidt wakeonwan-paramiko.py:

import paramiko from contextlib import contextmanager host = '111.111.111.111' username = 'root' password = 'password' ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(host, username=username, password=password,port=10000) stdin, stdout, stderr = ssh.exec_command("/usr/bin/wol -i 192.168.31.255 xx:xx:xx:xx") ssh.close() 

python3 wakeonwan-paramiko.py can wakeup my home pc from external network,i feel it is more simple to edit wakeonwan.py to wakeup pc remotely?
How to fix it?

4
  • Does this answer your question? Turn on my Ubuntu server remotely? Commented May 15, 2021 at 12:38
  • You need support from your (home) router. It's explained in the PyPI documentation of send_magic_packet. "The package needs to be sent as a broadcast package." [sic]. Commented May 15, 2021 at 12:45
  • Since netfilter doesn't like transformations involving broadcasts, and many home routers are Linux based, I guess this would be more suitable: unix.stackexchange.com/questions/77874/… (to be running on the home router). Commented May 15, 2021 at 12:53
  • If the router can't be running arbitrary programs, you can run socat from the linked answer on pc2 instead. If the router could be configured with a permanent ARP entry for pc1, then it's not needed: a port forwarded wol would work. Commented May 15, 2021 at 13:10

1 Answer 1

5

The tricky part in sending Wake-on-LAN packets in from beyond the local network is in getting the router send the packet out to the local network, so that the completely passive PC1 can receive it.

The magic packet is addressed to the router's external IP address, which makes it an unicast packet. The forwarding rule in the router specifies the target PC's own IP address as the inner IP address. So, per the standard procedure for forwarding unicast traffic, the router will first make an ARP request to find out the MAC address of the target PC... but gets no answer, because the target PC is powered off. A network interface that is waiting for wake-on-LAN packets is in a low-power receive-only mode: it will not typically be able to answer to ARP requests.

As the ARP request fails, the router might send back an ICMP error packet indicating "host unreachable"... but the Python wakeonlan module does not seem to have the facilities to process such an error response, even assuming the ICMP message does not get filtered out by paranoid firewalls on its way back.

The fact that the MAC address is embedded into the magic packet payload does not help, because the router does neither know nor care about that. For the router, the magic packet is just another TCP or UDP packet that will be processed just as usual.

You would have to configure the forwarding rule send the magic packet into the broadcast address of the internal network, in order to make it a broadcast. That way, the router will not need to make an ARP query before passing the packet into the inner network. So, if the netmask of your internal network is 255.255.255.0, then you should use 192.168.31.255 as the inner IP address in the forwarding rule.

But... as @A.B mentioned in the comments, Linux-based routers don't generally like transforming unicasts into broadcasts, so this approach might not work.

An alternative solution would be to add a static ARP table entry for the target PC into the router's ARP table, so it would not need to make the ARP query, but could just proceed into forwarding the packet to the inner network.

By quick source code inspection, the wakeonlan python module seems to use SOCK_DGRAM, which means it uses UDP. So you should be able to change the forwarding rule from "TCP and UDP" to "UDP only".

4
  • 1
    nitpicking, TCP would never work: sending the 102 bytes of the MagicPacket™ in the SYN appears difficult. Commented May 15, 2021 at 13:54
  • @A.B I have seen a WoL tool that claimed to use TCP. Probably it just built up a raw packet for WoL and just abused the Ethernet protocol identifier of TCP. Might have worked once upon a time, but yes, any modern firewall worth its price would probably reject it. Commented May 15, 2021 at 14:05
  • 1
    Also FWIW, I just discovered that unicast->broadcast is a routing restriction on Linux, not caused by netfilter (although netfilter can't handle correctly reply packets, but it doesn't matter for WOL). tested and it works when enabling the all and the ingress interface, according to this S/F answer: serverfault.com/questions/232582/… Commented May 15, 2021 at 14:25
  • I was almost going to write my own answer until I read your penultimate paragraph. Yes! Create a static ARP entry for the PC you want to wake, it's by far the cleanest solution. Some routers (eg: draytek) do this if you pin the IP. For OpenWRT there's a Q/A telling you how here. Commented May 21, 2021 at 21:24

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.