I have a static IP at OVPN but I want to route it from a Linux firewall. How do I fix this?

ovpn.com is a VPN service that offers VPN connectivity for OpenVPN and Wireguard. As of today ovpn.com has a beta release of static ip-addresses over Wireguard. As I, for some weird reason, love to collect ip-addresses I also have a few accounts at ovpn that has different tasks. They are however very much bound to a static interface and nothing less. The default solution does not allow you to forward the entire IP address somewhere else on your LAN, so if you need to give access to several machines this way, you have to set up port forwarding.

Now I have a server pool where different IP’s are routed to different places on my LAN Several years ago, I found out how to handle PRQ (Periquito) VPN routing, very much the same way when several ip-address was was configured.

But this problem can be solved both with OpenVPN and the WireGuard solution. Both OpenVPN and WireGuard allows post-up scripts where you explicitly can configure a more advanced routing.

Before starting #1

Before starting, remember when your VPN connectivity is about to be configured: Do a first traceroute from your VPN connection and see where the traffic goes like this:

root@ovpn-wg:/home/me# traceroute 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
 1  172.32.0.1 (172.32.0.1)  13.130 ms  12.973 ms  12.941 ms

As you can see, your first stop to internet is at 172.32.0.1 – you need to know this and set up your local server to be for example 172.32.0.2 (you use the entire network for this, like 172.32.0.0/24). For OpenVPN a similar set up is based on 10.127.0.0/24 instead.

Before starting #2

The first thing you should take care of, is the ip-forwarding. Go to /etc/sysctl.conf and change:

#net.ipv4.ip_forward=1
#net.ipv6.conf.all.forwarding=1

to …

net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1

This makes the changes permanent, since you probably want to use this at boot up. Then run sysctl -p to update the settings without the rebooting part. You have now ip forwarding rules activated.

OpenVPN

For OpenVPN, I realize this is much straight forward. When OpenVPN is executed you just have to replace the IP-addresses like this:

ip addr del 1.2.3.4/24 dev tun0
ip addr add 10.127.0.2/24 dev tun0
ip route add 1.2.3.4/32 dev eth0

For the moment, I usually set up the auto connectivity with OpenVPN with this script. At this point I have no better solution for a cronjob or service (I realize that I have to fix this too). So unless you use the script, there’s much of manually setting this solution up. By means, I’ve started to avoid this. But not only because cronjobbing OpenVPN is a pain, but also because OpenVPN compared to WireGuard is extremely slow. Mostly caused by the encryption libraries.

Coming this far, means you are probably ready to set up your LAN machine, so jump to that section from here.

WireGuard

For WireGuard, I actually used a new, clean, instance. I usually run openvz for my machines but OpenVZ does not support the user space setup that WireGuard requires. So instead, when I wrote this, I started with a new virtualbox server. If your machines or VM-host support wireguard, there would be no difference here for you.

Also, I use a bunch of scripts to make sure the OpenVPN is always running. This is not necessary for the WireGuard set up this far, so those parts are skipped.

Make sure you have the ip forwarding enabled as described above. Begin with installing WireGuard. This is done on Ubuntu 20.04, so it’s very straight forward from here too. As an option, you could install the recommended packages too, as in the example.

sudo apt install wireguard resolvconf

Copy your ovpn-config from ovpn and put it in /etc/wireguard. If you don’t know what this means, you have probably missed that part. You have to log in at ovpn.com and generate keys and the configuration first.

To entirely enable autostart on boot, run:

sudo systemctl enable wg-quick@vpn<num>-se-ipv4
sudo systemctl daemon-reload

After this, you are probably ready to connect.

sudo service wg-quick@vpn<num>-se-ipv4 restart

If everything works this far, you have this visible in your ip config (ip addr):

3: vpn<num>-se-ipv4: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none 
    inet <your-ip-address>/32 scope global vpn01-se-ipv4
       valid_lft forever preferred_lft forever

It is now time to check the trace, that was described before. See ”Before starting #1”, where you do the traceroute. If everything seems ok, you can now reconfigure your interface. Manually, it looks like this:

## SERVER
ip addr del <static-ip>/32 dev <vpn-device-name>
ip addr add 172.32.0.2/24 dev <vpn-device-name>
ip route add <static-ip> dev <local-network-device>
ip route add 0.0.0.0/1 dev <vpn-device-name>

The most likely scenario now, is that you won’t be able to reach the gateway from the server you’ve done this at. On the other hand, you will reach your client when the configuration is finished. This is probably cause by OVPN-firewalls. The local addresses are probably not permitted to communicate, since it has been set up for a static ip.

There might be more to fix here, for example OVPN endpoint is periodically pinging the static ip to check if it is alive. As we are forwarding traffic to another place, your server will report back that it is unavailable:

14:29:41.466350 IP 172.32.0.1 > <static-ip>: ICMP echo request, id 54127, seq 12, length 24
14:29:44.529574 IP 10.1.1.41 > 172.32.0.1: ICMP host <static-ip> unreachable, length 52

That is something that I still have to work with, as long as no client is configured.

So, let’s continue to the client configuration.

Client Configuration

This is the easiest part. As you can see below, we till use ip rules here. You probably have another ip address configured at your local computer, so we need to tell the routing tables where to put the inbound- and outbound traffic for the static ip address:

ip addr add <static-ip>/32 dev enp4s0
ip rule add from <static-ip>/32 table <tableId>
ip route add default via <wireguard-gateway> table <tableId>

How do I script this, serverside?

To make life a bit easier, you can also script the above solution. If you use the example here, you can for example put that script in /etc/wireguard/reroute.sh – do not forget to chmod +x /etc/wireguard/reroute.sh

Also make sure that you change localNet and wgIp to what fits your connection. localNet for example could also be eth0 or eth1, while wgIp is the value reflected in the above traceroute.

#!/bin/bash

vpnName=$1
localNet=enp0s3
wgIp=172.32.0.2/24
workDir=/etc/wireguard

echo "WireGuard"
if [ ! -f ${workDir}/${vpnName}.conf ] ; then
	exit
fi

ipAddr=$(grep Address ${workDir}/${vpnName}.conf | awk '{printf $3}')

echo "Reroute ${ipAddr} to ${localNet}, exit interface is now ${wgIp}."

ip addr del $ipAddr dev ${vpnName} >/dev/null 2>&1
ip addr del $wgIp dev $vpnName >/dev/null 2>&1
ip addr add $wgIp dev $vpnName

# Remove the route if is already there, to make errors silent.
ip route del $ipAddr dev $localNet >/dev/null 2>&1
ip route add $ipAddr dev $localNet

ip route add 0.0.0.0/1 dev ${vpnName}

When this is all done, add this row in the [Interface] section of the wireguard configuration:

PostUp = bash /etc/wireguard/reroute.sh %i

MASQUERADE notice

For this solution I never had to use any MASQUERADE-setup, but if you feel this is necessary, for example if you use many clients and this as a gateway and it’s absolutely necessary you can add this row:

iptables -t nat -A POSTROUTING -o <vpn-device-name> -j MASQUERADE

Probably this is less of a problem if you use the same ip-address network all the way out to the exiting point.

You’re done!

That’s it, folks!

If something went wrong, feel free to tell about it.