Thursday, August 4, 2016

TOWL - Telemetry over Opportunistic WiFi Links

Premise & Background:

Can you build a "LoJack" style asset tracking capability using open WiFi hotspots?

The proliferation of cheap, lightweight WiFi embedded ("IoT") devices made me wonder.  The WiFi association stack, DHCP client stack, et al. has to be incredibly lightweight and simple to fit in the firmware on, say, an ESP8266.  If you programmed one to scan, find an AP, associate, get an address, and send a single packet - would it be able to do it fast enough to report its location from a moving vehicle?

[Aside: This is actually something I've wondered about for years, but the IoT chips offered a unique and low-cost way to try it.]

"But wait," you say, "there really aren't that many open APs these days.  Most of them are captive or paywall portals, or at least make you agree to some goofy ToS."

Right, but as has been pointed out multiple times by multiple people all the way back to Dan Kaminsky's DNS tunneling talk in 2004 - hotspots diligently resolve DNS queries.  All you have to do is base32 encode the data you want to send in the hostname of a valid DNS record request, and set up a DNS server for a subdomain (under a domain you own) to catch the queries.

If it works, you get near real-time telemetry over opportunistic WiFi links using DNS recursion!  Think: "low cost LoJack with no data subscriptions".
Digistump Oak ESP8266

I used the Digistump Oak variant of the ESP8266 prototype boards.  I like the fact that it can be flashed OTA, which proves to be useful once the device is deployed in something like an automobile.

In my testing, the complete chain from calling connectAP() to getting the DNS query response typically takes between 3 and 6 seconds, which is certainly fast enough from a slow moving vehicle.

Device Output

The device stores the telemetry in a 16-byte struct consisting of:

struct telem {
  uint32_t tstamp;  // GPS time in ctime format
  int32_t lat;      // Latitude * 1000000
  int32_t lon;      // Longitude * 1000000
  uint8_t spd;      // Speed in MPH
  uint8_t sats;     // Number of GPS satellites received
  uint8_t id;       // Arbitrary number for ACK
  uint8_t mode;     // Object state information
};  // 16 bytes total

The fields are largely self-explanatory.  You'll notice that I used an 8-bit number for speed, so the max speed it will report is 255 MPH.  Also, the 32-bit ctime field means it's vulnerable to the Year 2038 Problem.

The field worth explanation is "mode", which is set as follows:

Value |   Meaning
 255  |  Startup position.
 254  |  Live. Transmitted and ACKed in realtime
 1-n  |  Stored position

The first few position observations are always flagged as mode 255, regardless of whether they're able to be transmitted live or not.  (This way you know where the device started.)

The stored position value is simply the number of 10-second intervals since last transmission modulo the MAX_INTERVAL setting.  This is how the unit "downsamples" the stored waypoint resolution if the buffer fills up.

So... how well does it work?

Here's a plot on OpenStreetMaps of me driving to work one morning.  The blue markers are live (mode 254) and the red markers are stored.

Of note are the blue markers along the freeway.  I've regularly observed this device successfully logging the telemetry data at speeds upward of 60 MPH! 

Technical Details


  • Digistump Oak
  • NMEA serial GPS module (e.g. uBlox or MTK)


The software for the Digistump Oak, as well as a PoC DNS server (in python) to log the output, is available here:

Check the README notes under both subdirectories for build dependencies / config notes.


You'll need to host a custom nameserver on the Internet to receive the DNS queries.  You'll also need to control a domain so that you can designate your DNS query receiver as a subdomain. 

E.g. if you own the domain "", you could designate a server to receive the TOWL queries by creating a NS record for "", pointing at the server you intend to run the catcher on. If said server is at IP address, then that record looks something akin to:


Run the PoC code on the designated server. Be sure to configure both the TOWL devices and the server code for the "" domain name. (See README under each directory for instructions.)

Have fun!

gps tracker dns

Wednesday, July 20, 2016

Script to toggle LEDs on the Netgear Nighthawk AC1900 / R7000

I recently purchased the Netgear Nighthawk AC1900 dual-band router, to go along with my new faster Internet connection.

First off, I'll say- I wasn't a fan of Netgear's past home routers, but this one is quite amazing!  Not only can it keep up with my 1Gbps fiber connection, it also seems to have massively improved the wireless situation in my home over my previous Linksys router.

Anyway, enough of that.  One funny thing about this router, in addition to looking like a 1990s stealth aircraft, is that it's covered with SUPER HIGH INTENSITY WHITE LEDs.  They add to the sleek look, for sure, but you can practically read by them in a dark room.  (!)  Not so great if you happen to sleep in the same room with the router.

Thankfully, the Advanced Setup UI provides a mode to turn off all the LEDs (save for the power LED, which I just stuck a piece of gaffers tape over.)

I like the status LEDs, though, so I thought - wouldn't it be nice to be able to programatically toggle them?

I was hoping I could do it with a simple request from curl, but it turns out you need to auth to the setup page and retrieve a timestamped id token, probably as an anti-CSRF measure (albeit not a bulletproof one.)  So, voila - a quick & dirty python script to toggle the LEDs on the nighthawk router.

Python 2.7
Python requests library

Download link:


# Quick and dirty script to toggle the super-bright LEDs on the Netgear
# Nighthawk R7000 router.  Tested on FW V1.0.5.70_1.1.91.  YMMV.

import requests
import sys

# !!!
# IMPORTANT:  Put your actual router password and router IP address below:
# !!!
ROUTERPASS = 'password'

# First, we have to get a valid timestamp from the settings page:
r = requests.get(ROUTERADDR + 'start.htm',
                 auth=(ROUTERADMIN, ROUTERPASS))
r = requests.get(ROUTERADDR + 'LED_settings.htm',
                 auth=(ROUTERADMIN, ROUTERPASS))
o = r.text.find('led_settings.cgi?id=')
if o == -1:
  if r.text.find('multiLogin') > -1:
    print 'Error: Another browser is currently logged into the router.'
    print 'Invalid response from router:'
    print r.text

o2 = r.text[o:].find('"')

# Next, construct the CGI URL with the returned timestamp
led_url = ROUTERADDR + r.text[o:o+o2]

if len(sys.argv) == 2 and sys.argv[1].upper() == 'OFF':
  data = 'Apply=Apply&led_settings=turn_off&led_now=en_blink'
  data = 'Apply=Apply&led_settings=en_blink&led_now=turn_off'

# Send the magic command:
r =, data=data, auth=(ROUTERADMIN, ROUTERPASS))
print 'Status code: %d' % r.status_code
#print r.text

# Avoid "multiLogin" errors:
r = requests.get(ROUTERADDR + 'LGO_logout.htm', auth=(ROUTERADMIN, ROUTERPASS))

Monday, February 8, 2016

Interactive Modemspeed - SSH like it's 1995.

A couple of years ago I created a simple python program to simulate various modem speeds when you piped a command through it.  Easy, fun, but of limited use.

So, I revisited it and made the read portion non-blocking so that it can be used interactively.  The aim is to have a script I can pipe SSH through to make the remote connection act like it's behind an oldschool modem.

$ ssh remotehost | /path/ speed

Substitute /path/ with the location of the script.
Substitute speed with the speed (in bits per second) you want to experience. 

If you omit speed, you get 300 bits per second.   

Did your friend leave a terminal unlocked?  Why not have some fun?

$ function ssh() { /usr/bin/ssh "$@" | /path/interactive-modemspeed 2400 ;}

(Make sure to put the absolute path to the ssh binary so you don't create a bash fork loop.  :-P)

Now they'll wonder why all their new SSH sessions feel like they're on a BBS in 1989.

Here's the code:


import fcntl
import os
import sys
from time import sleep

def modem(text, speed):
  # Assume speed is in bits/sec, and we're running at 8,N,1
  # So, 10 bits per character.  (1 start, 8 char, 1 stop)
  delay = 1.0 / (speed / 10)  # = seconds per character
  for char in text:

if __name__ == "__main__":
   if len(sys.argv) > 1:
     baud = int(sys.argv[1])
     baud = 300
   # open stdin in non-blocking mode so we can read 1 character at a time
   fd = sys.stdin.fileno()
   fl = fcntl.fcntl(fd, fcntl.F_GETFL)
   fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)

   while True:
       c =
       modem(c, baud)
     except IOError:
       continue  # Resource temporarily unavailable

Monday, January 18, 2016

Generic $5 128x64 OLED SPI display with Arduino Pro Micro

I bought a couple of ~$5 generic 128x64 graphic OLED displays on eBay to play with.  It took some trial and error to figure out how to get the Arduino Pro Micro to talk to them, and there's lots of different information on the net about doing so (probably owing to the wide variety of implementations of these displays and generic controller chips.)

This particular one uses the SD1306 controller and is wired for a 4-wire SPI interface.

I used the u8glib library to talk to it.  The "gallery" page on the library repo provides lots of examples of people's various combinations to make these work.  This particular one wasn't shown, but by perusing through the different examples I was able to find a combination that worked.

I'm using the SW SPI function of u8glib, so I don't have to use the ARM chip's native SCK or MOSI pins.  I found that this device will accept data without the CS pin connected (pulled low instead), so I left that out to save an output pin.  (You'd want to use CS if you were trying to use the same SW SPI bus to talk to multiple devices.)

I wired it as shown:

Arduino Pin -> OLED pin
  15 ----> SCK
  14 ----> SDA
  16 ----> RES
  10 ----> DC

Then, in the u8glib "Hello, World" example, I used the following definition:

// SW SPI Com: SCK = 15, MOSI = 14, CS = N/C, A0 = 10, RESET = 16
U8GLIB_SSD1306_128X64 u8g(15, 14, U8G_PIN_NONE, 10, 16);  

Note: The "RESET" pin was the crucial one I was missing in my initial attempts, as it's not defined in the SD1306 example configs in the source.  I had even tried tying the RES line high or low to no avail.

With those four lines, though, it works fine!  I'm not sure what the eBay auction page means by "only needs two I/O pins from Arduino."  Maybe they copied that from the I2C version.  :-P

 - K.C.

Wednesday, November 11, 2015

Installing mitmproxy on a Raspberry Pi / Raspbian Jessie

This post is a quick list of the steps it took to install mitmproxy on a vanilla Raspbian Jessie install on a Raspberry Pi.  The compile steps take quite a while, which made the trial-and-error method of figuring out which libraries were missing to be a painful process.  Hopefully this post will make it easier for anyone else trying to do the same thing.

Naturally, do
$ sudo apt-get update && sudo apt-get upgrade 
first to bring everything up to date.

Missing libraries:

  • python-dev
  • libxslt1-dev
  • libxml2-dev
  • libffi-dev
  • libssl-dev

Fairly simple, just do:

$ sudo apt-get install python-dev libxslt1-dev libxml2-dev libffi-dev libssl-dev 

Out-of-date library:

mitmproxy requires pyasn library >= 0.1.8.  
(As of this writing, the latest in the repo is 0.1.7)

Check your installed version:

$ dpkg -l | grep pyasn                                    
ii  python-pyasn1                         0.1.7-1   (...) 

If the version is >= 0.1.8 you're fine.  If, like above, it's version 0.1.7 then you'll need to replace it with a newer version.  The pip repo contains 0.1.9, so I used that.

$ sudo apt-get remove python-pyasn1              
$ sudo pip install pyasn1                        

If all the above went well, you should now be able to download, compile, and install mitmproxy (and its included dependencies) using pip.  (Note:  This will take 30+ minutes on a standard RaspPi B)

$ sudo pip install mitmproxy                           

If all goes well, you should now be able to run mitmproxy.

Have fun!

Sunday, September 20, 2015

Rebuilding the Jada Toys 2006 Camaro

We've had this cool inexpensive Jada Toys "2006 Camaro" R/C car for several years now. The batteries are worn out, the controller doesn't work well anymore and it had been relegated to just being a regular "toy car" for my four year old.

I was cleaning my electronics bench yesterday and realized I probably had enough spare parts from my other R/C ventures to gut and rebuild the Camaro with more modern parts.  Sure, the parts probably cost more than the car did, but I already had them so why not?

The first order of business was assessing whether the existing mechanisms in the car are serviceable at all.  After removing the 13 required screws to get the body off the chassis, we get a good view of the inside:

The brushed motor / gear-differential assembly (right) are probably either usable as-is or not usable at all, so I decide to keep them intact and try just driving them with a brushed motor speed controller.

The receiver / control combination circuitboard in the center looks surprisingly antique for something from the mid-2000s. (close-up) It's a totally analog 27 MHz radio receiver circuit, apparently made by the toy division of Huawei.  It's all thru-hole components and a couple of relays.  Honestly, it's shockingly reminiscent of the circuitboards that were in my childhood toys in the 1980s.  It was probably designed in that era.  Yeah. That has to go.

But what of that "steering" mechanism?  This car was fast and fun as it was originally built, but one thing I always hated about it was that the controls weren't proportional.  It had about two speeds, and the steering had three positions:  Hard left, center, hard right.

Taking apart the steering mechanism we see why:

So the steering mechanism is a geared brushed motor connected to a set of contactors that close when the steering is in the "R" or "L" position.  It's like a motorized switch for selecting between "L" and "R".

The underside of the mechanism mates with the steering crossbar with a 5mm peg:

I momentarily consider removing and re-using that disc, but decide that just putting a similar sized plastic peg on the end of a standard servo arm is probably easier.

Here's the resulting chassis steering mechanism minus the legacy control parts:

It looks thankfully simple and straightforward.  I need to fabricate a mount to hold a standard servo in a position where the arm can actuate that steering crossbar.  So, I measure and design a similar shaped peg for a servo arm and then a mounting bracket it suspend it from those two "towers" where the old, bulkier system used to be.  (Part designs are here:

Servo with servo arm & fabricated peg and 3D-printed mounting adapter:

New steering mechanism mounted in the chassis:

Here's a video of a function test.  It works surprisingly well for a first attempt!!

I used the receiver from a Hobbyking GT-2 TX/RX combo, and a Hobbyking X-Car 45A Brushed Motor ESC as the motor driver.  They were straightforward to install.  I replaced the battery connector with an XT-60 since I have lots of XT-60 equipped LiPo batteries already.

Here's a chassis / electronics "before/after" combo:

The original system ran on a 9.6V NiCad battery.  So we decide that either a 2S Lipo battery for "medium speed" or a 3S Lipo battery for "Turbo Speed" will probably work.

Sure enough, with 3S it's fast as lightening and can drift, spin-out, and do donuts.  I don't have any great videos of it driving yet, as Miles isn't terribly skilled at either driving or videography, and I can't do both at the same time.   I'll make a video with my GoPro and post it soon.  In the mean time, here's a basic video (with a 3S 1300 mAh battery) to show that the conversion worked.  (Yes, he stopped just prior to the wall.  Whew!)

It works great, and it's fun to drive!   Here's a complete parts list:

"Donor Car":  Jada Toys 2006 Camaro Radio Control Car

Fabricated Parts:
Steering knuckle & Micro Servo Mounting Adapter

Purchased Parts:
HobbyKing X-Car 45A Brushed ESC
HobbyKing HK-GT2 TX/RX combo
Turnigy TGY-50090M Analog Metal Gear Servo

That's it!

Sunday, August 16, 2015

Programming a generic STM32F103C board in Arduino

A while back I purchased some generic STM32F103C8T6 development boards on eBay for about $4 each.  I initially had some limited success programming them using the GCC ARM Embedded (eabi) toolchain and a generic STM32 loader program.  Since then I've discovered a project to get them working with the Arduino 1.5+ toolchain.

There's a lot of different information about the various STM32 boards out there.  I'm documenting my notes here mostly for my own sanity since I don't play with these boards often.  Maybe you'll find it useful too.

Arduino hardware library for these boards:

"Support" forum:

The USB port
The generic boards do not have a meaningful USB bootloader.  The USB port is only useful for power.  (TODO: Flash the "Maple Mini" bootloader onto them for future ease of use?)

Arduino Board Selection & options
Tools -> Board -> Generic STM32F103C
Tools -> Variant -> "STM32F103C8 (20k RAM. 64k Flash)"
Tools -> Upload method -> "Serial"

FTDI / Serial connection
Connect 3.3V FTDI USB -> Serial programmer as follows:

  • STM32 UART0 TX pin A9 -> FTDI RX
  • STM32 UART0 RX pin A10 -> FTDI TX

I use the GND and 3.3 pins on the 4-pin header for power, but the ones on the IO pads work fine too.

Program / Run Jumper
  • Run mode:  Both jumpers at "0"
  • Program Mode: Jumper 0 (top) at "1"

With J0 set to "1", press "reset" just before hitting "upload" in Arduino to flash firmware.  Program will run immediately after flashing, but won't run after power-cycle until you set Jumper 0 back to "0".  (??)
I have no idea what the bottom jumper is for.

PC13 LED seems to be wired from +3.3V to the PC13 pin.  So setting the pin low lights the LED, and setting it high extinguishes it.

That's it!  With any luck, after loading the above library and following these notes you can push Arduino sketches to your super-cheap, 72MHz STM32 ARM board.