Amazon Dash doorbell


The Amazon Dash is a Wifi button originally intended for the ultra- lazy for reordering consumables from Amazon when you’re running low. It was going to £1 recently in Black Friday promotions, so I thought I’d have to snap one up. Normally they go for a not bank breaking £5, which you can recoup if you actually want to order one of the items once on them.

Amazon Dash

When pressed it connects through Wifi to send a request to Amazon, then turns off - looks fit for repurposing for home automation!

dhcp tricks

For this hack you need to be running dnsmasq for DHCP on your local network. It’s pretty common on alternative router firmware like Tomato, etc.

If you don’t the alternative is to have something listening for the dhcp or arp broadcast requests the device makes when it wakes - but this seems is a bit more fiddly than the following solution.

Push the button

First you’ll want to prevent it from ordering a load of toilet roll everytime someone presses your doorbell (!), so the trick is to setup the Dash partially (enough to get onto your network), but do not assign a product to it. This ensures it won’t actually order anything.

If you’ve already assigned a product, you can rerun setup by holding the button down for 5s and redoing the wifi network setup part of the process.

Next I configured the Dash button to a fixed IP and hostname on the network, in /etc/dnsmasq.conf:

dhcp-host=50:F5:XX:XX:XX:XX,set:restricted,dash1,192.168.10.193,1d

The mac address can be found in the dnsmasq logs. set:restricted puts the device into a separate pool of restricted IP addresses.

Having done this, the Amazon App on the phone annoyingly still pops up a notification to indicate it needs a product, so it’s clearly still contacting Amazon. So I added a host record to dnsmasq configuration to divert the DNS lookup the device does from Amazon just to point to localhost.

Check what host lookup it is performing by sniffing your network:

$ tcpdump -ieth0 udp port 53

My UK purchased button was looking up parker-gw-eu.amazon.com, so add to /etc/dnsmasq.conf:

host-record=parker-gw-eu.amazon.com,127.0.0.1

Remember to reload dnsmasq configuration:

systemctl restart dnsmasq

Test the button again - it will stay pulsing white for a little longer because it cannot phone home, but eventually gives up after a few seconds.

Bad robot

Also, to be safe I firewalled this subnet from contacting the internet, just so I don’t accidentally create a botnet if the device gets hacked.

In /etc/iptables/iptables.net (for Archlinux - locations vary for other Linuxes):

# block restricted devices from forwarding
-A FORWARD -s 192.168.10.192/27 -j RESTRICTED
-A RESTRICTED -p udp --dport 123 -j ACCEPT
# REJECT rather than DROP so devices give up sooner
-A RESTRICTED -j REJECT

I still let through the NTP time requests (port 123) the device sends, so it doesn’t have to keep retrying them.

Sticking to the script

Now finally to get the button doing something useful instead, we use the very handy dhcp-script directive dnsmasq provides to run a script when it asks for an IP address. Run as the nobody user to be safe:

dhcp-script=/usr/local/bin/dnsmasq-script
dhcp-scriptuser=nobody

The script will be run with 4 parameters:

  1. old/new/add: whether the lease is old, new, or just been created.
  2. mac address: device mac address
  3. ip address: ip assigned
  4. hostname: hostname assigned (optional)

There’s also a stash of environment variables it will get too:

  • DNSMASQ_DOMAIN=home
  • DNSMASQ_INTERFACE=eth0
  • DNSMASQ_LEASE_EXPIRES=1481793446
  • DNSMASQ_LOG_DHCP=1
  • DNSMASQ_TAGS=dhcp restricted known eth0
  • DNSMASQ_TIME_REMAINING=86400
  • JOURNAL_STREAM=8:1042433
  • LANG=en_GB.UTF-8
  • PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
  • PWD=/
  • SHLVL=1

In the script /usr/local/bin/dnsmasq-script I’ve put:

#!/bin/bash

if [ "$1" == old -o "$1" == add -a -n "$4" -a -n "$DNSMASQ_TAGS" ]; then
  MESSAGE='{"topic":"dash","source":"'$4'","command":"on"}'
  mosquitto_pub -t gohome/dash -m "$MESSAGE"
fi

This sends an MQTT message to my home automation system - customise it to your setup.

The first condition checks:

  • if this is an add lease or old lease being renewed
  • if there is a hostname assigned to the device
  • that the request has tags

Because the way dnsmasq works, whenever you restart it this script will be called for all existing leases, so you don’t want the doorbell ringing for this case - the tags check prevents this.

Remember to make it executable by all (chmod +x /usr/local/bin/dnsmasq-script).

Finally reload dnsmasq configuration:

systemctl restart dnsmasq

Hit the button, and mosquitto_sub should show the message being sent.

Timeliness

Of course this isn’t limited to doorbells - anything you want to trigger with a button around the house could be done. In terms of how long this all takes

  • it’s pretty consistently 4s by my stop watch, which seems fast enough for someone waiting on the doorstep.
dash  iot  doorbell