vpn Archives - InputOutput.io

Hardening your VPN Setup with iptables

I’ll be heading out to Defcon 19 next month, so I want my VPN connection to be stable and secure.

You probably know the situation. You’re at your local coffee shop, using their (hopefully not) wide-open unsecured wifi hotspot. But you’re smart enough not to send all your data out over the clear, since there might be malicious script kiddies ready to take your sensitive data and sell it to kids on the street. So you use a VPN. You fire up OpenVPN and connect to your VPN service. Then you start browsing, comforted by the fact that your traffic is encapsulated in a secure SSL tunnel. Better yet, the user experience is transparent: you don’t have to configure your applications to manually use a SOCKS5 proxy. OpenVPN handles your routing tables and creates a virtual interface using the tun module. It’s so simple, you don’t need to think about it. But there’s a problem with this setup.

No one can reach into your stream and extract or insert data, but there’s a caveat. Anyone can destroy your TCP stream by sending you a spoofed RST packet from the remote server, or otherwise making the service unavailable to you. Destroying the TCP stream destroys the virtual (tun) interface, which, in turn, destroys the routes associated with that interface. Now you’re using your physical interface unprotected from those pesky hackers. Worse still, you don’t realize it. Not a thing has changed from the perspective of user experience. Since everything is transparent, you don’t notice any change at all. Now you’re screwed.

Little did you know that this all could have been avoided by our friend iptables. Sure, you could modify your routes further to ensure that only traffic going to the remote server goes over your physical interface, but that’s too easy. Plus, routing tables aren’t intended for security, they’re inteded to move packets along. iptables seems like the tool for the task, so I modified a script I found here to make sure that we disallow any traffic that we don’t want:

#!/bin/bash
if [[ $EUID -ne 0 ]]; then
	echo "This script must be run as root" 1>&2
	exit 1
fi

# name of primary network interface (before tunnel)
PRIMARY=wlan0

# address of tunnel server
SERVER=seattle.vpn.riseup.net
# address of vpn server
VPN_SERVER=seattle.vpn.riseup.net

# gateway ip address (before tunnel - adsl router ip address)
# automatically determine the ip from the default route
GATEWAY=`route -n | grep $PRIMARY | egrep "^0\.0\.0\.0" | tr -s " " | cut -d" " -f2`

# provided by pppd: interface name
TUNNEL=tun0

openvpn --config /my/path/to/riseup.ovpn --auth-user-pass /my/path/to/authentication.conf &

# iptables rules - important!

#LOCAL_NET=192.168.0.0/16
LOCAL_NET=$GATEWAY

# Flush all previous filter rules, you might not want to include this line if you already have other rules setup
iptables -t filter --flush

iptables -t filter -X MYVPN
iptables -t filter -N MYVPN

# Exceptions for local traffic & vpn server
iptables -t filter -A MYVPN -o lo -j RETURN
iptables -t filter -A MYVPN -o ${TUNNEL} -j RETURN
iptables -t filter -A MYVPN --dst 127.0.0.1 -j RETURN
iptables -t filter -A MYVPN --dst $LOCAL_NET -j RETURN
iptables -t filter -A MYVPN --dst ${SERVER} -j RETURN
iptables -t filter -A MYVPN --dst ${VPN_SERVER} -j RETURN
# Add extra local nets here as necessary

iptables -t filter -A MYVPN -j DROP

# MYVPN traffic leaving this host:
iptables -t filter -A OUTPUT -p tcp --syn -j MYVPN
iptables -t filter -A OUTPUT -p icmp -j MYVPN
iptables -t filter -A OUTPUT -p udp -j MYVPN

echo "nameserver 8.8.8.8" > /etc/resolv.conf

You’ll want to modify the openvpn command, interfaces, and servers to meet your needs. And that’s it! If your stream is taken down, you have these rules to protect you. I have this script as a post-connect hook for any untrusted networks I connect to (wicd is a nice network manager for adding hooks). Later, if you want your traffic to go over the clear again, you can use this script:

#!/bin/bash
if [[ $EUID -ne 0 ]]; then
	echo "This script must be run as root" 1>&2
	exit 1
fi

iptables -t filter --flush
iptables -t filter -X MYVPN

How to Subvert Deep Packet Inspection, the Right Way.

Note: I was first inspired to write this post based on the great coverage of deep packet inspection by the Security Now (SN) podcast.  For more detailed information than I could ever provide, please listen to Security Now, especially episodes 149, 151, and 153.

What is deep packet inspection?

In bygone days, the role of an Internet Service Provider (ISP) had been that of a passive provider of content.  The ISP provided the necessary infrastructure to connect your computer with the larger global network of computers, the internet.  When you pay your monthly bill to the ISP, you are paying a usage charge, effectively ‘renting’ their infrastructure to get yourself on the grid.  They did not disrupt, filter, or sell your private information, and life was good.
In 1994, Congress passed the Communications Assistance for Law Enforcement Act (CALEA).  This act required all digital telecommunications carriers to enable wiretapping of their digital switches.  In 2005, CALEA was extended, at the behest of the DOJ, FBI, and DEA, to include the tapping of all ISP traffic.  Prior to this extension, the FBI had relied on court order or voluntary cooperation of individual ISPs, engaging in packet sniffing with programs such as Carnivore.  So the government spying on your net usage is nothing new.
Recently, however, a very disturbing friendship has developed between advertising agencies and ISPs.  Particularly nefarious advertising companies such as NebuAd have been approaching ISPs and offering them sums of money if they will install devices that monitor and even modify the on-the-fly communications to place ads on websites that you visit.  Earlier on, these ads were just crudely inserted JavaScript, sometimes causing a rendering error in the page.  Recently, some companies such as Phorm in Britain have gotten smarter and are using the devices they’ve bribed the ISPs into installing to monitor each and every website you visit.  This is frightening because your browsing habits reveal an enormous amount of information about the type of person you are, and in fact in many cases pinpoint exactly who you are.  So these advertising agencies are effectively logging and storing everything that you do across the web, to build a profile of you for the supposed intent of providing more targeted advertising.  Luckily, there is a way to protect yourself from these invasive policies.

Using SSH to create a secure SOCKS proxy tunnel

Note: My experience in subverting these practices is largely based in using SSH within a bash environment.  You can perform the same actions with Windows using putty as well, but the syntax is quite different, and not my area of expertise.  I suggest using the howto on this page if you are using putty.

Requirements:

  • Remote shell account on a machine running an SSH server
  • An SSH client
  • Programs that allow you to proxy traffic with SOCKS

One very effective way to subvert deep packet inspection is to create a secure, encrypted tunnel that you send all of your traffic through.  The ISPs cannot modify the content of the packets if they are point-to-point encrypted, since they have no way of seeing what the content actually is.  The idea is to wrap the packets with encryption only so far as to get them out of the reach of your ISP, and once they arrive at a remote server that you have shell access to, that server unwraps the traffic and sends it out on its merry way.  Be sure that the remote server that you have access to is secure and trusted.  If it is not, you may effectively be opening yourself to a man-in-the-middle attack or packet sniffing.  If you have access to a remote shell, you can use SSH to create a secure SOCKS proxy on a specific port of your local machine, which forwards all traffic to the remote machine before reaching its final destination.  Simply type:

ssh -D localhost:port -f -C -q -N user@host.tld

where port is the local port you want to open.  When this command is issued for the first time, make a note of the hex fingerprint that is displayed.  If at any time in the future you get a warning stating that there is a fingerprint mismatch or that the fingerprint does not match your known_hosts file, your traffic may be being intercepted.  This fingerprint acts as verification that you are indeed opening a connection to the remote server you intend to communicate with.  Now, if you issue the command “netstat -antp” and if everything went well you will see a new local port being provided by ssh.  If under the ‘local address’ field, your output looks like the following: “127.0.0.1:port” then this port is only accessible locally.  You can now configure programs such as x-chat, pidgin, and firefox to use the ip address “127.0.0.1” with the port you have specified to enable this proxy.

Word of warning #1: What you gain in privacy on the ISP side, you may lose in anonymity on the remote server side.  For instance, if your remote server has a static IP and your ISP doesn’t, it may be easier for the websites you access to track your browsing habits over time.  One way to counter this is to have a multitude of people use this server as their primary proxy; that way there is no way of pinpointing who exactly is accessing what.

Word of warning #2: When configuring certain programs to use the SOCKS proxy, there is a potential for DNS leakage.  What this means is that even though the traffic between yourself and the remote server is encrypted, the name resolution may not be.  This may present a problem, but certain programs such as firefox allow you to ensure that there is no DNS leakage.  In firefox, browse to “about:config” and make sure the setting for “network.proxy.socks_remote_dns” is set to true.  Certain extensions of firefox such as FoxyProxy take care of this for you in their plugin settings.

Complete SSH encapsulation: the tun module

Requirements:

  • Root access to a remote machine running an ssh server
  • An SSH client
  • The tun module installed both locally and remotely

The problem that I had with the solution in the previous section is as follows.  There are plenty of programs using my network that do not have the ability to use a SOCKS proxy.  Given the track record of the worst of the advertising companies, I wouldn’t put it past them to start intercepting and modifying all sorts of traffic, not only the traffic with the highest volume or visibility such as web traffic.  What is really needed is an all-encompassing proxy, one that just takes all outgoing and incoming traffic and sends it over that secure encrypted link.  SSH is such a wonderfully flexible and versatile program, and it has built-in support for creating a secure VPN to do just that.  The idea is to make it so that all your traffic is routed through the remote server using a secure VPN link.  This section requires a basic grasp of routing tables, kernel modules, and iptables.

So our first task is to establish the secure VPN.  To do this, both machines must have the ‘tun’ kernel module installed and loaded.  Just issue the comman

modprobe tun

on both the local and remote machines from their respective root shells.  Locally, issue the command:

ssh -w 0:0 -f -C -q -N root@host.tld

This command establishes a new network interface on both sides of the connection, tun0.  Then, type:

ifconfig tun0 10.0.0.200 pointopoint 10.0.0.100

SSH into the remote machine, and issue these commands:

ifconfig tun0 10.0.0.100 pointopoint 10.0.0.200
ping -c 3 10.0.0.200

If you get a ping response, you’ve successfully set up a secure VPN!  This is good, but in order to route your traffic through the remote machine, it must be set up to enable packet forwarding, and also to have iptables configured so that it acts as a gateway.  I’ve modified a small shell script for this purpose.  You may need to modify it further to suit your needs:

wget http://www.inputoutput.io/shareconnection.sh
chmod +x shareconnection.sh
./shareconnection.sh

Your remote server is now configured to act as a gateway.  Locally, you must now set up your routing tables to direct all traffic (except the traffic that is still needed to keep the tun0 interface alive!) through the tun0 interface.  The following commands assume that your default local gateway is a router with the ip address 192.168.0.1, and your default interface is eth0:

route add host.tld gw 192.168.0.1 eth0
route del default gw 192.168.0.1 eth0
route add default gw 10.0.0.100 tun0

And presto!  All outbound and incoming traffic is now routed through your remote machine.  Again, the same concern in the above section regarding anonymity and verification of the remote fingerprint applies in this case as well.  Since the remote server is now acting as your gateway, there is no reason to fear DNS leakage, and no programs to configure.  Now you can rest assured that your connectivity is secure from the prying eyes of the ISPs and their sneaky cohorts, the traffic-shaping advertising companies.

My next article will detail how to connect this tunneled interface with programs such as hostap and dhcpd to create a wireless access point providing an automatically proxified connection to wireless clients.