The IPsec module incorporates different functions, which are grouped into various menu items. Since the start of our
project we have been offering IPsec features based on the legacy :code:`ipsec.conf` format, which we are migrating to
`swantcl.conf <https://docs.strongswan.org/docs/5.9/swanctl/swanctlConf.html>`__ as of version 23.1. While
migrating the existing featureset we came to the conclusion that the world has changed quite a bit and in order to
offer better (api) access to the featureset available we decided to plan for deprecation of the legacy "Tunnel settings" as they
have existed since we started. No timeline has been set, only a feature freeze on tunnels using the "Tunnel settings" menu item.
One of the main goals for the long run is to better align the gui components so they reflect the reality underneath, as we use
`strongswan <https://www.strongswan.org/>`__, our aim is to follow their terminology more closely than we previously did.
The following functions are available in the menu (as of OPNsense 23.1):
* Connections
* New configuration tool offering access to the connections and pools sections of the :code:`swanctl` configuration
* Tunnel Settings
* Legacy IPsec configuration tool
* Mobile Clients
* Offering access to various options of the `attr <https://docs.strongswan.org/docs/5.9/plugins/attr.html>`__ plugin and pool configurations for legacy tunnels
* Pre-Shared Keys
* Define `secrets <https://docs.strongswan.org/docs/5.9/swanctl/swanctlConf.html#_secrets>`__ to be used for local authentication.
* Key Pairs
* For public key authentication collect public and private keys.
* Advanced Settings
* Define passthrough networks (to exclude from kernel traps), logging options and some generic options
* Status Overview
* Shows tunnel statusses
* Lease Status
* For mobile clients, show address leases for various pools configured
* Security Association Database
* Shows security associations, the fundamental concept of IPsec describing a relationship between two or more entities
* Security Policy Database
* Installed security policies describing which traffic is allowed to pass a tunnel
* Virtual Tunnel Interfaces
* Edit or create new :code:`if_ipsec(4)` interfaces and show the ones created by legacy tunnels
Having used the tunnel settings from the early OPNsense days, some terminology might be a bit confusing when moving into the new options offered.
This paragraph aims to explain some of the common terms from the tunnel section and their new place in the connections.
For a full list of changes, the upstream migration `documentation <https://wiki.strongswan.org/projects/strongswan/wiki/Fromipsecconf>`__
is an interesting read as well.
* Phase 1 - The general connection settings, like local/remote addressess and general protocol settings. Choices in authentication to use
are also part of this, they may involve multiple rounds.
* Phase 2 - Nowadays Strongswan calls these **children**, as these define the :code:`CHILD_SA` subsections in play. This is where you can define
the networks on both ends. When multiple segments are being added into the same child, these are being treated as one policy
where all of them are able to communicate to eachother.
* Phase 1 / Tunnel Isolation - This option made sure every network defined in phase 2 would be treated as a child of it's own (e.g. two phase 2's would turn into two children)
* Phase 2 / Manual SPD entries - Manual SPD entries, this has been replaced with it's own menu option (Security Policy Database)
When setting up IPsec VPNs there are two main types of scenario's with their own advantages and disadvantages.
Policy based
--------------------------
The first one is the standard policy based tunnel, which guards the security of the tunnel with policies and installs kernel
traps to send traffic over the tunnel in case it matches these policies. For example a local network :code:`192.168.1.0/24`
sending traffic to a remote location responsible for :code:`192.168.2.0/24`. The advantage of this scenario is the ease of setup,
no routes are needed to be configured, when in this example :code:`192.168.1.10` contacts :code:`192.168.2.10` the packets
are seamlessly forwarded over the tunnel to the remote location.
When local traffic doesn't match the policies in question due to the tunnel needing Network Address Translation,
that's also possible as long as policies are manually added to the security policy database,
this is also referred to as "NAT before IPsec".
Route based (VTI)
--------------------------
Route based, also known as VTI, tunnels are using a virtual interface known as :code:`if_ipsec(4)`, which can be found under
:menuselection:`VPN -> IPsec -> Virtual Tunnel Interfaces`. This links two ends of the communication for routing purposes
after which normal routing applies. The "(Install) Policies" checkmark needs to be disabled in this case for the child (phase 1 in the legacy tunnel configuration)
definition. Usually the communication policy (phase 2 or child) is set to match all traffic (either :code:`0.0.0.0/0` for IPv4 or :code:`::/0` for IPv6).
So the same example as the policy based option would need (static) routes for the destinations in question (:code:`192.168.1.0/24` needs
a route to :code:`192.168.2.0/24` and vice versa), peering happens over a small network in another subnet (for example :code:`10.0.0.1` <-> :code:`10.0.0.2`)
bound to the tunnel interface.
The advantage of this type of setup is one can use standard or advanced routing technologies to forward traffic around tunnels.
In order to filter traffic on the :code:`if_ipsec(4)` device some tunables need to be set. Both :code:`net.inet.ipsec.filtertunnel`
and :code:`net.inet6.ipsec6.filtertunnel` need to be set to :code:`1` and :code:`net.enc.in.ipsec_filter_mask` and :code:`net.enc.out.ipsec_filter_mask`
need to be set to :code:`0` in order to allow rules on the device. The downside is that policy based tunnels (:code:`enc0`) can not be filtered
anymore as this changes the behaviour from filtering on the :code:`enc0` device to the :code:`if_ipsec(4)` devices.
..Warning::
Currently it does not seem to be possible to add NAT rules for :code:`if_ipsec(4)` devices.
In order to reliably setup a VTI tunnel, both ends should use static ip addresses. Although in the legacy configuration it
was possible to resolve hostnames, this will never lead to a stable configuration as the :code:`if_ipsec(4)` device
matches both source and destination `[#] <https://github.com/freebsd/freebsd-src/blob/c8ee75f2315e8267ad814dc5b4645ef205f0e0e1/sys/net/if_ipsec.c#L479>`__
before accepting the traffic and has no knowledge about any external changes.
The number of examples for the new module on our end is limited, but for inspiration it's often a good
idea to walkthrough the examples provided by `Strongswan <https://wiki.strongswan.org/projects/strongswan/wiki/UserDocumentation#Configuration-Examples>`__.
Quite some swanctl.conf examples are easy to implement in our new module as we do follow the same terminology.
In some (rare) cases one might want to add custom configuration options not available in the user interface, for this reason we
do support standard includes.
While the :code:`swanctl.conf` and the legacy :code:`ipsec.conf` configuration files are well suited to define IPsec-related configuration parameters,
it is not useful for other strongSwan applications to read options from these files.
To configure these other components, it is possible to manually append options to our default template, in which case files
may be placed in the directory :code:`/usr/local/etc/strongswan.opnsense.d/` using the file extention :code:`.conf`
IPsec configurations are managed in `swantcl.conf <https://docs.strongswan.org/docs/5.9/swanctl/swanctlConf.html>`__ format (as of 23.1), merging your own additions is possible by
placing files with a :code:`.conf` extension in the directory :code:`/usr/local/etc/swanctl/conf.d/`.
..Warning::
Files added to these directories will not be mainted by the user interface, if you're unsure if you need this, it's likely
a good idea to skip adding files here as it might lead to errors difficult to debug.
..Note::
Prior to version 23.1 it was also possible to add secrets and ipsec configurations in :code:`/usr/local/etc/ipsec.secrets.opnsense.d/`
and :code:`/usr/local/etc/ipsec.opnsense.d/`, with the switch to 23.1 these files are deprecated and should be manually migrated into swanctl.conf
As of version 24.1 OPNsense is able to use OCSP to validate client certificates when using the new Instances. Make sure :code:`Use OCSP (when available)`
is enabled in the trust section of the server instance and the CA used contains a proper :code:`AuthorityInfoAccess` extension
as described in our :doc:`Trust section <certificates>`.
The mechanism of client overrides utilises OpenVPN :code:`client-config-dir` option, which offer the ability to use
specific client configurations based on the client's X509 common name.
It is possible to specify the contents of these configurations in the gui under :menuselection:`VPN -> OpenVPN -> Client Specific Overrides`.
Apart from that, an authentication server (:menuselection:`System -> Access -> Servers`) can also provide client details in special cases when returning
:code:`Framed-IP-Address`, :code:`Framed-IP-Netmask` and :code:`Framed-Route` properties.
A selection of the most relevant settings can be found in the table below.
..csv-table:: Client Specific Overrides
:header:"Parameter", "Purpose"
:widths:30, 40
"Disabled", "Set this option to disable this client-specific override without removing it from the list"
"Servers", "Select the OpenVPN servers where this override applies to, leave empty for all"
"Common name", "The client's X.509 common name, which is where this override matches on"
"IPv[4|6] Tunnel Network", "The tunnel network to use for this client per protocol family, when empty the servers will be used"
"IPv[4|6] Local Network", "The networks that will be accessible from this particular client per protocol family."
"IPv[4|6] Remote Network", "These are the networks that will be routed to this client specifically using iroute, so that a site-to-site VPN can be established."
"Redirect Gateway", "Force the clients default gateway to this tunnel"
When configuring tunnel networks, make sure they fit in the network defined on the server tunnel itself to allow the server to send data back to the client.
For example in a :code:`10.0.0.0/24` network you are able to define a client specific one like :code:`10.0.0.100/30`.
To reduce the chances of a collision, also make sure to reserve enough space at the server as the address might already be assigned to a dynamic client otherwise.
WireGuard® is a simple yet fast and modern VPN solution, which in some cases is more convenient than IPsec or OpenVPN, certainly
in terms of options you need to configure. In our experience IPsec is the fastest solution for site-to-site connections, but Wireguard is the simplest
option to setup.
A wireguard setup on our end exists of the following main components:
* Instances: in the wireguard configuration these are called "interfaces" and they describe how the virtual :code:`wgX` device on our end is configured in terms of addressing and cryptography.
* Peers: these are the clients that are allowed to connect to us, described by their optional remote address including the networks that are allowed to pass through the tunnel. Peers belong to one or more instances.
.................................
Instances
.................................
In order to configure an instance, we start by adding one in the gui and generate a keypair. The public key is usually required for the
other end of the tunnel (peer). An unused port to listen on is required as well. The tunnel addresses are configured on the :code:`wgX` device
(which is always visible in :menuselection:`Interfaces --> Overview`).
By default, when "*Disable routes*" is not set, routes are created for each connected peer to the networks selected in "*Allowed IPs*", optionally
only a single gateway route might be configured as well.
..Note::
When choosing tunnel addresses, make sure the network defined includes the addresses being used by the peers. For
example when choosing :code:`10.10.0.1/24` the :code:`wgX` interface has this address configured and is able to accept
a peer using :code:`10.10.0.2/32`.
..Note::
Make sure to enable Wireguard in the general tab before adding instances.
..Tip::
Remember to create a firewall rule to allow traffic to the configured port and inside the tunnel.
.................................
Peers
.................................
Peers define the hosts that we exchange information with, which might be a road-warrior type or a static destination, in which case
you either provide or omit an "*Endpoint Address and Port*". At minimum you need the public key of the other party, optionally you may offer a pre-shared key
as additional security measure. The "*Allowed IPs*" define the networks that are allowed to pass the tunnel.
..Note::
In most cases the "*Allowed IPs*" list contains the networks used on the remote host and the peer ip address
(instance/tunnel address) configured on the other end.
..Tip::
When NAT and firewall traversal persistence is required, the :code:` Keepalive interval` can be used to exchange packets every defined
interval ensuring states will not expire.
.................................
High availability (using CARP)
.................................
When using wireguard on active/passive high availability clusters, only one instance at a time is allowed to communicate to the
other party. In OPNsense this can be reached by selecting a :code:`vhid` to track as instance dependancy {Depend on (CARP)}.
If an instance depends on a CARP vhid, it will query the current status and determine if the interface should be usable (when MASTER), the
interface status (up/down) will be toggled accordingly.
..Note::
As the interface itself will not change, all of its addresses and routes remain when not being active. This ensures a relatively
quick switch between roles.
..Tip::
Because the carp dependancy is managed per instance, you are able to keep tunnels available selectively, for example to manage the machines
remotely.
.................................
Diagnostics and debugging
.................................
In :menuselection:`VPN --> WireGuard --> Diagnostics` you can find the configured instances and peers including their last known
handshake and the amount of data being exchanged. For Instances you are also able to see if the device underneath (:code:`wgX`) is
up or down, depending on the carp status described in the previous chapter.
..Tip::
Althought wireguard itself offers very limit logging, our setup process will make a note of errors and signal about certain events.
When having issues configuring an instance or peer, always make sure to check the logs in :menuselection:`VPN --> WireGuard --> Log File` first.
..Warning::
When having issues exchanging packets between both ends of the tunnel, always make sure to check if the "*Allowed IPs*"
in the peer configurations contain the proper networks.
In case traffic is not allowed when traveling **in**, its dropped silently (a capture will not show it),
roughly the same happens when traveling **out**, a capture will show it, but nothing will be send out.
..Note::
Runtime debugging from the console is possible using the :code:`ifconfig` command,
for more information see the upstream `manual page <https://man.freebsd.org/cgi/man.cgi?wg(4)>`__
.................................
Examples
.................................
This paragraph offers examples for some commonly used implementation scenarios.