Secure Firewall for OpenVPN

Creating a secure firewall is essential for any openvpn configuration.

First of all, I’d strongly recommend grabbing a copy of Linux Firewalls.
Its got a great section on iptables, with a look at all the commands available to you
as well as an example firewall configuration.

I have setup an openVPN which has a configuration where there are three different types of user.

1. Customers
2. Suppliers
3. Support

As far as the VPN knows, these are all the same thing -> a node on the network. It is in the firewall that I will put my rules to govern who can ‘see’ whom.

Customers are grouped into “Companies”. Every customer must be able to see every other customer
in their company.

Every supplier node must be able to see every customer that they have supplied a system to.

Every support agent must be able to see every customer.

All other connections should be blocked

Note of Caution
The *only* way to be able to have a chance of doing this kind of configuration is by knowing what each
nodes VPN ip address is, or what group of ip addresses it could be in.
That means that you have to use ccd in your sever settings

My Firewall
First, I make sure that ip forwarding is enabled on the server. You can check if it is enabled by typing

cat /proc/sys/net/ipv4/ip_forward

if it shows 0, it is disabled. 1 means enabled.

echo 1 > /proc/sys/net/ipv4/ip_forward

forces it to be enabled

Then, I run my firewall rules. First I want to ensure that the default behaviour for any packet is to be dropped

iptables --policy FORWARD DROP

I want to log anything that is passed between nodes:

iptables -A FORWARD -i tun0 -j LOG --log-level 6 --log-prefix 'Forward tun0 Log'

Then, for every pair of nodes that I want to see each other I run this command:

iptables -A FORWARD -i tun0 -s 10.2.2.5 -d 10.2.2.1 -j ACCEPT

That says allow packets to go from 10.2.2.5 to 10.2.2.1. Of course, for that to work, we
also need to allow packets to go the other way.

iptables -A FORWARD -i tun0 -s 10.2.2.1 -d 10.2.2.5 -j ACCEPT

Another Note Of Caution
In order for the above configuration to work, I push all routes to all nodes in my server.conf file
route 10.0.0.0 255.0.0.0
That means that the firewall is the ‘all powerful’ being that can control and change who can see what
at any point in time, without having to touch the vpn configuration.

Scripting the firewall
I’ve written a little python script to ensure that I don’t make errors when creating my firewall
every time a supplier/customer/support member is added.

Config File

The config file for the script is made up of 3 parts.
1. IP addresses. These map to the ones that you have assigned to each node in the ccd directory
of your server.conf setup.
2. PermissionGroups. These are groups of the ipaddresses useful for setting permissions
3. Permissions. These are the permissions that are setup for the firewall rules to fire against.

#config.py
#IP_ADDRESSES - create an ip address for each node in the vpn.

IP_OPEN_VPN_SERVER = "10.8.0.1" #not really needed, for reference only

#CompanyA
COMPANYA_CUSTOMER1 = "10.2.1.1"
COMPANYA_CUSTOMER2 = "10.2.1.5"
COMPANYA_CUSTOMER3 = "10.2.1.9"

GRP_COMPANY_A = [COMPANYA_CUSTOMER1, COMPANYA_CUSTOMER2, COMPANYA_CUSTOMER3]

#CompanyB
COMPANYB_CUSTOMER1 = "10.2.2.1"
COMPANYB_CUSTOMER2 = "10.2.2.5"
COMPANYB_CUSTOMER3 = "10.2.2.9"

GRP_COMPANY_B = [COMPANYB_CUSTOMER1, COMPANYB_CUSTOMER2, COMPANYB_CUSTOMER3]

#SUPPLIERS
SUPPLIER1 = "10.3.1.1"
SUPPLIER2 = "10.3.1.5"

#SUPPORT PEOPLE
SUPPORT1 = "10.1.1.1"
SUPPORT2 = "10.1.1.5"
SUPPORT3= "10.1.1.9"

GRP_SUPPORT = [SUPPORT1, SUPPORT2, SUPPORT3]

#PERMISSION GROUPS

#Who should support be able to see
PERM_SUPPORT = [COMPANYA_CUSTOMER1, COMPANYA_CUSTOMER2, COMPANYA_CUSTOMER3,
COMPANYB_CUSTOMER1, COMPANYB_CUSTOMER2, COMPANYB_CUSTOMER3]

PERM_COMPANY_A = [COMPANYA_CUSTOMER1, COMPANYA_CUSTOMER2, COMPANYA_CUSTOMER3]

PERM_COMPANY_B = [COMPANYB_CUSTOMER1, COMPANYB_CUSTOMER2, COMPANYB_CUSTOMER3]

PERM_SUPPLIER1 = PERM_COMPANY_A

PERM_SUPPLIER2 = PERM_COMPANY_B

#Permissions is a dictionary of 'this ip should be able to communicate with': [these ips]
#as a result, a path is created between each key and every ip in the values
PERMISSION_GROUPS = {GRP_SUPPORT: PERM_SUPPORT,
GRP_COMPANY_B:PERM_COMPANY_B,
GRP_COMPANY_A:PERM_COMPANY_A,
[SUPPLIER1]: PERM_SUPPLIER1,
[SUPPLIER2]: PERM_SUPPLIER2}

PERMISSIONS = {}
for group, permissions in PERMISSION_GROUPS.iteritems():
for ipaddress in group:
PERMISSIONS[ipaddress] = permissions

Firewall Script
Now here’s the firewall script that will turn your config file into a living, breathing firewall.

#autoConfigure.py
""This module deals with the ip rules for the customers, suppliers and support over the VPN!"""

from config import PERMISSIONS
import os

class SomethingWentWrongException(Exception):pass

def runFireWallRule(rule):
ans = os.system(rule)
if ans==0:
return True
else:
raise SomethingWentWrongException

def resetFireWall():
runFireWallRule("iptables -F")

def loadFireWall(logging=True):
#allow port forwarding
runFireWallRule("echo 1 > /proc/sys/net/ipv4/ip_forward")
runFireWallRule("iptables --policy FORWARD DROP")
if logging:
runFireWallRule("iptables -A FORWARD -i tun0 -j LOG --log-level 6 --log-prefix 'Forward tun0 Log'")
for rootIP, destinations in PERMISSIONS.items():
"""creates routed from the rootIP to destinationIP and back again"""
for destination in destinations:
if rootIP!=destination:
runFireWallRule("iptables -A FORWARD -i tun0 -s %s -d %s -j ACCEPT"%(rootIP, destination))
runFireWallRule("iptables -A FORWARD -i tun0 -s %s -d %s -j ACCEPT"%(destination, rootIP))

if __name__=='__main__':
resetFireWall()
loadFireWall()

Try running the autoconfigure.py file, as root, and see what the output is of iptables -L

Leave a Reply

Your email address will not be published. Required fields are marked *