Site to site VPN with OPNSense

Preparation

This guide only covers what is left out elsewhere: to setup site-to-site VPN where two routers are connected and the subnets behind them can freely talk to each other through the tunnel.

To setup OpenVPN on OPNSense, please see their awesome documentation on setting up what they call site-to-site. I think what the documentation really means is opnsense to opnsense since with that setup I was unable to communicate between subnets.

Router connectivity

To enable the server to speak with its clients, first create an interface for the new openvpn server by going to Interfaces > Assignments and assigning the appropriate interface (usually named ovpns#). I'll call it VPN_SERVER.

This sets up reply-to in the firewall generated rules and assigns an address to the vpn interface (ovpns#) originally created by openvpn (see System > Gateways > Single). Having an address allows the server to talk to other computers on the network. The address assigned to the ovpns# is the first address in the tunnel subnet you specified when creating the openvpn server (e.g. 10.10.0.1).

The client already has an address assigned to its interface, so this step is only necessary for the server. I still do like to create interfaces for my vpn connections to allow for fine-grained control over firewall rules as I have different requirements depending on which server or client connection the router is handling.

Now enable both the client and server to talk to each other through the firewall by going to Firewall > Rules > <vpn interface name> and adding a rule which states to pass traffice through the interface you specified. I'll leave firewall configuration as an exercise to the reader as that is a large topic on its own right.

Here's an example to get you started

Action: pass
Quick: check
Interface: <name of interface you created or "OpenVPN">
Direction: in
TCP/IP Version: <IPv6 if you have it, IPv4 if you don't know>
Protocol: any
Source: any
Destination: any
Log: check
Description: whatever!
Save

I like to Log (put a checkmark) new rules to make sure they are evaluated at the right time and how I expect them. You can disable logging when you're confident about the rule.

Now you should be able to ping from one router to another.

Subnet connectivity

To allow computers behind routers to connect to each other, the router needs to be able to route the traffic between the two subnets and help the remote router understand how to route the response traffic. This is where NAT comes into play.

In short, assuming we have the following topology:

Subnet A (10.1.0.0/24) <---> Router A (10.1.0.1/24) <--vpn--> Router B (10.2.0.1/24) <---> Subnet B (10.2.0.0/24)

we will set up NAT on both Router A and Router B to allow Subnet A and B to communicate without having to each know what's going on on the other side of the link.

Fortunately for us, NAT should already be set up by opnsense for the openvpn server. To set it up for the client, you need a hybrid NAT setup where you allow opnsense to manage some, but not all NAT rules.

Go to Firewall > NAT > Outbound, select Hybrid outbound NAT rule generation and click Save. Then under Manual rules, click the plus button on the right, and add the following rule making sure to replace items as appropriate for your network.

Interface: <name of vpn interface>
TCP/IP Version: IPv6 if you know, otherwise IPv4
Protocol: any
Source address: Single host or Network
                then specify your LAN subnet
                (e.g. mine is 10.0.0.0/24)

Destination address: any
Translation / target: Interface address

This tells the router that if any computer from 10.0.0.0/24 subnets tries to pass traffic through the vpn tunnel, rewrite the request so the other side sends traffic back to me (the router) instead of the computer behind me. I (the router) will take care of the traffic routing once I get the reply.

Now you should be able to ping any host behind server's router successfully.

Add a similar NAT rule on the server and you'll be able to ping client subnet's hosts from the server subnet.

Routing (optional)

NOTE: The above setup relies on the automatic routing rules generated by opnsense based on the "remote network" specified in the openvpn settings. If you only have one openvpn server instance that is part of a site-to-site setup but is also used for road-warrior setup, you'll have to add those routes manually.

Name resolution

I have assigned different domains to each site. Enabling DNS from either side to the other is as simple as letting unbound know about the existence of the other domain through overrides.

Go to Services > Unbound DNS > Overrides, click the plus button under Domain Overrides, enter the remote side's domain, IP address of the remote router, and save.

Now you should be able to ping any host behind each router by name.