A blog on Computer Science, Security, Programming, and more...

HeapSpray Blog » Security » View Post

07
Jun
2014

Allow Traffic Only To VPN in Linux with iptables

Written by Matt

iptables is a little awkward if you're not used to it. The way that it works is that it attempts to match events against an ordered list of rules, and if none match then the default policy is used for that chain. iptables stops processing the list once there's a match, so if you have a very general rule at the top it will frustrate you when everything is allowed/blocked for seemingly no reason.

Here's a script to allow traffic from a physical interface (wlan0 or eth0) to just one IP (which could be a VPN IP).

#!/bin/bash

# Set your LAN subnet here
LANIP='192.168.1.0/24'

# Set the allowed destination IP (or IP range), port and protocol
DSTIP='8.8.8.8/32'
DSTPORT='1194'
DSTPROT='udp'

# flush all previous rules (reset iptables)
iptables -F

# drop INPUT and FORWARD if not matched (-P stands for policy, we're setting the default policy to DROP the packet if nothing below is matched)
iptables -P INPUT DROP 
iptables -P FORWARD DROP

# allow established sessions and localhost traffic (many programs rely on localhost connections)
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -s 127.0.0.0/8 -d 127.0.0.0/8 -i lo -j ACCEPT

# allow LAN traffic and traffic going to the VPN
iptables -A OUTPUT -d $LANIP -j ACCEPT
iptables -A OUTPUT -d $DSTIP -p $DSTPROT -m $DSTPROT --dport $DSTPORT -j ACCEPT

# drop everything else (on the real devices)
iptables -A OUTPUT -o wlan0 -j DROP
iptables -A OUTPUT -o eth0 -j DROP

Basically, the above says that anything to/from localhost, or anything that has either a LAN IP or the DST IP as its destination in the packet header will be allowed. Everything else going out of the wlan0 and eth0 devices is caught by the last two rules, and is dropped. Be careful about the order that you write these rules in, if I had put the last two rules at the top (after the -F rule), then ALL traffic would get instantly dropped, because those are two very general rules and they will match every single packet that leaves either interface. Once a rule is matched, later rules are not processed, and along with the two INPUT and FORWARD DROP policies at the top, I'd have isolated the OS from the network completely.

-A in the rules means append, so append to the chain OUTPUT or INPUT (this puts the rule at the bottom, as opposed to -I which stands for insert, and places the rule at the top, to be evaluated before any other rule). The line -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT is important otherwise we cannot get input responses from connections we open to the LAN, since the default INPUT policy is to drop. In the rest, -s stands for source (the source IP in the packet header), -d stands for destination (again, destination IP in the packet header), -p specifies the protocol (UDP or TCP, most of the time), and -j specifies the action to be taken if the rule matches, either ACCEPT (allow the packet) or DROP it. In the last two lines, -o signifies the output interface, the interface that the packets are being sent from, just as -i in the line for localhost means input interface. --dport is of course just destination port.

  • Name and Email fields are optional
  • Your email will not be public, only the administrator can see it
  • You are rate limited to one comment for every 10 minutes