I've been trying to get Bonjour Sleep Proxy working off and on for a long time. I'm starting to collect some details to help me when I'm back "on" again.Also, I tried using ether-wake which is pre-installed on my RT-N66U router that has asuswrt-merlin firmware installed on it. I believe, but I am not positive, that this also uses plain ethernet with 0x0842 since it doesn't request an IP address that UDP needs. I was unable to wake the iMac with this tool from router. I was able to wake it using the wol tool pre-installed which uses UDP packets. This means I can at least wake up my Macs using the router's WOL web page since that is the tool it uses on backend
Apple refers to the basic feature with widely different names but usually mean the same thing. I use the 4 names interchangeable on this page.
A good starting point is to make sure you can remotely wake up your machine using magic packets. I initially tried this with OS X 10.6; which is a good thing as I may have been misled by 10.8's (mis)behavior.
I tried a few tools to remotely wake the computer by sending a Magic Packet. I had most success with tools that used UDP packets directed to Port 9.
My iMac is new enough that Wifi reports it supports Wake on Demand; as described by this Apple page. So I tested this by connecting to my local network using Wifi and disconnecting my Ethernet cable. Then I ran
From another computer, I used some standard WOL tools to send the magic packet. After a few seconds, I'd try to ssh to my iMac. First try rarely woke up the computer. It appears the wifi chip sleeps deep enough that it misses a lot of packets. So I sent maybe 10 magic packets in a row and my computer would reliable wake up and I could ssh to it.
Next, I disabled Wifi and reconnected the Ethernet cable and repeated the test. I could reliably wake up my iMac with only 1 magic packet sent.
One other random note. I used the following python script from a Linux box to send a custom Ethernet frame (non-IP) using Ethertype 0x0842 packet since thats what Bonjour Sleep Proxy's send. I was able to reliably wake up the iMac over ethernet but I've not tested Wifi. This script only works on Linux as far as I know because it needs AF_PACKET.
I upgraded from 10.6 to 10.8 and discovered that magic packets seemed to stop working. After some googling, this seems a common problem for people starting with 10.7.
I would send the magic packet and couldn't ssh into my box. If I manually woke up the computer, I could tell that it was actually being woken up but just didn't seem to be initializing the network stack and/or allowing ssh to accept connections. I could tell it was woken up from syslog and timestamps:
Since Wake on Demand over Wifi is treated as an aftertought in the OS, the message during that wake usually says
The issue seems to be related to the Power Nap feature but internally it seems to be called Dark Wake alot. I'm not totally sure why Apple didn't think to have Wake on Demand fully bring up networking but perhaps one day they will fix that. In mean time, you can disable the Dark Wake/Power Nap feature which doesn't change the way the box sleeps but simply how far awake it becomes.
Dark Wake is built into the kernel and you can modify its behavior with options passed to the kernel during bootup. In the kernel shipped with 10.7, a darkwake flag was introduced. It is a bit mask that was initialized to a value of 3. You can see sample code from the open sourced kernel around that timeframe:The common work around for 10.7 users is to edit
After a reboot, waking from magic packets should work same as it was in 10.6.
In 10.8 kernel, the default value for the bitmask changed to 11 (0xb). You can also see this from open source kernel around that timeframe:
I don't know exactly what the new 0x08 does *but* if you clear that bit with darkwake=0 then although the computer will again wake from magic packets like in 10.6, it will no longer go to sleep on its own. Clearing bits 1 and 2 (0x3); like in 10.7 fix; but leaving the new bit 5 (0x8) still set seems to get the desired behavior.
So now I have 10.8 back to where I can manually wake it up.
Somewhere along this 10.6 to 10.8 time frame I got an Apple TV and learned that this device can perform the role of a Bonjour Sleep Proxy Server. So I began to see if I could get that working but haven't had much success.
First step was to learn which Apple products can support Sleep Proxy on client side. I found that the feature is controlled by mDNSResponder daemon. You can run this command to have it dump out some needed info to /var/log/system.log:
Look for section at very end that lists Network Interfaces:
The interesting part are the symbols. If you see a sun, as above, it says that this Network Interface supports Wake on Demand and that its detected a Sleep Proxy on your network. If its a sun but with clear center then it means this Network Interface supports Wake on Demand but no Sleep Proxy was seen on network. If there is no sun symbol then it means mDNSResponder thinks your interface does not support Wake on Demand.
I've found that all Wifi interfaces claim Wake on Demand is not supported inside mDNSResponder; regardless of what your System Information window says or the fact that Apple swears it works on Wifi. I've checked on an iMac and a Macbook Air.
I also found enabling addition logging from mDNSResponder is helpful in pinpointing where things are going wrong:
Perform a forced sleep and then after waking up, search for the phrase WOMP (Wake on Magic Packet).
If it thinks its not supported then it will say "no WOMP".
If your motivated enough, it is the NetWakeInterface() function that (mis)detects if the interface supports WOMP (Wake on Magic Packet). You could hack it to see if this is "en0" or "en1" and force to supports regardless of kernel flags. The following is piece of code that needs modification:
Take care to not say ever device supports it.
That change alone is probably not enough since; as stated above; waking from Wifi usually takes several packet sends but it looks like Sleep Proxy Servers only send 2 packets. It would be difficult to fix your Apple TV or Airport. If you have an Apple computer you always leave running, you can tell it to support being a Sleep Proxy Server and hack up SendWakeup() to send multiple times.
For now, I'm sticking with my Ethernet port and disabling my Wifi ports.
Some newer Mac's support a mini-Sleep Proxy in the NIC so the computer doesn't need to wake up to refresh th advertised services. If you enable above -USR1 logging option and sleep, you can grep for this support:
The above says my computer does not have that support in the NIC and it will communicate to Sleep Proxy Server on its own. If that line instead said "using local proxy" then mDNSResponder will not be involved in maintaining the advertised services.
I mention this mostly in case I get a newer computer some day and see unexpected packets sent that do not match up with syslog. Also, if you try to fix the Wifi not support WOMP, be sure and read up on "-UseInternalSleepProxy 0" option to mDNSResponder to disable use of NIC proxy.
Now on the ssh, run
If life is good, you can ssh back to Mac to sleep, the Sleep Proxy Server should send some magic packets, and it should wake up and complete ssh connection.
Seeing this arp table helps you understand how the Sleep Proxy Server has a hook to know when to wake up your Mac. Since arp caches are cleared over time (usually 60 minutes) then it might also give some clues to why the sleep proxy behavior changes over time.
To debug problems with a Sleep Proxy Server, its helpful to understand how they work. A Sleep Proxy Server must advertise a _sleep-proxy._udp service. You can detect this with the dns-sd command and Sleep Proxy Clients perform the same query right before going to sleep:
The client will also need to know the Name and Port the Sleep Proxy Server is listening on for this service:
Before the client goes to sleep, it must register with the server. It does this by sending a unicast Dynamic DNS Update which contains at a minimum a list of the TCP services (using SRV and TXT records) that should cause the computer to wake up, a Dynamic DNS Update Lease OPT record and a EDNS0 Owner OPT record directly to the server name and port from previous query.
The Dynamic DNS Update Lease OPT record seems to be the main trigger to cause the server to proxy for the client. It contains a Time To Live value that the client must wake up and re-register with server before the server disables the proxy feature. The EDNS0 Owner OPT record contain the client's MAC address to send in magic packet. The SRV records are used as a list for port to monitor for TCP SYN messages; all other ports are ignored. Each SRV record contains its own Time To Live value but its not clear to me if the the server will stop listening when they expire or use the OPT records TTL. Once all services expire, the server will also stop responding to ARP requests for the client; effectively ending its proxy roll until the client re-registers.
Once a client sends this packet, the server will send out a gratuitous ARP packet with its own MAC address to clear out machine's ARP caches. It will also begin to respond to ARP requests for client's IP address with its own MAC address; as long as one or more services still haven't timed out. An ARP request alone will not cause a request to wake up the client.
If someone attempts to establish a TCP connect to one of the services, the packet will be sent to server because of the ARP response. The server will detect this and send out a magic packet to wake the client but doesn't respond to the TCP connection request. Once client awakes, it sends its own gratuitous ARP which reroutes the initial TCP connection packets to client and it responds to complete connection.
That the main job of the server. It looks like the server will also be a proxy and respond to mDNS requests on behalf of the client. In practice, all machines will have the client's services cached in their local mDNS cache since the client wakes up roughly every 2 hours and send out a multicast list of its services with a TTL of 1 hour and 15 minutes. The last job of the service is to send out a magic packet when the TTL of the OPT record expires as a last ditch effort to get client to refresh its services; although in practice the Mac's wake themselves up before this magic packet is ever sent. The Linux based SleepProxyClient script takes advantage of this though instead of using an RTC timer to wake themselves up.
Since Apple products do not send IP based magic packets, you can't log them with Linux iptables commands. You can use ebtables logging though. Here is what I use on my Linux based router to log magic packets to syslog:
If you have tcpdump install somewhere, here is example of logging unicast Dynamic DNS Updates, multicast DNS messages but only from sent from 192.168.1.4 (the sleeping Mac), and non-IP magic packets and save them to a file to be later parsed by wireshark. Note: Port 53956 is based on response from above
If you have a spare Mac; besides the one your trying to be a Sleep Proxy Client and wake from sleep; you can tell its mDNSResponder daemon to be a Sleep Proxy Server. This gives you the ability to enable logging and better debug your issues. This is enabled by editing
Be warned that you must go to System Preferences->Power Savings->Computer sleep option to Never. If this option is set to let computer sleep then mDNSResponder will NOT become a Sleep Proxy. The value of 10 is also important because it gives higher priority to this proxy compared to any other that may be on your network.
You must restart your computer for changes to take effect or you can issue this two commands to restart mDNSResponder without rebooting:
I've used this and the killall -USR1 to log timestamps of when server starts responding to ARP requests and when it stops responding to them. Seems it stops responding to them at roughly 75 minutes after the last Dynamic DNS Update message was sent from Client.
Apple has an iCloud service called Back To My Mac which lets you connect to your computer from a remote location. I believe its somewhat meant to work with sleeping Macs as well. As best I understand, the sleeping computer's mDNSResponder must perodically wake to refresh its registered services with both any local Sleep Proxy Server and to the iCloud Back To My Mac Servers but that a local Sleep Proxy Server is always required to send the magic packets to wake the sleeping Mac.
To ssh from a command line from a remote location, you'll need to find the ID given to your iCloud account by running dns-sd command:
The above tells you the iCloud address for this account is 1245678.members.btmm.icloud.com. If you wanted to look for computer names registered with ssh service for that account you can run
If I look at my router's port forwarding table, I see that ports related to Back To My Mac are being registered multiple times and on NAT boxes you can only forward 1 port 1 time. If your router only supports UPNP registration then I think only 1 computer can register to BTMM at a time. If it uses NAT-PMP then that supports a way for clients to request a port # but a different one be returned. When you look at output on your router from NAT-PMP registration you should see unrelated IP addresses and ports 4500 and 5353 mapped to unrelated ports on:
I know its the miniupnp daemon that suports both UPNP and NAT-PMP so I'll watch its changes.
If your having issues with BTMM, look at your port forwards and verify that you computer in question is registered and has a non-conflicting port value on the WAN side.
Using both an Apple TV 2 and an Macbook Air as a Sleep Proxy Server, I notice that over time the sleeping Mac's services slowly stop showing up in Bonjour Browser for the local network. When using the Apple TV 2, the services also disappear from Back To My Mac/iCloud network most the time. Using Macbook Air, the BTMM network seems to keep advertising the services longer. I can't quite nail down exact timing of when the services are lost.
I've seen reports that BTMM works more reliably for people in waking their Mac's up which kinda aligns with above. But on the other hand, my experience tells me that its the sleep proxy that wakes up the Mac in all cases and once it loses knowledge of a service for sleeping Mac, it also stops sending Magic Packets to wake the Mac.
If your sleeping Mac doesn't wake up in a timely fashion, the services will expire and be removed. You can use the following command to get a feel for what time intervals mDNSResponder is waking up your Mac:
From above log, you can tell its sometimes setting to wake up in about 1 hour and 45 minutes and other times in about 1 hour and you can tell the timestamps correspond roughly to those time periods. mDNSResponder likes to wake up 10% early compared to Time To Live values its tracking. Those values above roughly correspond with TTL of 75 minutes and 120 minutes.
So it seems my Mac is attempting to do the right thing and wake up occasional to refresh its advertised services. Its a little suspicious to me that its using the 6466 values. I've done some initial investigation into what a Sleep Proxy Client does (mostly by browsing this python script) when it goes to sleep to see how long the Sleep Proxy Server will wait before timing out the client's services.
The server not responding to ARP's after 75 minutes; which is same time period as Time To Live in Dynamic DNS Update for the services. Here is a small snippet of decoding packet from wireshark:
Turns out the TTL of 120 minutes comes from the OPT record in the Dynamic DNS Update message that the sleeping client sends right before sleeping. It also tracks multiple outstanding TTL's from DHCP and other items and wakes up after the shortest TTL.
Wireshark doesn't decode this OPT record but you can see it by looking at the data. 120 minutes is 7200 seconds which is 0x201c or 0x1c20 stored in little endian format:
On of the RFC's says that this OPT TTL is supposed to be the value used for overall Dynamic Update; regardless of the TTL of the TXT and SRV records.
As a test, I tried to shorten the TTL of the Dynamic DNS Update from 2 hours to 1 hour and 15 minutes. I had no success in recompiling the mDNSResponder because it requires to may private headers to be installed that do not ship with OSX. So instead I patched the binary. The TTL is set in SendSPSRegistrationForOwner() with value DEFAULT_UPDATE_LEASE (7200).
You can run this command to disassemble the mDNSResponder binary:
So take note of the 0x3f3a1 value (ignore the 1 set up higher) and use your favorite binary editor to change the value. Here is one way:
I replaced my local binary with this modified version and verified it now sends Dynamic DNS Update with new TTL and client always wakes up with in 1 hour. I still have issues with services being lost. So its not a real fix but does make it randomly work a little more often then it was.
As long as client is sleeping, the sleep proxy seems to work. If the client wakes up because of the "lightweight" wake mentioned above, then it will resend a new Dynamic DNS Update message. More often then not and this resend , it only sends 1 packet instead of 2 and that 1 packet is usually the one with limited info.
From that point on, the sleep proxy no longer knows about the now missing info and so will not respond to any services and wake up the Mac.
In parallel, the client is maintaining a list of services with iCloud's Back To My Mac. With that unicast DNS server, it does not need to send as many services; namely it doesn't send the iTunes audio streaming (DAAP) or Home Sharing services. This shrinks it enough that it can more often send in 1 message. So sometimes you wan wake up your Mac by using the Back To My Mac address as apposed to the private LAN name.
Work around? Turn off some of your shared services until its able to register with a single message. I've been playing with this and so far its working its been working fine... although I'd really like to have those services re-enabled!