← Projects

Awaken Wake-on-LAN Controller

Android app to turn my computers on from home and off from anywhere. Wake-on-LAN to wake them, SSH to shut them down and ICMP ping to know when they're online.

Stack
Android · Java · Kotlin · SQLCipher · SSH
Status
Completed
Year
2026
ymid@ubuntu:~$ uptime up 0 min, 1 user ymid@ubuntu:~$ ▍ shutting down… router · 192.168.1.1 ubuntu · 192.168.1.12 ethernet awaken MAGIC PACKET → UDP :9 FF FF FF FF FF FF + ••:••:••:••:••:4F ×16 SSH :22 · ymid@ubuntu sudo shutdown -h now ICMP ECHO reply · 20 ms 00:55 Devices HOME Ubuntu ••:••:••:••:••:4F OfflineOnline · 20 ms Turn… Shut… Magic packet sent AWAKEN · now Ubuntu is online Confirm it’s you Shut down Ubuntu Touch the fingerprint sensor
  1. 01 Wake Magic packet · UDP 9
  2. 02 Detect ICMP ping
  3. 03 Shut down Biometrics · SSH

A room at night. The PC is off.

Waking is easy, shutting down isn't

Awaken started because I wanted to turn on my home PC from my phone. Wake-on-LAN does that with a single UDP packet, but it can only wake a machine: there is no magic packet to turn one off. To close the loop I needed a second channel, one that could get into the machine and run a command.

The answer was SSH. Awaken logs into the machine with a password or private key and runs the shutdown command you set for each one, for example sudo shutdown -h now. For now, shutdown works on Linux machines.

Wake at home, shut down from anywhere

The hardest part was the difference between being at home and being away. On the local network everything is direct: the magic packet goes out as a broadcast and SSH goes to the PC's local IP. From the internet, the router blocks that traffic, and opening the SSH port to the world wasn't an option.

To shut down from outside, I opened a single port on the router, for a WireGuard VPN running on the PC itself, and the machine's firewall only lets in what's needed. The phone joins the VPN and Awaken talks to the PC as if it were at home. SSH is never exposed to the internet: it's only reachable from the local network or through the tunnel.

Waking from outside is a different problem: with the PC off, the VPN doesn't exist either, so the magic packet would need another open path into the network. I researched up to that point and decided to stop there. Waking only from the local network is safer and covers real use: what I actually need is to shut the PC down if I leave in a hurry and forget.

Knowing which network you're on

One of the bugs that took me longest was getting the app to recognize which Wi-Fi network the phone was on. Android doesn't make it easy: reading the network name or scanning the ones around you depends on permissions, location above all, and without them the system just tells you nothing. I needed it for trusted networks: on the home Wi-Fi, shutting a machine down doesn't ask for a fingerprint; on any other network, it does.

Credentials that can't leak

To shut down over SSH, Awaken stores each machine's username and password or private key. That's enough to get into a machine. My first version didn't protect them the way it should have: I caught it in an AI-assisted review and moved the local database to SQLCipher, which encrypts it on disk. The database key is generated at random on first launch and kept with the Android Keystore, never in the code.

On top of that, the first time Awaken connects to a machine it stores the fingerprint of its SSH host key. If the fingerprint changes on a later connection, it refuses to connect instead of sending the password to a machine that might not be yours. And any destructive action, like shutting down, asks for a fingerprint or PIN.

Everything else

  • Background monitoring with real ICMP ping, no root, over an unprivileged ICMP socket: it notifies you when a machine comes online or goes offline, even with the app closed.
  • Access without opening the app: Quick Settings tiles, a widget, shortcuts and Device Controls.
  • Voice commands with Google Assistant, through wakeonlan:// deep links.
  • Monitoring can be switched off remotely with Firebase Remote Config if it drains too much battery, without shipping an update.
  • Export and import the device list as JSON.

On a real device

The same sequence, recorded on the phone.