Difference between revisions of "OpenVPN/RIPRouting"

From Secure Computing Wiki
Jump to: navigation, search
(Undo revision 1592 by Esubiguxoc (talk))
(Configuring OpenVPN)
 
Line 83: Line 83:
 
ns-cert-type server
 
ns-cert-type server
 
tls-remote "/C=AU/ST=VIC/L=Melbourne/O=XYZ/CN=router2/emailAddress=me@example.com"
 
tls-remote "/C=AU/ST=VIC/L=Melbourne/O=XYZ/CN=router2/emailAddress=me@example.com"
tls-client
+
tls-server
  
 
## Connections
 
## Connections
remote router1.example.com 1202
+
remote router2.example.com 1202
 
port 1202
 
port 1202
  

Latest revision as of 02:34, 5 December 2013

OpenVPN Topics

GENERAL: RoutingRIP RoutingBridgingFAQFirewallVPN ChainingHigh-AvailabilityTroubleshootingDonationsIRC meetingsDeveloper DocsTester Docs
OS RELATED: FreeBSD Routed FreeBSD Bridged

RIP and Routing

I have been trying to set up RIP with OpenVPN for a few days and found that there are lots of people on the Internet trying to do the same thing, but I could not find solutions easily with google, so I decided to document what I came up with (with lots of help form ##openvpn).

The basic scenario I have is a number of hosts (numbered 1-10 say) have VPNs set up in random configuration, between each other. I want to route traffic between the hosts regardless of which VPN is connected where. (This system is actually driven by a web interface that allows the VPNs to be established pretty randomly between hosts). If a link goes down, I want routes to change so that traffic can be carried through other VPNs in a mesh network.

What didnt work

I think its important to document what didnt work so as to save someone some time if they try to do it the same way. I first started using a standard client/server arrangement like in the manual. I immediately ran into a couple of problems:

  1. The client/server set up point to point IP addresses in a confusing way for the tunnel. For example the server might have its tun0 interface with 192.168.1.1 and the remote end is 192.168.1.2 while the client has tun0 at 192.168.1.6 pointtopoint 192.168.1.5. Both interfaces are /32 by default. What happens here is that quagga will receive a RIP update packet from 192.168.1.1 on tun0. According to the interface data the host 192.168.1.1 is not even on that interface. What might happen is that even if the route is added it will be disabled (because the client cant really reach 192.168.1.1 on any actual interface).
  2. I then tried using the topology directive to expand the interface to /30 which worked but I then ran into another problem. The server needs to have iroutes for the networks behind the client networks and it will not forward packets to remote networks behind the client unless it has iroutes for them. Since the whole point of using RIP is to avoid having to specify hard coded routes its impossible to maintain iroutes within OpenVPN for dynamic networks. In a sense OpenVPN is acting as a router by itself in client/server mode and it only supports having static routes put in (Wishlist: can OpenVPN understand RIP announcements and adjust iroutes by itself?).

What does work

After wasting time with this I realised that I needed point to point mode (--p2p which is the default). After I realised this the VPNs were set up in a matter of minutes so it is really easy to use - you just need to know how to do it.

The trick with p2p modes is that even though its called p2p - one end has to be the tls-server and the other must be the tls-client so they are not exactly the same (wishlist: can OpenVPN just switch modes if it doesnt work by itself so the two configs may be the same?).

Installing quagga

Quagga is a fork of zebra with an open license. Quagga has a similar interface to a Cisco IOS, but dont hold that against it - its still a daemon based program. I will be describing installing it on debian based distros but its pretty easy to set up everywhere:

apt-get install quagga

Edit the /etc/quagga/daemons file to enable zebra and ripd. Add the following two files to /etc/quagga:

/etc/quagga/zebra:

hostname Router
password zebra
enable password zebra

/etc/quagga/ripd:

hostname ripd
password zebra
log file /var/log/quagga/ripd.log
!
router rip
redistribute connected

So the default configuration is to enable RIP but not to give it any interfaces to actually send messages on. As the VPNs come up and down these interfaces are added using an up script.

Configuring OpenVPN

The OpenVPN configurations are:

ca   /etc/openvpn/ca.crt
cert /etc/openvpn/router2.crt
key  /etc/openvpn/router2.key
ns-cert-type server
tls-remote "/C=AU/ST=VIC/L=Melbourne/O=XYZ/CN=router1/emailAddress=me@example.com"
tls-client

## Connections
remote router1.example.com 1202
port 1202

## We set up the two end points
ifconfig 172.1.71.2 172.1.71.1

## This script does stuff when the vpn comes up (mainly sets up rip)
up "/etc/openvpn/vpn_up.py"

dev tun1
proto udp
resolv-retry infinite
float
persist-tun
persist-key
cipher BF-CBC
comp-lzo
keepalive 5 30

The other side is similar too:

ca   /etc/openvpn/ca.crt
cert /etc/openvpn/router1.crt
key  /etc/openvpn/router1.key
ns-cert-type server
tls-remote "/C=AU/ST=VIC/L=Melbourne/O=XYZ/CN=router2/emailAddress=me@example.com"
tls-server

## Connections
remote router2.example.com 1202
port 1202

## We set up the two end points
ifconfig 172.1.2.1 172.1.2.2

## This script does stuff when the vpn comes up (mainly sets up rip)
up "/etc/openvpn/vpn_up.py"

dev tun1
proto udp
resolv-retry infinite
float
persist-tun
persist-key
cipher BF-CBC
comp-lzo
keepalive 5 30

The things to note are:

  1. Each connection must be on a different port because the tunnels are point to point.
  2. The ifconfig line sets up the end points in opposite order.
  3. Each tunnel is set up on its own tun device (OpenVPN will just choose a tun device to use when a new connection is made). The device is passed the vpn_up.py script which adds the tun device to RIP.
  4. We specified persist-tun to maintain the tun interface even if the VPN went down. This allows routes to remain in the RIP tables if the VPN is dropped for a short time.

The vpn_up.py script just adds the new interface to the RIP daemon:

#!/usr/bin/python

import os

try:
    os.spawnl(os.P_WAIT, "/usr/bin/vtysh", "vtysh", 
    "-c", "configure terminal", 
    "-c", "router rip",
    "-c", "network %s" % os.environ['dev'])
except Exception,e:
    pass