Thursday, September 11, 2008

OpenVPN - Site-to-Site routed VPN between two routers

The following details the procedure for establishing a site-to-site routed VPN between two DD-WRT/vpn image enabled routers. The author tried the config on two Linksys WRT54GL(v1.1)

Procedure Summary

  1. Router Preparation.
  2. Install OpenVPN on your PC and generate your secret key.
  3. Configure one router as the server.
  4. Configure the second router as the client.
  5. Test the VPN connection.
  6. Advanced Configuration: Multiple routed networks.


Router Preparation

At the time of writing, the latest available DD-WRT package is DD-WRT v24sp1 (10/8/08). Before proceeding, you need to download the VPN-flavoured version of DD-WRT from the DD-WRT Download Page.

Due to the fact that most of us have DHCP-assigned dynamic IPs, you are also recommended to create a dynamic dns host for the server router. More information on this procedure is available here.

Finally, make sure that your two routers are not distributing an overlapping IP subnet range. Usually, all routers come preconfigured with a 192.168.1.0 DHCP range distribution. Since you are doing routed configurations, you need to change the 192.168.1.0 subnet to another one. The easiest way is to adopt a sequential assignment:

Server side: 192.168.1.0 Client1 side: 192.168.2.0 Client2 side: 192.168.3.0 etc...

This way, when your internal networks communicate with each other, they don't overlap and you don't end up having miscommunication.

If you are looking for a bridged configuration, you'd better check this page instead.

Secret Key Generation

Prior to configuring your routers, you need to create a shared secret key. This key will be used to authenticate and encrypt your site to site communication.

Start by downloading the latest OpenVPN package from OpenVPN's main site. Install the package (Usually gets installed in C:\Program Files\OpenVPN if you are running Windows). Now, get a command prompt and issue the following command from the OpenVPN directory:

openvpn --genkey --secret static.key

This will create a text file named 'static.key'. Opening it in Notepad, or any text editor will get you an output similar to the following one:

#
# 2048 bit OpenVPN static key
#
-----BEGIN OpenVPN Static key V1-----
aeb68165149e096d8f04252dd22fe67d
dd15d8c87e8a577c5c14ebd1ef0bf0b6
0e1d652f91fe66ed3774505e641936dd
458a6db60fb36b969d8bcd37803cf1d3
6d49383ec2daa1d2ae70e3ca49b950a4
bba985940e5e4a15fac702cbcf47f9d0
39f7939980bbb63d2964bb6216471162
0a519fe25d1e0d48044a1ad85dc94758
af6f7b7c52ccaaefa3d013fcbf621366
5ea18d9dc36c3b2a9ac277a9903998fe
45e10b0f79fd443727c3f30278981b3d
0fa525ad843645b4acc28969450bd601
4ce774aba0e830149489dc1592741580
fbd3cd24cc7baa68e06b3e3aedae2565
a36b8a3f687ddbb78411740d755249cf
45c0617c215b66eabc72f60f47b32c64
-----END OpenVPN Static key V1-----

Warning: Don't go lazy and copy the above, doing so will jeopardize your secure connection, recreate the file from scratch.


Server Configuration

Using Notepad or any text editor, create the following two configurations:


Config 1

# Move to writable directory and create scripts
cd /tmp
ln -s /usr/sbin/openvpn /tmp/myvpn

# Config for Site-to-Site SiteA-SiteB
echo "
proto udp
port 2000
dev tun0
secret /tmp/static.key
verb 3
comp-lzo
keepalive 15 60
daemon
" > SiteA-SiteB.conf

# Config for Static Key
echo "
-----BEGIN OpenVPN Static key V1-----
................................................
...YOUR SECRET KEY TEXT SHOULD BE PASTED HERE...
................................................
-----END OpenVPN Static key V1-----
" > static.key

# Create interfaces
/tmp/myvpn --mktun --dev tun0
ifconfig tun0 10.0.0.1 netmask 255.255.255.0 promisc up

# Create routes
route add -net OTHERSUBNET netmask 255.255.255.0 gw 10.0.0.2

# Initiate the tunnel
sleep 5
/tmp/myvpn --config SiteA-SiteB.conf

Warning: Watch out for the OTHERSUBNET chunk, you should replace it with your client network's subnet (for example: 192.168.2.0 or 192.168.3.0).

Also, do note that the static key that was created in the previous step should be pasted in the appropriate section, right after the 'echo text.


Now, create a second configuration with the following text.

Config 2

# Open firewall holes
iptables -I INPUT 2 -p udp --dport 2000 -j ACCEPT
iptables -I FORWARD -i br0 -o tun0 -j ACCEPT
iptables -I FORWARD -i tun0 -o br0 -j ACCEPT

Now, go to your Router configuration interface, click on 'Administration' then 'Commands'. Paste your 'Config 1' in your 'Startup' section and you 'Config 2' in your 'Firewall' section.

You're done with the server configuration!


Client Configuration

The client configuration is very similar to the server configuration, with a few small modifications.

Again, you need to create two configs:


Config 1

# Move to writable directory and create scripts
cd /tmp
ln -s /usr/sbin/openvpn /tmp/myvpn

# Config for Site-to-Site SiteA-SiteB
echo "
remote REMOTEADDRESS
proto udp
port 2000
dev tun0
secret /tmp/static.key
verb 3
comp-lzo
keepalive 15 60
daemon
" > SiteA-SiteB.conf

# Config for Static Key
echo "
-----BEGIN OpenVPN Static key V1-----
................................................
...YOUR SECRET KEY TEXT SHOULD BE PASTED HERE...
................................................
-----END OpenVPN Static key V1-----
" > static.key

# Create interfaces
/tmp/myvpn --mktun --dev tun0
ifconfig tun0 10.0.0.2 netmask 255.255.255.0 promisc up

# Create routes
route add -net OTHERSUBNET netmask 255.255.255.0 gw 10.0.0.1

# Initiate the tunnel
sleep 5
/tmp/myvpn --config SiteA-SiteB.conf

Warning: Watch out for the OTHERSUBNET chunk, you should replace it with your server network's subnet (for example: 192.168.1.0).

Also, do note that the static key that was created in the previous step should be pasted in the appropriate section, right after the 'echo text.

In addition to the above, and since this is your client, you need to replace the REMOTEADDRESS with your server's IP address or the dynamic DNS address you created in the previous Router Preparation section.


Now, create a second configuration with the following text.


Config 2

# Open firewall holes
iptables -I INPUT 2 -p udp --dport 2000 -j ACCEPT
iptables -I FORWARD -i br0 -o tun0 -j ACCEPT
iptables -I FORWARD -i tun0 -o br0 -j ACCEPT

Now, go to your Router configuration interface, click on 'Administration' then 'Commands'. Paste your 'Config 1' in your 'Startup' section and you 'Config 2' in your 'Firewall' section.

You're done with the client configuration!

VPN Tests

I am getting many emails from people asking for this section, so I'll try to add some meat. Let me know what you think about it.

Due to the fact that our routed VPN configuration is not 'natively' supported by DD-WRT, but rather an ad-hoc one. There is no direct way to get information through the router's web interface. Instead, I propose the following two alternatives/suggestions:


First Technique: Shell Logging

Add logging to the VPN tunnel operation. This can be done by inserting the following line in the client and/or server configuration:

log /tmp/openvpn.log

This will instruct openvpn to create a log file named 'openvpn.log' in /tmp. By enabling Telnet or SSH and connecting to your router, you should be able to get the logging output by issuing the following command:

router$ less /tmp/openvpn.log

You need to use your arrow keys to scroll up and down in the log and 'q' to exit the scroller.

Warning: This should only be used for testing and debugging purposes as it generates extra load on your router, as well as eating up valuable space in memory.


Second Technique: Use Syslog

Syslogging is an excellent way to get all sorts of information on your routers. In addition to OpenVPN alerts and tunnel stats, you can get router access, DHCP usage, etc... Pretty much everything using Syslogging. Unless a 'log' stanza is present in the openvpn config file, openvpn will dump all the logging to syslog by default.
The recipe:
1. Open your browser and connect to your router's interface. Click on 'Services' and scroll all the way down (I am assuming DD-WRT RC4 and above has been flashed on your router).
2. Locate the 'System Log' section and click on 'Enable' next to syslogd. This will add one more space called 'Remote Server' right underneath 'syslogd', type in your computer's IP address or preferably any other workstation that can successfully ping the router.

   Image:Syslogview.JPG  


3. Download a Syslog Daemon and viewer, there is an excellent freeware version available at Kiwi Enterprises' website that I'm linking here.
4. Install the syslog daemon and don't forget to enable it, this can be done in the Kiwi Sylog Application's toolbar: Click on the 'Manage' menu then successively select 'Install the Service' then 'Start the Service'. You can verify that the syslog service is operational by pressing 'Ctrl+T', this should send a test message on the console.
5. To test it immediately, force your router to reboot and voila! You should see all messages coming from your router (including VPN initiation and communication messages) appearing on your Kiwi Syslog console page. If you are creating several VPN connections, you can configure all your routers to redirect their syslog to one PC, allowing you to easily monitor all your networks from one site! I'm currently managing 4 VPNed locations and this tool has proved to be invaluable to me.

Advanced Configuration: Multiple routed networks

Warning: This section is not for the faint-hearted people. Please read carefully and email me should you have any questions/comments/thoughts. Wiki is all about teamplay!

Let's assume we need to configure a 3-sites VPN connection as per the following figure:
Image:3sites-vpn.jpg

Attention: I tried keeping this technique simple and didn't use Certificates/CAs. Should you be interested in more complex scenarios, I do consultancy work and would gladly assist you.

You need to first start by duplicating the above Client configuration on the two 'Client1' and 'Client2' routers. Pay extra attention to the IPs and IP ranges you are using and write down your configs. In essence, both clients will have pretty much the same configuration with one minor change. Since both will be connecting to the same server, you cannot use the same port number for both clients, so we will be giving port 1999 for the first client and 2000 for the second client.
Also, we need to tell Client1 how to reach Client2's subnet and vice-versa. This means including a second routing entry in our configuration. As such, our configurations will look pretty much like the following:

Client1 Configuration

Client1 -- Startup

# Move to writable directory and create scripts
cd /tmp
ln -s /usr/sbin/openvpn /tmp/myvpn

# Config for Site-to-Site Client1-Server
echo "
remote REMOTEADDRESS
proto udp
port 2000
dev tun0
secret /tmp/static.key
verb 3
comp-lzo
keepalive 15 60
daemon
" > Client1-Server.conf

# Config for Static Key
echo "
-----BEGIN OpenVPN Static key V1-----
................................................
...YOUR SECRET KEY TEXT SHOULD BE PASTED HERE...
................................................
-----END OpenVPN Static key V1-----
" > static.key

# Create interfaces
/tmp/myvpn --mktun --dev tun0
ifconfig tun0 10.0.1.2 netmask 255.255.255.0 promisc up

# Create routes
route add -net SERVERINTERNALSUBNET netmask 255.255.255.0 gw 10.0.1.1
route add -net CLIENT2INTERNALSUBNET netmask 255.255.255.0 gw 10.0.1.1

# Initiate the tunnel
sleep 5
/tmp/myvpn --config Client1-Server.conf


Client1 -- Firewall

# Open firewall holes
iptables -I INPUT 2 -p udp --dport 2000 -j ACCEPT
iptables -I FORWARD -i br0 -o tun0 -j ACCEPT
iptables -I FORWARD -i tun0 -o br0 -j ACCEPT

Client2 Configuration

Client2 -- Startup

# Move to writable directory and create scripts
cd /tmp
ln -s /usr/sbin/openvpn /tmp/myvpn

# Config for Site-to-Site Client2-Server
echo "
remote REMOTEADDRESS
proto udp
port 1999
dev tun0
secret /tmp/static.key
verb 3
comp-lzo
keepalive 15 60
daemon
" > Client2-Server.conf

# Config for Static Key
echo "
-----BEGIN OpenVPN Static key V1-----
................................................
...YOUR SECRET KEY TEXT SHOULD BE PASTED HERE...
................................................
-----END OpenVPN Static key V1-----
" > static.key

# Create interfaces
/tmp/myvpn --mktun --dev tun0
ifconfig tun0 10.0.2.2 netmask 255.255.255.0 promisc up

# Create routes
route add -net SERVERINTERNALSUBNET netmask 255.255.255.0 gw 10.0.2.1
route add -net CLIENT1INTERNALSUBNET netmask 255.255.255.0 gw 10.0.2.1

# Initiate the tunnel
sleep 5
/tmp/myvpn --config Client2-Server.conf


Client2 -- Firewall

# Open firewall holes
iptables -I INPUT 2 -p udp --dport 1999 -j ACCEPT
iptables -I FORWARD -i br0 -o tun0 -j ACCEPT
iptables -I FORWARD -i tun0 -o br0 -j ACCEPT


Server Configuration

As for the server, we need to perform three modifications:
1. Tell the server to listen to 2 connections, one on port 1999 and the other on port 2000. This can be done by running the openvpn daemon twice (As you will see in the coming configuration, we will be creating two TUN interface, called 'tun0' and 'tun1').
2. Make sure to add a route to the two clients.
3. Allow Client-to-Client connection in the Firewall configuration script.

Server -- Startup

# Move to writable directory and create scripts
cd /tmp
ln -s /usr/sbin/openvpn /tmp/myvpn

# Config for Site-to-Site Server-Client1
echo "
proto udp
port 2000
dev tun0
secret /tmp/static.key
verb 3
comp-lzo
keepalive 15 60
daemon
" > Server-Client1.conf

# Config for Site-to-Site Server-Client2
echo "
proto udp
port 1999
dev tun1
secret /tmp/static.key
verb 3
comp-lzo
keepalive 15 60
daemon
" > Server-Client2.conf

# Config for Static Key
echo "
-----BEGIN OpenVPN Static key V1-----
................................................
...YOUR SECRET KEY TEXT SHOULD BE PASTED HERE...
................................................
-----END OpenVPN Static key V1-----
" > static.key

# Create interfaces
/tmp/myvpn --mktun --dev tun0
/tmp/myvpn --mktun --dev tun1
ifconfig tun0 10.0.1.1 netmask 255.255.255.0 promisc up
ifconfig tun1 10.0.2.1 netmask 255.255.255.0 promisc up

# Create routes
route add -net CLIENT1INTERNALSUBNET netmask 255.255.255.0 gw 10.0.1.2
route add -net CLIENT2INTERNALSUBNET netmask 255.255.255.0 gw 10.0.2.2

# Initiate the tunnel
sleep 5
/tmp/myvpn --config Server-Client1.conf
/tmp/myvpn --config Server-Client2.conf

Server -- Firewall

# Open firewall holes for Client1
iptables -I INPUT 2 -p udp --dport 2000 -j ACCEPT
iptables -I FORWARD -i br0 -o tun0 -j ACCEPT
iptables -I FORWARD -i tun0 -o br0 -j ACCEPT

# Open firewall holes for Client2
iptables -I INPUT 2 -p udp --dport 1999 -j ACCEPT
iptables -I FORWARD -i br0 -o tun1 -j ACCEPT
iptables -I FORWARD -i tun1 -o br0 -j ACCEPT

# Allow Forwarding packets between Client1 and Client2
iptables -I FORWARD -i tun0 -o tun1 -j ACCEPT
iptables -I FORWARD -i tun1 -o tun0 -j ACCEPT


Troubleshooting / FAQ

I will be including in this section any troubleshooting questions I received as well as their solution (If I have one or if the sender found a fix for it).

DMZ feature is used on your DD-WRT router

If you decide to run OpenVPN on your DD-WRT based router, make sure to disable any DMZ as the DMZ will override the usual port forwarding needed by your OpenVPN clients/server and would forward all connection requests to the DMZ host.

My tunnel is up but I cannot ping the remote endpoint

Yes, this is normal if the router is set to be not 'pingable' (The option is set by default). To rectify this and allow your server-side and client-side hosts to ping both routers' endpoints while making sure that external hosts (Not belonging to your networks) still don't ping your routers' interfaces, add the following entry to your Firewall section in both routers:

iptables -I INPUT 3 -i tun0 -p icmp -j ACCEPT

Great! How about internal remote administration through HTTP?

Well, in that case you will have to do the same operation as in the previous issue (i.e. Cannot ping the remote endpoint) and add an extra iptables command in your Firewall section in both routers:

iptables -I INPUT 1 -i tun0 -p tcp --dport 80 -j ACCEPT

Why should I use a routed configuration and not a bridged configuration

Interesting question. Well, a bridged configuration will 'join' both networks together as one, same subnet, same IP range... Looks easier, but the problem here would be that all kinds of packets, including the infamous broadcasts will be traveling from one side of the network to the other, resulting in less-than-optimized usage of your precious bandwidth. On the other hand, a routed network will only send directed packets from one side of the network to the other.

I have a problem connecting my VPNs while using Chillispot, what's the issue?

The problem here is that Chillispot insists on using 'tun0' as a communication tunnel. The easiest solution is to simply replace your 'tun0' with another tunnel ('tun2', 'tun3', etc...)
Also, you need to make sure that both your firewall and startup sections are updated accordingly.

[edit] DHCP Forwarder / DHCP Server feature of DD-WRT

Please take note that this VPN configuration will not work if your router(s) is/are set up as DHCP forwarders. They must be DHCP servers in order for the VPN to connect properly.

Remarks

This should get you right in business and activate Site-to-Site routing between all Clients and the Server. I'm personally running 4 VPN connections using the above mentioned model without any issue whatsoever!

Please share your thoughts, comments and experiences!

No comments: