OpenBSD OpenVPN Site to Site VPN Behind a NAT gateway
This configuration arose from a situation where a DR site was setp in a business hotel. The ISP could not provide a public routable ipv4 address for the firewall that went into the hotel suite to connect back to the corporate network. We were able to get a static natted ip. The hotel ISP firewall was fairly restrictive in terms of what ports and protcols it would allow outbound. In particular we had trouble keeping our ipsec tunnels up and running and IPSEC over UDP encap was not working properly. OpenVPN was a better choice for this setup:
Main Site: Debian Linux with OpenVPN 2.1.3, public static ip a.b.c.d
DR Site: OpenBSD 4.6 with package: OpenVPN 2.1rc15p2; static ip 192.168.1.10 natted to w.x.y.z by upstream hotel ISP firewall.
The main site is also running an existing OpenVPN instance on the standard port 1194/udp for client users so we wil create a separate instance of OpenVPN to handle the site to site tunnel.
The hotel also forces all traffic to use its http proxy or else outbound http is blocked. We will use pf rules so that browsers will work w/o needing the proxy manually set (transparent redirect):
Step 1. generate a static key, save it in the file: /etc/openvpn/static.key
openvpn --genkey --secret static.key
Copy this key to the other gateway and save it in the same location.
Step 2. Open port udp 10000 inbound on each firewall from the partner firewall.
Here are the OpenBSD pf.conf changes, port 10000 udp would be opened on the linux firewall using iptables.
Section 1 macros - we define a bypass table of ips that will not be redirected.
table <bypass_proxy> persist file "/opt/scripts/bypass_proxy.conf"
The contents of this bypass file contain the networks that will not be redirected:
172.30.0.0/16
Section 4. Nat rules:
# Exclude the ips in the bypass table from redirect on port 80 outbound:
no rdr on $int_if proto tcp from any to <bypass_proxy> port www
# redirect port 80 outbound to the bus hotel proxy:
rdr on $int_if proto tcp from {$lan} to any port www -> \
10.168.195.254 port 8080
## no nat vpn traffic:
no nat on $ext_if from 172.30.0.0/16 to 172.30.0.0/16
## nat lan traffic:
nat on $ext_if from $lan to any -> $fwip
Section 5. pass rules:
pass in quick on $ext_if proto udp from $hqfwip to $fwip port 10000 keep state
pass in quick on tun0
pass out quick on tun0
Step 3. Build the tunnel scripts:
Here is the OpenBSD side script. You should test with just running the openvpn process command by itself, without the ampersand (that backgrounds it) and without the route statements first on each side. Once you can ping the tunnel ips from each side you can procede with the static route adds.
In this example the OpenBSD side has a tunnel ip of 192.168.254.10, with the linux gateway having .9
The 172.30.40.0/24 network is behind the OpenBSD side. The linux side has several 172.30.x networks, which are listed in the setup script:
The OpenBSD box has a private static NAT ip - 192.168.1.10, so the linux side refers to this public nat ip in its tunnel configuration which is w.x.y.z. The public ip of the linux gateway is a.b.c.d. The hotel ISP gateway NATs the traffic from w.x.y.z to 192.168.1.10. The openvpn configs must not use this private ip on the OpenBSD gateway - they need to use the public ip.
The 192.168.254.9 and 10 addresses were chosen at random, they are not important other than they are used for the tunnel endpoints.
OpenBSD vpn setup script:
#!/bin/sh
echo "Current OpenVPN site to site Process:"
ps ax | grep [/]etc/openvpn/static.key
echo "Killing current openvpn process:"
ps ax | grep [/]etc/openvpn/static.key | awk {'print $1'} | xargs kill -9
sleep 3
echo "Creating new process"
/usr/local/sbin/openvpn --secret /etc/openvpn/static.key --remote a.b.c.d --dev tun0 --ifconfig 192.168.254.10 192.168.254.9 --verb 1 --port 10000 &
sleep 6
echo "Adding routes:"
route add -net 172.30.20.0/23 192.168.254.9
route add -net 172.30.36.0/24 192.168.254.9
route add -net 172.30.4.0/23 192.168.254.9
route add -net 172.30.32.0/23 192.168.254.9
echo "Current OpenVPN site to site Process:"
ps ax | grep [/]etc/openvpn/static.key
echo "Done!"
Here is the linux side vpn setup script:
There are 2 openvpn instances on the linux box, so the script is careful only to stop the process that is handling the site to site vpn.
#!/bin/bash
echo "Current OpenVPN site to site Process:"
ps ax | grep [/]etc/openvpn/static.key
echo "Killing current openvpn process:"
ps ax | grep [/]etc/openvpn/static.key | awk {'print $1'} | xargs kill -9
sleep 3
echo "Creating new process"
/usr/local/sbin/openvpn --secret /etc/openvpn/static.key --remote w.x.y.z --dev tun1 --ifconfig 192.168.254.9 192.168.254.10 --verb 1 --port 10000 &
sleep 6
echo "Adding routes:"
route add -net 172.30.40.0/24 gw 192.168.254.10
echo "Current OpenVPN site to site Process:"
ps ax | grep [/]etc/openvpn/static.key
echo "Done!"
