Dash Button Corral

Amazon’s new Dash Button things are pretty cool. I bought a couple and wanted to keep the original firmware on them to not take them apart, but still control them and have them talk to my server rather than Amazon’s. So I set up my home router to be a “network of lies” to trick it into talking to my server as if it was an Amazon one. Here I’ll describe how you can do this too.
For reference, my home router runs OpenWRT so this was all done with it. These changes might be possible with other Linux-based routers but I love OpenWRT and know it best so it’s what I used.

First thing is to set up your Button. Download the Amazon Shopping app on your iPhone or Android and set up the device as per the instructions. You can stop it at the last step to select a product if you want, or go ahead and select one if you want to use it as intended later. Just make sure the SSID you have them going to is your OpenWRT router that you control.

By running WireShark and ettercap, we can observe how the Dash Buttons behave. They phone home to “parker-gateway-na.amazon.com”. But they look up the IP for that domain by talking to Google’s DNS servers. The Button doesn’t use the DNS server given by your home DHCP server, it insists on using Google’s. That’s pretty smart. But we can get around that.

So we need to build fences for a corral within to keep our Buttons from roaming around, or upgrading their firmware. The first step is to trick it from using Google’s DNS servers. Instead, we want it to hit our own.
For this, we SSH into our OpenWRT router and edit “/etc/firewall.user”. We tell it to redirect all traffic (TCP and UDP, DNS is UDP) to our DNS server when someone tries Google’s. So add these two lines:

iptables -t nat -I PREROUTING -j DNAT --destination --to
iptables -t nat -I PREROUTING -j DNAT --destination --to

Then apply those changes by running

/etc/init.d/firewall restart

Now when the Button contacts, it’ll actually be talking to our router’s DNS server on If yours is different, then change those iptables commands to point to your preferred DNS server.

The second part of our corral is to make “parker-gateway-na.amazon.com” point to a server of our choice. To do that, I edited “/etc/config/dhcp” on my router which is my router’s DNS server config. In the “config dnsmasq” section, I added this line:

list address '/parker-gateway-na.amazon.com/'

This tells my local DNS server that when it gets asked about “parker-gateway-na.amazon.com” it should tell everyone it’s on You can change this to be some machine on your network, or another IP like your EC2 instance or Digital Ocean droplet or whatever.
Apply the change by running

/etc/init.d/dnsmasq restart

You should now be able to test this on your machine. Run
dig @ parker-gateway-na.amazon.com
This command tells ‘dig’ to do a DNS lookup using as the DNS server and look for ‘dig parker-gateway-na.amazon.com’. It should resolve as an A record to that IP you gave to dnsmasq.

If that’s ready and working, now you can set up your target server to serve your Buttons. I did this using nginx, and here is what my config file looks like:

server {
listen 80;
listen [::]:80;

# SSL configuration
listen 443 ssl;
listen [::]:443 ssl;
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
include snippets/snakeoil.conf;

root /code/amazon-dash/www;

# Add index.php to the list if you are using PHP
index index.php index.html index.htm index.nginx-debian.html;

server_name parker-gateway-na.amazon.com;

# To allow POST on static pages
error_page 405 =200 $uri;

rewrite ^/2/b$ /dash.php;

location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;

# pass the PHP scripts to FastCGI server listening on the php-fpm socket
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;

I’m just using PHP for this, and as you can see, I host it at “/code/amazon-dash/www”. But you can put your files wherever you want.
It redirects the path that the button looks for at /2/d to “dash.php”

Here is the code in “dash.php”


$out = fopen("/tmp/dash_request.txt", "w");
$req = print_r($_SERVER, true);
$req .= print_r($_POST, true);
$bindata = file_get_contents('php://input');
$bb = print_r(str_split($bindata), true);
$id = substr($bindata, 6, 16);

$idd = sprintf("id: %s \n\n", $id);

fwrite($out, $req."\n\n".$idd."\n");

if($id == "G030G0055XXXXXXXX")
$output = shell_exec("bash /code/amazon-dash/scripts/x.sh 2>&1");
else if($id == "G030G0055YYYYYY")
$output = shell_exec("bash /code/amazon-dash/scripts/y.sh 2>&1");


I am doing my best to parse out the unique ID given to each Dash button. This is that “DSN” code printed on the outside of the box it comes in. That way you can tell multiple buttons apart. And in this case, I just have the different buttons executing different shell scripts. So you can make them do whatever you want.
I also set up some debugging so that info about the requests are logged to “/tmp/dash_request.txt”. I figured out only enough of the protocol to extract the unique ID. But it’s binary and I’m sure there are lots of interesting things in there that I’m missing out on. Remaining battery for example is probably one of them.

But anyway, at this point you have your little Dash Button corral to keep the buttons you own from running away. Plus they can do whatever you want them to do. If your scripts return a 200 OK HTTP response, the Buttons will even light up green to say that all is cool.


Note that I don’t know how long this will last. I very much expect Amazon to issue a firmware upgrade to fix this. One thing is that the Buttons talk to parker-gateway-na.amazon.com using HTTPS. And if you take a look under the skirt of the firmware that dekuNukem kindly posted to https://github.com/dekuNukem/Amazon_Dash_Button (you can run the “strings” command on the Cottonelle.bin file he has) you’ll notice it has quite a few certificates in there. Luckily for us, in the initial release the Amazon engineers didn’t bother validating the certificates, which they probably should have. This lets our Nginx server to sit there and pretend to be “parker” and present bullshit self-signed certificates which the Dash Buttons are happily expecting.
I think one of the first changes in a subsequent firmware upgrade will be to address this. But once you corral them in on your network, you can keep them from doing this.

Creating a Vagrant virtual machine for OpenWRT

Since my last post, there have been many great improvements to Micah’s Fadecandy project and the “fcserver” application I ported for Atheros-based OpenWRT devices. I didn’t really keep up with things and only just released builds with the newer versions. They’re at the same download URLs, just in release2. https://github.com/nemik/fadecandy-openwrt/releases/tag/release2

To keep this from happening again, it seems like a good idea to show people how to make their own OpenWRT builds with “fcserver” and other things they might want. The buildroot for OpenWRT is simple but can still be a challenge sometimes.
That’s why the Vagrant http://www.vagrantup.com/ virtual machine helper is so awesome. It makes using virtual machines very easy on just about every platform. Unfortunately the complete Vagrant box with OpenWRT buid-root is over 2.7GB and is too much for me to host here for download. If anyone wants to help with this, please get in touch.
But in the meantime, I’ll show you how to do the same thing yourself.

1. Download and install Vagrant for your OS from http://www.vagrantup.com/
2. Set up a Debian-Wheezy-based Vagrant box. Download “Debian Wheezy 7.2 amd64 (VirtualBox Guest Additions 4.3.0) (2013/10/19)” from http://www.vagrantbox.es/
3. Save this to some directory for this project, call it “openwrt_vagrant”
4. Run vagrant box add fadecandy-openwrt debian-7.2.0.box to add the box
5. Download my Vagrantfile from http://nemik.net/x/Vagrantfile into the directory. This is the config for it, it will make the virtual machine run on IP “”
6. Run vagrant init fadecandy-openwrt to initialize the box
7. At this point it should be all set up, so let’s start the virtual machine with vagrant up
8. The box should come up successfully, and when it does, SSH into it with vagrant ssh. You can also do this by doing: ssh -i ~/.vangrant.d/insecure_private_key vagrant@
9. Now we’re inside the Debian system! We should update it with sudo apt-get update and then sudo apt-get upgrade
10. The upgrades will require a restart of the box. Exit from it with Ctrl+d or the exit and then shut down the vagrant machine with vagrant halt. Then start it up again with vagrant up and SSH back in like in step 8
11. When SSH’d back into the box, let’s install the build dependencies needed for building OpenWRT. sudo apt-get install subversion build-essential git-core libncurses5-dev zlib1g-dev gawk
12. Now let’s get OpenWRT source with git clone git://git.openwrt.org/openwrt.git
13. Go into the new source directory with cd openwrt
14. Add my package to the feeds. Edit the “feeds.conf.default” file with vim or nano and add the line “src-git fadecandy git://github.com/nemik/fadecandy-openwrt.git” to the file
15. Update and install the packages from the feeds by running ./scripts/feeds update -a followed by ./scripts/feeds install -a
16. It’s now time to set up the OpenWRT build configuration. Run make menuconfig
17. In the menu, change your “Target Profile” to the device you’re targeting, like say a TP-Link TL-MR3040
18. Turn off the firewall too so we don’t have to open more ports. Go to “Base System” and press space until “firewall” isn’t selected anymore.
19. Go to “Utilities” and scroll down to “fcserver”. Press space on the option until it’s a star “*” and then exit from the menu and save it.
20. Download some static files to go into the OpenWRT OS from http://nemik.net/x/openwrt-fc-files.tar.gz. Run wget http://nemik.net/x/openwrt-fc-files.tar.gz and then tar xzvf openwrt-fc-files.tar.gz These file set up the default root password, wifi access point, and things like that.
21. Now to finally do the build. For this, just run make
22. That should be it! If this finished successfully, you’ll have a build in “bin/ar71xx/” with the name “openwrt-ar71xx-generic-tl-mr3040-v2-squashfs-sysupgrade.bin” just like the ones I’ve been releasing.

Standalone OpenWRT Fadecandy Server for LED control

I recently discovered Micah’s awesome Fadecandy USB controller for WS281x LED pixels. One of the things that I like the most about it is its “fcserver” to control LED pixels using Websockets. That is fantastic, but all implementations I’ve seen have people running it on a RaspberryPi or regular PC.

I wanted to create a sort of “stand-alone” and embedded version of this using less expensive TP-Link routers, running OpenWRT. My current favourite of these is the TP-LINK TL-MR3040 but it would work just as well with the infamous WR703n or others; so long as they have USB support.

To do this, I created an OpenWRT package of the fcserver code: https://github.com/nemik/fadecandy-openwrt
You can add this to your own OpenWRT build by adding the line src-git fadecandy git://github.com/nemik/fadecandy-openwrt.git to your “feeds.conf.default”. Then run ./scripts/feeds update -a, then ./scripts/feeds install -a. Then run make menuconfig. Select “fcserver” from “Utilities” and your target architecture/device. Then run make

Or, just get my pre-built binaries from here:
TP-Link MR3040 v1
TP-Link MR3040 v2
TP-Link MR3020
TP-Link WR703N

and flash them to your unit.

The defaults are:
* root password is “root”
* Open wifi access point called “Fadecandy” is broadcast. You can connect to it and get an IP
* The ethernet port is configured to accept DHCP leases, so if you plug it into your local router, it can give it an IP and you can get to it remotely then

That’s it. Then just plug in the Fadecandy USB device into your OpenWRT device’s USB port. It should detect it. Then you can connect to its “Fadecandy” access point over Wifi and visit “fadecandy:7890” to get to the Fadecandy server interface.
Unfortunately, my WS2812 LEDs and Fadecandy controller have not yet arrived, but I do have a Teensy3. When I flashed it with the Fadecandy firmware version 1.07 (using TeensyLoader) it worked and blinked to identify itself from the web UI!
So I think that means it is working? If anyone could try it out with their pixels, please let me know how it works out for you. I hope performance is alright. Otherwise, I’ll be reporting back on it once my equipment arrives.

I like this approach because the OpenWRT units are very cheap, small, low power, and provide great connectivity. They also use a 5V source like many LED pixel strings, so they can be more easily integrated and embedded into art pieces and installations.

Whitelisting IPs in Apache and RHEL

I had a problem recently where I wanted to whitelist a set of IPs (and that set may change anytime) to allow them to use a reverse-proxy on Apache in an RHEL (Red Hat Enterprise Linux) environment. Here’s some instructions on how to do this yourself.

1. So the first step is to edit your Apache config. I was doing this in an SSL context so I edited the /etc/httpd/conf.d/ssl/conf file and put this in the VirtualHost part:
RewriteEngine On

RewriteMap ipslist txt:/var/www/whitelist.txt
RewriteCond %{REMOTE_ADDR} ^(.*)$
RewriteCond ${ipslist:%1|black} ^black$ [NC]
RewriteRule ^ - [F]

The first line turns on Apache’s Rewrite module, this is required for this setup to work. Then it creates a RewriteMap called ‘ipslist’ located at /var/www/whitelist.txt. I advise putting this in /var/www because if done in some other /home directory, it won’t work with SELinux enabled as it won’t allow Apache to access files there. Chmod’ing the whitelist.txt to 664 is a decent permission.

2. Create your whitelist. This is the “/var/www/whitelist.txt” file. For this, just put in the IP you want whitelisted followed by a space then “white”. Then the next IP on the next line.
So a sample one could be: white white

and so on.

3. Restart Apache, just do “sudo /etc/init.d/httpd restart”

4. That should be it! All the rest of your config can be as it is, including proxying functionality or whatever because the URL rewriting happens before all that.

The nice thing about the “RewriteMap” function is that you can change the whitelist.txt anytime you want and you don’t have to restart or reload Apache! It’ll automatically pick up on the change from the file’s changed date and update it.

Belkin Wemo Teardown part 2

Made progress today with using UPnP to communicate with the Wemo.

I used the awesome miranda-upnp Python library to explore the device. Its URL for listing services is at

There are ones for “rules”, “remoteaccess”, “metainfo”, “WiFiSetup”, “firmwareupdate”, “timesync” and “basicevent”.

The most interesting one, I’m guessing, is “basicevent” because it contains an action called “SetBinaryState” and “GetBinaryState” on top of others like “GetSerialNo”, “GetMacAddr” etc. But the BinaryState thing looks cool because I’m guessing it is what is used to control the switch.

Unfortunately, sending commands/actions to this service always returns a 500 error, with error code -111 is “Invalid Service” although from all indications I am sending the SOAP request to the proper URL and service. I tried it manually and through miranda-upnp, same results.
At this point I think it is a header I might be missing, perhaps the “User-Agent”? And without the one the device is expecting, it will reject with a 500?

I unfortunately don’t have an iOS device to test with. Has anyone with an iOS device and Belkin Wemo sniffed the traffic between them? If I can get my hands on one, next step would be use Ettercap and Wireshark on that same wifi AP to see what the iOS app is sending that I’m not.

Belkin Wemo Teardown part 1

I received a Belkin Wemo device today to play with.

Since I do not have an iOS device, and for some reason the Wemo ONLY works with iOS (wtf?), I’m trying to get it working without it.

So far I’ve connected my laptop to its wifi access point. It assigned me an IP of and its IP is
No conventional ports such as 22/SSH, 23/Telnet or 80/HTTP worked.

Running nmap revealed very few ports to be opened:

nemik@a64:~$ nmap -sT

Starting Nmap 5.21 ( http://nmap.org ) at 2012-07-16 17:48 CDT
Nmap scan report for
Host is up (0.029s latency).
Not shown: 998 closed ports
53/tcp    open  domain
49152/tcp open  unknown

Nmap done: 1 IP address (1 host up) scanned in 1.81 seconds

When running telnet on the opened port 49152, there were interesting things:

nemik@a64:~$ telnet 49152
Connected to
Escape character is '^]'.
HTTP/0.0 400 Bad Request
SERVER: Linux/2.6.21, UPnP/1.0, Portable SDK for UPnP devices/1.6.6
CONTENT-TYPE: text/html
<html><body><h1>404 Not Found</h1></body></html>
Connection closed by foreign host.

Same for curl:

nemik@a64:~$ curl -i
HTTP/1.1 404 Not Found
SERVER: Linux/2.6.21, UPnP/1.0, Portable SDK for UPnP devices/1.6.6
CONTENT-TYPE: text/html
<html><body><h1>404 Not Found</h1></body></html>

Interesting that it runs Linux though! I’d like to open it up to see the type of chips used inside but I do not have the triangular screwdriver for Belkin’s weird security screws on the device. If/when I order some and get it opened, I’ll post pics.

The next step is to borrow an iOS device and see if I can sniff the traffic for initializing the device. If anyone has done something similar or has any tips, please let me know.

Error mounting some SD cards on Linux Kernel 3.3+

I ran into an issue today using the gpiommc and mmc_spi kernel modules to use SD cards from GPIO pins, in OpenWRT.

Using a 2GB Transcend card I was getting:

[ 1473.570000] gpio-mmc: GPIO based MMC-Card "default" removed
[ 1473.960000] gpio-mmc: Failed to request mmc_spi module.
[ 1474.030000] mmc_spi spi32757.0: ASSUMING 3.2-3.4 V slot power
[ 1474.100000] mmc_spi spi32757.0: SD/MMC host mmc0, no DMA, no WP, no poweroff
[ 1474.190000] gpio-mmc: MMC-Card "default" attached to GPIO pins di=1, do=3, clk=4, cs=2
[ 1477.420000] mmc_spi spi32757.0: setup: unsupported mode bits 4
[ 1477.490000] mmc_spi spi32757.0: can't change chip-select polarity
[ 1477.960000] mmc0: error -145 whilst initialising SD card
[ 1478.030000] mmc0: card claims to support voltages below the defined range. These will be ignored.
[ 1478.210000] mmc0: unrecognised CSD structure version 0
[ 1478.270000] mmc0: error -22 whilst initialising MMC card

With more debugging, it turns out the “mmc_read_switch” function in the “drivers/mmc/core/sd.c” file was returning an error -145 with that SD card. Not sure why, either the CARD doesn’t support it? I can’t even find that error code anywhere so not really sure what the root reason is.
BUT when just doing a “return 0;” there, the SD card ends up mounting perfectly and working quite well.

This same SD worked in kernel 2.6.30 but its “mmc_read_switch” function was simpler and probably didn’t try to read all the extra info that the 3.3+ one is and erroring out on. Not getting this info didn’t seem to impact anything much.

I hope this helps someone if they’re looking for a fix for a similar issue.

Setting up a KillerBee

Having recently ordered an Atmel AVR RZ Raven kit I was curious to play with it and try to develop some 6LoWPAN applications. This was mainly done with Contiki OS using the EXCELLENT tutorial on it here: http://www.wsncloud-murdoch.org/wiki/index.php/ConfigurationofAtmelRavenswith_Contiki

I also wanted to get the KillerBee framework working. Contrary to what the KillerBee documentation says, you don’t really need an AVR JTAG ICE whatever $300 programmer. It works just fine the Atmel AVR Dragon which is only $50 USD.

Using that programmer, I was able to successfully flash the AVR Raven USBstick to the KillerBee firwmare using:

sudo avrdude -c dragonjtag -p usb1287 -e -P usb
avrdude -p usb1287 -c dragon
jtag -P usb -U flash:w:kb-rzusbstick-001.hex

I’m now able to use the zbdump tool and the others to sniff on ZigBee traffic. This is a lot of fun and seems there’s quite a few ZigBee and 6LoWPAN devices around here in River North in Chicago.

Arduino + OpenWRT = Art

It’s an OpenWRT image for the very cheap TP-Link TL-WR703N Linux routers you can buy from here: http://www.dealextreme.com/p/tp-link-703n-ultra-mini-portable-3g-802-11b-g-n-150mbps-wifi-wireless-router-light-blue-white-102903

What’s cool about them is that with the OpenWRT (https://openwrt.org/) Linux operating system, you can make this router do whatever you want, including broadcast a Wifi access-point, run Linux applications, etc. The REALLY cool thing is that it has a fully working USB port too! This means you can connect various devices to it such as USB storage, Arduinos, Launchpads, etc and even multiples of them on hubs.

I made a ready firmware version for the router that is configured to do this http://nemik.net/tmp/openwrt-ar71xx-generic-tl-wr703n-v1-squashfs-sysupgrade.bin

It is designed to make the TL-WR703N talk directly to Arduino’s and MSP430 Launchpad microcontroller kits by simply plugging in the kits into the USB port. Older Arduino’s will use FTDI drivers and make a /dev/USB0, new Arduino UNO’s make a /dev/ttyACM0, and TI’s MSP430 Launchpads make a /dev/ttyACM0 device. You can talk serial to them all directly then!
Just set the baud rate by doing something like:

stty -F /dev/ttyUSB0 raw speed 9600

and replace /dev/ttyUSB0 with /dev/ttyACM0 for Arduino UNO’s and TI Launchpad kits and 9600 with the baud rate you programmed your kit/sketch to.

You can read serial data from the kits with something like

cat /dev/ttyUSB0

and write to it simply by doing

echo "hello world" > /dev/ttyUSB0

I also packaged in SQLite and some other stuff I found useful. The .config can be found at http://nemik.net/tmp/openwrt_arduino.config

The Launchpad USB support comes from a new patch I submitted here: https://lists.openwrt.org/pipermail/openwrt-devel/2011-November/012919.html which I hope can get added to the trunk if it’s OK. It enables those drivers in the kernel, they’re already part of the kernel source.

This is not bad to use if you know your way around Linux. I disabled wireless on it and by default it listens for telnet until you set a root password for SSH with ‘passwd’.
Its subnet is and if you plug a computer into its LAN port, it should issue an IP by DHCP on the 192.168.3.x subnet.

I hope it is useful for someone.

For an example, I used it to help a friend with an interactive art installation. It’s an art installation in Chicago called “Hatchery”. The website for it is here: http://www.popupartloop.com/active.php?id=123
It’s a sculpture inside a glass building with two photosensors on the outside measuring light. When a person places their hand on one of the sensors, it detects it because the difference between them is greater than some threshold (ADC’s are needed for this part) and then as the hand is held there, it starts a cool LED light sequence. If we make a video for it, I’ll post it here later.
Anyway, what also happens is that when the hand is placed there, the Arduino sends a serial string with something like “Touched!”. A program running on the WR703n (to which the Arduino is hooked up with over USB) listens for this and when it gets it, logs it to an SQLite database that resides on a large USB stick. The router also broadcasts a wireless access point that I can connect to from my Android phone and hit a certain URL to download that SQLite DB whenever I walk by. It’d be nicer to make it available direct on the internet but there are no public access points in the area for it to connect to.
Then I take the SQLite DB and do some queries on it to do a few simple analytics such as how many people touched it at what times, hours, days, etc. The analytics page is available here: http://nemik.net/hatchery/

I hope it’s some inspiration make your own networked devices using Launchpads and these unbelievably cheap yet powerful Linux machines.

Generate your own One Time Passcodes (OTP) to use with Android

  1. Download and build “otptool” from http://code.google.com/p/mod-authn-otp/wiki/OTPTool with the usual dance:
    make install
  2. Download and install the Google Authenticator application from the market: https://market.android.com/details?id=com.google.android.apps.authenticator&hl=en on your Android phone
  3. Make up a hex-based secret for the two, like ‘12345678901234567890’
  4. Base32 encode the secret:
    python -c "import base64,binascii; print base64.b32encode(binascii.unhexlify('12345678901234567890'))"
  5. Open the Google Authenticator app and manually add an account. Put whatever you want for the account name. For the Key, enter the output from step 4. Make sure it is ‘Time based’, Save.
  6. You’ll see a code in the app that rotates every 30 seconds.
  7. run otptool -t '12345678901234567890' or whatever secret you chose.
  8. Should be the same as on the app! Make sure your time is synced and correct on both devices.