Creating a Wireless Proxy/VPN Router with a Raspberry Pi

A few months ago I read an article on Make, describing how to make an Onion Pi. An Onion Pi is a Raspberry Pi setup as a wireless router that routes all traffic through a Tor proxy service. The idea is cool because any device could use Tor at that point. I don’t know of a Tor client for iPhone but with an Onion Pi it would be possible to route any device through Tor with pretty much no setup for the device connecting. I thought this was really interesting and I’ve always wanted to mess around with a Raspberry Pi, but I never really had a project in mind.



All of these articles are worth your time if you’re wanting to do this yourself. I will warn you that I was not able to use the automated scripts included in the Baking an Onion Pi article due to differences in the hardware I used. However, because I had issues, I was able to learn on my own how things are setup and it also allowed me to alter the end result of my project.


My End Result:

Ultimately, I ended up with a Raspberry Pi wireless router that could be a standard router with out any re-routing, a Tor proxy wireless router, or a VPN connected wireless router. With a couple of bash scripts, that basically turn services on or off and restores saved iptable configurations, it’s fast and simple to be able to switch between each mode. I plan to document how I did this in the next few posts. This is a guide to recreating what I made.


My Hardware:


Here’s the hardware I ended up using for this project.

With just over $82 in this project the price is not too far off from a good router. The benefit to building your own router is that at the end, this will be a lot more powerful, and expansive, than a router off the shelf at the same price point. I have a bunch of ideas of how I’d like to expand what this device is doing, but for now I’m happy with it being a multipurpose router.



Before getting started I’m make a few assuptions:

  • You’re using Raspbian
  • You’ve done basic configuration to your Raspbian installation like changing the default password
  • You’ve configured your keyboard correctly (the first time I used Raspbian it was configured for the UK and was … weird)
  • You have some linux command line experience (if not you should be able to run through each step and it should work)
  • You have an account with Private Internet Access for VPN


Part 1 – Creating a basic router:

Before configuring VPN or installing Tor, I want to walk through configuring the system as a basic wireless access point. I want to build layer by layer each mode. By doing this you’ll create the iptable configurations along the way to be used in the bash scripts to switch the router between each mode.

The idea is to use the USB wireless adapter to broadcast out from your Raspberry Pi so that other devices can connect to it, and then route all the traffic to the ethernet port.

Step 1 – Install Software

Access point server (hostapd), DHCP server (udhcpd), & DNS proxy server (bind9).

sudo apt-get install hostapd udhcpd bind9

Step 2 – Configure the Access Point

If you type in:


You should see wlan0 listed. That’s the wireless card.

You’ll need to edit the file /etc/udhcpd.conf. I used nano to do this.

sudo nano /etc/udhcpd.conf

And I edited the file to look similar to this:

interface wlan0
remaining yes
opt dns
option subnet
opt router
option lease 864000 # 10 days

To save using nano press Ctrl+X and then Y to save the file.

With this configuration, we’re going to use as the router’s address, and devices connecting to it will be – 254.

Edit the file /etc/default/udhcpd and remove the # from the following line to uncomment it out:




To set the Pi’s static address to run:

sudo ifconfig wlan0

In order to keep this static route every time your Pi reboots, you’ll need to edit the /etc/network/interfaces file.

sudo nano /etc/network/interfaces

Mine looks like this:

auto lo

iface lo inet loopback
iface eth0 inet dhcp

#allow-hotplug wlan0
iface wlan0 inet static

#wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
#iface default inet dhcp

Later you’ll update this file with a iptables we want to restore by default.

Next you’ll need to configure your wireless card to act as an access point by editing the file /etc/hostapd/hostapd.conf

sudo nano /etc/hostapd/hostapd.conf

If it opens up blank it means that it didn’t exist. It’s not a problem because you’ll just file it with the following configuration:


Warning: As long as you’re using the same wireless card that I am you should be fine with the driver being set to nl80211. The first article I read about baking an Onion Pi, the driver was set to something different which didn’t work for me.

Another thing to note is the channel I’ve selected. I used channel 1 because I scanned my area first to see what everyone else was running. I saw a lot of devices on channel’s 6 and 11, which makes sense. Most of the time you’re going to want to stick with 1, 6, or 11.

Be sure to replace the ssid and wpa_passphrase with values you want. I suggest an SSID to be something like “PiFi”, or “OnionPiFi”, or “VPiN”, or maybe “virusinstaller.exe” (actually with a name like that, discard a passphrase all together to see who’s brave). Be creative.

Next, edit the file /etc/default/hostapd

sudo nano /etc/default/hostapd

And change the line:




Before we start the wireless network you want to configure bind9. Bind9 will act as a local caching DNS server. If you remember in the file /etc/udhcpd.conf, we configured the client connecting to the router to point to the router itself for DNS. The line was:

opt dns

So onward to the next step…

Step 3 – Configure the DNS (bind9)

Edit the file /etc/bind/named.conf.options

sudo edit /etc/bind/named.conf.options

You’ll want to add forwarders to and My file looks like this:

options {
    directory "/var/cache/bind";

    forwarders {;;

    dnssec-validation auto;

    auth-nxdomain no; # conform to RFC1035
    listen-on-v6 { any; };

These addresses are public Google DNS servers.

Restart bind9:

sudo service bind9 restart

To make sure that bind9 starts when the device is rebooted:

sudo update-rc.d bind9 enable

Step 4 – Configuring NAT

Next you’ll want to enable NAT.

sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"

To get this to stick each time the device reboots, edit the file /etc/sysctl.conf and add the following line to the bottom of the file:


Next, enable NAT in the kernel, by running these commands:

sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT

With this in place you’ll need to save this configuration to a file that can be restored each restart. To do this run:

sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"

And then edit /etc/network/interfaces by adding this to the bottom of the file:

up iptables-restore < /etc/iptables.ipv4.nat

Step 5 – Start up wireless

Next you should start the wireless network:

sudo service hostapd start
sudo service udhcpd start

And to make sure those services start with the device:

sudo update-rc.d hostapd enable
sudo update-rc.d udhcpd enable

Part 1 – Complete! 

At this point you should have a basic Raspberry Pi wireless access point. Try connecting to it and going to a website. If it work, pat yourself on the back. This was a lot of instructions and it’s not even done yet. If it didn’t work, sorry. Ping me or check out the sources I posted above.


Part 2 – Configuring OpenVPN with Private Internet Access

The next part will cover installing, and configuring OpenVPN to work with Private Internet Access. They’re a great provider and I’ve been using them for years now. These instructions should kind of work for other providers. For a basic install, check out the last link I posted above, Raspberry Pi as a VPN Wireless Access Point.

Step 1 – Install OpenVPN

Next you’ll need to install OpenVPN

sudo apt-get install openvpn

Step 2 – Configure OpenVPN

Private Internet Access provides configuration files for OpenVPN, and you can download the zip file here: Private Internet Access OpenVPN Configurations

You’ll want to download the zip:

sudo wget

This zip has a bunch of stuff that you won’t really need, so you might want to extract it to a different directory.:

sudo unzip -d openvpn

Next copy the files ca.crt and crl.pem to /etc/openvpn, but first make sure you’re in the folder you just extracted the zip to:

cd openvpn

Then copy ca.crt and crl.pem to /etc/openvpn

sudo cp ca.crt /etc/openvpn/ca.crt
sudo cp crl.pem /etc/openvpn/crl.pem

Next you’re going to create a configuration in /etc/openvpn (the actual file name doesn’t matter. When OpenVPN starts it just looks for a .conf file; however this will need to be named this for the bash script I created later on).

sudo nano /etc/openvpn/client.conf

And modify the file with:

dev tun
proto udp
remote 1194
resolv-retry infinite
ca ca.crt
remote-cert-tls server
verb 1
reneg-sec 0
crl-verify crl.pem
auth-user-pass password.txt

With that conf file in place you can start the VPN:

sudo service openvpn start

If you type in ifconfig, you should see tun0 listed. That’s the VPN tunnel that you’ll create a iptables configuration for next.

Step 3 – Route traffic to tun0 instead of eth0

I copied my regular iptables config to a new one called /etc/iptables.ipv4.vpn.nat:

sudo cp /etc/iptables.ipv4.nat /etc/iptables.ipv4.vpn.nat

Then I edited the newly copied file and replaced eth0 with tun0.

sudo nano /etc/iptables.ipv4.vpn.nat

It ended up looking like this:

# Generated by iptables-save v1.4.14 on Sun Nov 2 22:21:20 2014
:INPUT ACCEPT [7:1139]
:OUTPUT ACCEPT [15:1057]
# Completed on Sun Nov 2 22:21:20 2014
# Generated by iptables-save v1.4.14 on Sun Nov 2 22:21:20 2014
:INPUT ACCEPT [17:929]
-A INPUT -i tun0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i tun0 -j DROP
-A FORWARD -i tun0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i wlan0 -o tun0 -j ACCEPT
# Completed on Sun Nov 2 22:21:20 2014

Step 4 – Restore the new iptables config

To get this working correctly you’ll need to restore this new iptables config:

sudo service openvpn stop
sudo iptables -F
sudo iptables -t nat -F
sudo iptables-restore /etc/iptables.ipv4.vpn.nat
sudo service openvpn start

Step 5 – Optionally have OpenVPN start automatically and restore this new iptable config on reboot

I have mine setup to start OpenVPN when the device reboots. To do this run:

sudo update-rc.d openvpn enable

And then edit /etc/network/interfaces and change the last line you added previously from:

up iptables-restore < /etc/iptables.ipv4.nat


up iptables-restore < /etc/iptables.ipv4.vpn.nat

 Part 2 – Complete!

At this point you now have a Raspberry Pi router that can route everything through Private Internet Access’ VPN. Next I’ll show you a couple of bash files that we’ll use to switch from a plain router to a VPN router as well as being able to choose which endpoint you want your VPN to connect to.


Part 3 – Installing and Configuring Tor

This part is pretty straight forward. There are some changes to the iptables that you’ll make but nothing too complex.

Step 1 – Install Tor

To install Tor:

sudo apt-get install tor

Step 2 – Configure Tor

To configure Tor you’ll need to create or edit /etc/tor/torrc:

sudo nano /etc/tor/torrc

Edit the file with this configuration:

Log notice file /var/log/tor/notices.log
AutomapHostsSuffixes .onion,.exit
AutomapHostsOnResolve 1
TransPort 9040
DNSPort 53

Step 3 – Flush the iptables

Next, you’ll want to flush the iptables:

sudo iptables -F
sudo iptables -t nat -F

Step 4 – Restore the regular iptables

And to be safe you should restore the regular iptables you configured previously:

sudo iptables-restore /etc/iptables.ipv4.nat

Step 5 – Modify the iptables

Create a SSH exception on port 22:

sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp --dport 22 -j REDIRECT --to-ports 22

Reroute DNS traffic:

sudo iptables -t nat -A PREROUTING -i wlan0 -p udp --dport 53 -j REDIRECT --to-ports 53

Reroute TCP traffic:

sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp --syn -j REDIRECT --to-ports 9040

Save this new configuration to /etc/iptables.ipv4.tor.nat:

sudo sh -c "iptables-save > /etc/iptables.ipv4.tor.nat"

Step 6 – Set up logging

sudo touch /var/log/tor/notices.log
sudo chown debian-tor /var/log/tor/notices.log
sudo chmod 644 /var/log/tor/notices.log

Part 3 – Complete!

If you want, you could start tor and your router would be routing everything through the Tor network.



Part 4 – Bash scripts to switch modes

Next you’re going to set up some bash scripts that will let you switch the router into each mode. But first, you’ll want to create a scripts directory that users can get to. For this I created the directory /usr/local/scripts.

Step 1 – Create a scripts directory

To do this type in:

sudo mkdir /usr/local/scripts
sudo chmod 755 /usr/local/scripts

If you want this directory in your PATH:

export PATH=$PATH /usr/local/scripts

Step 2 – Create the Regular Switch Script

This script will turn off OpenVPN and Tor.

sudo nano /usr/local/scripts/

Edit the file with the following:


#Stop OpenVPN
service openvpn stop

#Stop Tor
service tor stop

#Flush the iptables
echo "Flushing the iptables."
iptables -F
iptables -t nat -F
echo "Restoring iptables.ipv4.nat"
iptables-restore /etc/iptables.ipv4.nat

Step 3 – Create the OpenVPN Switch Script

This script will turn off Tor, configure OpenVPN correctly with the server of your choice, and turn OpenVPN on.

sudo nano /etc/local/scripts/

This script will take an argument of the server URL of your choice. Edit the file with the following:


#get url from bash arguments
echo "URL: $url"

#remove the old client.conf file
echo "Removing the current client file."
rm /etc/openvpn/client.conf

#write out the new client.conf file
echo "Writing the new client file."
echo "client
dev tun
proto udp
remote $url 1194
resolv-retry infinite
ca ca.crt
remote-cert-tls server
verb 1
reneg-sec 0
crl-verify crl.pem
auth-user-pass password.txt" > /etc/openvpn/client.conf
#Stop Tor
echo "Stopping Tor."
service tor stop

#flush the iptables
echo "Flushing the iptables."
iptables -F
iptables -t nat -F
echo "Restoring iptables.ipv4.vpn.nat"
iptables-restore /etc/iptables.ipv4.vpn.nat

#restart the openvpn service
echo "Restarting the openvpn service."
service openvpn restart

The way this script works is by calling it with a parameter of the URL of your choice. Private Internet Access has a bunch of different servers to choose from. The zip file listed earlier has each configuration, and really all you need from it are the URLs. For example, if you wanted to connect to their US East server you would use the script like this:

sudo sh /usr/local/scripts/

Simple enough.

Step 4 – Create the Tor Switch Script

This script will turn off OpenVPN, restore the Tor iptables, and turn the Tor service on.

sudo nano /usr/local/scripts/

Edit the file with the following:


#stop OpenVPN in case it's running
echo "Stopping OpenVPN"
service openvpn stop

#flush the iptables
echo "Flushing the iptables."
iptables -F
iptables -t nat -F
echo "Restoring iptables.ipv4.tor.nat"
iptables-restore /etc/iptables.ipv4.tor.nat

#Start Tor
echo "Starting the Tor service"
service tor restart

Part 4 – Complete!

You now have three scripts to switch the router between each mode.

To switch to the regular routing mode:

sudo sh /usr/local/scripts/

To switch to OpenVPN mode:

sudo sh /usr/local/

And to switch to Tor mode:

sudo sh /usr/local/



One last thing I built; a system tray application for windows:

I wrote a system tray application for Windows using C#, that allows me to switch my router’s mode. Originally it was only setup to work as a VPN router, which is why the application is called “V Pi N”. Once I got Tor installed, I updated it to be a mode switching application. Essentially it connects to my Pi router and runs the bash scripts I’ve configured to switch it between modes. I’ll probably release the source code once I’ve had a chance to clean it up a bit. Below is a screen shot of what it looks like.


Leave a Comment