Selective VPN routing [Solution: DSVR]

Before sharing about what I believe is my best solution yet, i’ll¬†take a walk down memory lane…

Client VPN

Got my first VPN account (PPTP/L2TP) and happily used it from my various Windows/Mac/iOS clients. Very quickly I came across a few limitations, namely:

1) Only one device at a time could use the VPN.
2) More restricted clients did not have a client side capability to configure the VPN (like the Apple TV/PS3)
3) When a device was on the VPN, all traffic went down it – not ideal from a performance perspective, and when you’re location is determine by IP (e.g. Google Maps).
4) Minor at the time, but could not have multiple VPNs running.

Router VPN [+Source Based Routing]

Configuring ¬†VPN connection at a single aggregation point (i.e. the router) was the next step, as this did solve some of the limitations (1 & 2 above). After a bunch of research (read: trial/error) I concluded that there was no practical way to be selective at the router based on¬†destination as many services used over the VPN where using CDNs with massive network ranges which we’re not practically predictable.

I decided that source based routing was a good solution, in my case I selected my Apple TV to be the only source to push down the VPN this has served me well,  and I published a tutorial on it a while back.

Defining the next step

Even though my problem/use-case had largely been solved, I wanted to go further. I set myself the following goals for my next solution:

1) Selective destination routing, route only sites/domains I want.
2) Multiple concurrent VPN client support, each with their own destination mappings.
3) Multiple clients able to share the outgoing VPN(s) connection(s)
4) A ‘plug-n-play’ appliance, with no configuration changes to exiting infrastructure (clients/router/modem)
5) Simple web administration interface.

With those goals in mind – it was time to determine a solution.

New Solution: DSVR [Domain-Specific VPN Router]


1. Selective destination routing

I’ve already touched on some of the challenges (e.g CDNs) – there were a few more – but ultimately I determined that a pre-populated list of IP routes for a service will not work.

Then an idea came to me – what if I made something that I’d best describe as a ‘DNS Router’, at a high-level it would need to do the following:

1) Intercept all outgoing DNS queries from my clients.
2) Analysis the query name against which domains I’m interested in pushing down the VPN.
3) Pass the unmodified DNS request upstream to a valid DNS server, and get a valid response back.
4) Before passing the DNS response to the original client, add routes for the RR data within the DNS record

What does this do? For each matched DNS request we are creating static routes down the VPN!

Theory is great – but I needed to now make this thing.

It was clear to me that the best starting point was to leverage existing work that’s been done creating a DNS proxy. I found a great one – dnschef – by¬†Peter Kacherginsky. Using this as a strong foundation I was able to modify and expand this to perform the 4 points above, and also handle some edge cases around CNAME responses etc.

In my testing – this has proven to work and be stable.

2.¬†‘Plug-n-play’ appliance,¬†no configuration changes, clients able to share

Deciding on a hardware platform for the appliance was easy – Raspberry Pi¬†– it’s low-cost, low-power, runs linux and small. It’s not without it’s limitations though (e.g. NIC limited by USB bus)

The aggregation point I selected to place the Raspberry Pi was between the existing CE/Modem and home router. This meant the RPi had to be configured as a typical NAT router. Other than the OS level configuration required to create the router, the RPi only has a single NIC, so I added a second NIC interface using a USB add-on.

To achieve the second portion of this goal ‘no configuration changes to exiting infrastructure’, I used iptables to transparent redirect all outbound DNS queries to my new custom DNS proxy/router.


3. Concurrent VPN client support

This was wasn’t too tough (for PPTP), basically just needed to configure the following for each:

1) PPP peer file
2) IP-UP script
3) INIT.D script

OpenVPN support is in the pipeline.

4. Web administration

Seeing that the core capability was done in Python, it was a logical choice to create the web interface in the same. I selected the Flask web-framework, and I used there small dev web server in lieu of the big boys like Apache.

The web interface allows for the following functions:

1) PPTP VPNs – Add/Modify/Delete
2) Specify which wildcard domains should route down which VPN
3) Stop/Start/Restart the core DSVR service
4) Status display for PPTP tunnel status, IP assignments, Route counts, uptime, mem/cpu usage
5) Reboot the RPi

webadmin (1)

Get/Build it

This blog post is just a static introduction. The code, instructions, limitations, issues and TODO’s are being maintained on the DSVR github page.

Do note that this should be considered an ALPHA release – it has not been tested by many people – use at your own risk.



Home Brew – Freezer to fermentation chamber conversion

For my home brew endeavors I had another problem to solve… a temperature controlled chamber for fermentation.

I had the following constraints/requirements:

1. Get it cold enough (10 – 15‚ĄÉ) for lager yeast. I live in a hot climate.
2. Large enough to allow my 30 litre fermenter (H:530mm,Dia:300mm) or my 6.5gal glass carboy (H:520mm, Dia:305mm) to fit.
3. Rather precise ¬†temperature accuracy¬†(~0.5‚ĄÉ)
4. Not cost “a lot”.

I decided that buying a suitably sized chest freezer and putting in a digital thermostat would be the way to go – Here’s what I bought:

1. Chest Freezer – Farfalla FCF-128A
– $299
– 128 litres
– External dimensions (W:750, H:780, D490)
– Available area for full-size fermenter (H:580, W: 382) (i.e. not including space above the “step”/”bump” inside the freezer due to the compressor)

2. Digital Thermostat – FOX1004

– $80
– Range 40.0 to 90.0‚ĄÉ
– 1 relay, 250 VAC 2A. Note: Not rated high enough to take full compressor load, hence the need for the contactor
– External dimensions (W:770, H:350, D:770)
– Input sensor diode(wire length : 3 metres)
– Input 230VAC 50/60Hz

3. Contactor – Schneider LC1K0901M

– $25
– TeSys K contactor
– 3P(3 NO) – AC-3 – <= 440 V 9 A
– 220…230 V AC coil

Now time to wire everything up.

Here is how I did it (click on the image to make it larger)

CircuitDiagram v0.2

The finished product


Note the thermometer probe is in the bowl filled with liquid – this will ensure a closer match to the actual beer temperature. Also, I put a battery powered (for now) fan in the chamber for circulation – need put in a better solution.


Home Brew – DIY Stir-plate

Inspired by one of my friends, I’ve decided to get into the world of home-brew beer. Of course I looked over all his gear and¬†immediately¬†got obsessed with the electronic components and how I could somehow automate things and connect things to the web… raspberry pi’s etc etc… but I did notice something much less ambitious, a¬†magnetic¬†stir plate, which is used for making the yeast starter in the home brew process.

Here is the finished product:

Components I used:

  1. Cigar Box – Had one around.
  2. AC-DC 12V Adapter (1.0A) – $10
  3. DC female input – $1
  4. Illuminated switch DC – $1.50
  5. Future Kit 804PWM based DC motor controller – $10
  6. Nice knob to attach to the potentiometer on the PWM controller – $1
  7. Standard DC Fan 80x80mm. 12V, 2.4W. Range 7-15V – $7
  8. Hard drive magnet – $4
  9. Stir bar(s) – $5 each
  10. General bits (wire, things to elevate the fan position)

Few things I learnt along the way:

  1. Don’t JUST use a¬†potentiometer, use PWM.¬†A common approach is to simply use a potentiometer between the power source and the fan. The main reason this is not effective is that standard DC fans need a rather ‘high’ minimum voltage to even rotate, in the case of mine, 7V. What this means is practice is that the majority of the potentiometer turn does nothing (I used 500 ohm, the smallest I could find), and that 7V was too fast to effectively bring the stirbar into a controlled spin. The better approach is to use PWM, in very simple terms this always provides full voltage, in this case 12V, but pulses it on and off very quickly to control the speed. What this means is that rotation of the potentiometer on the PWM controller gives you full control of fan speed. I was lazy and bought a pre-made PWM controller, if you’re more¬†adventurous¬†you could assemble a kit or built from schematics found all over the web, for example.
  2. Careful removing the hard drive magnet. I broke mine, fortunately it still works ok. Suggest you be very gentle and follow the instructions in this video.
  3. 2mm thick neodymium magnets are not enough. After I broke my hard drive magnetic I bought two 2mm thick circular magnetics, these were not strong enough in my case, would suggest around 4mm. I ended up using my broken hard drive magnets.
  4. Have the right tools.¬†In my¬†embarrassingly¬†many attempts to build this I did so without the right tools, which caused lots of frustration and shorted components. The tools I ended up buying made the entire stir-plate DIY more expensive than buying a generic one… but lessons aren’t free ūüôā and thats no fun. Some ‘tools’ I’d recommend are:
    • Stand/Holster for your soldering iron
    • Something to hold PCBs, wires etc to free your hands. For example.
    • Multimeter (mine one’s battery was flat the first attempt)
    • Test using a 9V battery rather than full 12V 1A DC source
    • Not a tool, but if you’re unexperienced like me… watch some YouTube videos about how to solder!