Project

General

Profile

Virtual IP

IKEv1 and IKEv2 both know the concept of virtual IPs. This means that the initiator requests an additional IP address from the responder to use as inner IPsec tunnel address.

In IKEv1, virtual IPs are exchanged using the mode config extension. IKEv2 has full support for virtual IPs in the core standard using configuration payloads.

strongSwan currently implements one scenario with IKEv2 configuration payloads, where an IP address is assigned to the initiator (since 5.0.1 multiple addresses can be assigned from multiple pools). The opposite is possible by the protocol, but is an uncommon setup and therefore not supported. It is supported for IKEv1, though, with mode config in push mode.

Initiator Configuration

To request an arbitrary virtual IP from the responder the client configures the following:

Configuration File IPv4 IPv6
swanctl.conf connections.<conn>.vips = 0.0.0.0 connections.<conn>.vips = ::
ipsec.conf leftsourceip=%config leftsourceip=%config6

It is possible to request a specific address by setting:

Configuration File IPv4 IPv6
swanctl.conf connections.<conn>.vips = 10.3.0.5 connections.<conn>.vips = 2001:db8::1
ipsec.conf leftsourceip=10.3.0.5 leftsourceip=2001:db8::1

However, the responder may return a different address, or may not return one at all.

To use a specific and static virtual IP (i.e. without exchanging any configuration payloads) it may simply be added to any local interface (even lo) and referenced in the client's local traffic selector (local_ts in swanctl.conf or leftsubnet in ipsec.conf). Configuring such an IP as in the example above will not have the intended effect because the IP won't get installed on the system unless the server actually assigns that IP to the client with a configuration payload.

The traffic selectors in swanctl.conf and ipsec.conf (local|remote_ts and left|rightsubnet, respectively) default to the value %dynamic. If virtual IPs are used, this value gets dynamically replaced by the received or assigned virtual IP.
Therefore, no local traffic selector must be configured on the client and no remote traffic selector on the server when using virtual IPs. This ensures the client's traffic selector is correctly narrowed to the assigned virtual IP.

Since 5.0.1 a client may request multiple IP addresses by listing a comma-separated combination of %config4, %config6 or fixed IP addresses in leftsourceip, respectively multiple IP addresses in connections.<conn>.vips. Configuring %config in leftsourceip will request an address of the traffic selectors' address family.
The main use case is for dual-stack hosts to request a virtual IP of each address family:

Configuration File IPv4 & IPv6
swanctl.conf connections.<conn>.vips = 0.0.0.0, ::
ipsec.conf leftsourceip=%config4,%config6

This is also illustrated in the ikev2/ip-two-pools-v4v6 test scenario.

DNS servers

Before 5.0.1 the client couldn't explicitly request other attributes, but it may still have requested and processed the DNS attribute (depending on the loaded plugins). With current releases DNS servers may explicitly be requested with the leftdns option in ipsec.conf (there is nothing similar in swanctl.conf). Received DNS servers are handled, for instance, by the resolve plugin, which uses the resolvconf utility to install them or writes them to /etc/resolv.conf (or another file specified with the --with-resolve-conf configure directive).

Implementation

On Linux, the virtual IP addresses will be installed on the outbound interface by default (may be changed, since 5.0.1, with the charon.install_virtual_ip_on option) and source routes will be installed in the routing table configured with charon.routing_table in strongswan.conf (or ./configured with --with-routing-table). The source routes force the use of the virtual IP when sending packets to the subnets defined as remote traffic selector (if the physical IP was used the IPsec policies wouldn't match and the packets wouldn't get tunneled).

Responder Configuration

As already documented above, the remote traffic selector in swanctl.conf and ipsec.conf (remote_ts and rightsubnet, respectively) defaults to the value %dynamic. This value gets dynamically replaced by the virtual IP assigned to a client. Therefore, no remote traffic selector must be configured on the server when using virtual IPs. This ensures the client's traffic selector is correctly narrowed to the assigned virtual IP (otherwise, every client would get the same traffic selector assigned, resulting in conflicting policies).

To serve a specific IP address (even if the initiator requests a different address) to a single client the following may be configured:

Configuration File IPv4 IPv6
swanctl.conf connections.<conn>.pools = <name>
pools.<name>.addrs = 10.3.0.5
connections.<conn>.pools = <name>
pools.<name>.addrs = 2001:db8::1
ipsec.conf rightsourceip=10.3.0.5 rightsourceip=2001:db8::1

Alternatively, the responder may define the following to let the client choose an address. This is not recommended if the client is not completely trusted.

Configuration File IPv4 & IPv6
ipsec.conf rightsourceip=%config

To serve multiple clients define an address pool in CIDR notation or as an address range:

Configuration File IPv4 IPv6
swanctl.conf connections.<conn>.pools = <name>
pools.<name>.addrs = 10.3.0.0/24
connections.<conn>.pools = <name>
pools.<name>.addrs = 2001:db8::3:0/24
connections.<conn>.pools = <name>
pools.<name>.addrs = 10.3.0.1-10.3.0.100
connections.<conn>.pools = <name>
pools.<name>.addrs = 2001:db8::3:1-2001:db8::3:100
ipsec.conf rightsourceip=10.3.0.0/24 rightsourceip=2001:db8::3:0/24
rightsourceip=10.3.0.1-10.3.0.100 rightsourceip=2001:db8::3:1-2001:db8::3:100

Since 5.0.1 multiple connections in ipsec.conf (i.e. conn sections) can share the same pool if they use the same definition in rightsourceip (previously each connection would use it's own copy and the same virtual IP may have been handed out to different clients).
As address pools are explicitly assigned to connections defined in swanctl.conf multiple connections can easily share the same pool.

It's also possible to use an external pool provided by a plugin by specifying a pool name to request addresses from:

Configuration File IPv4 & IPv6
swanctl.conf connections.<conn>.pools = poolname
ipsec.conf rightsourceip=%poolname

This queries registered plugins for an IP address from a pool named poolname (below are two examples that use the dhcp and eap-radius plugins, respectively).

Multiple pools may be listed since 5.0.1:

Configuration File IPv4 & IPv6
swanctl.conf connections.<conn>.pools = v4pool, v6pool
pools.v4pool.addrs = 10.3.0.0/24
pools.v6pool.addrs = 2001:db8::3:0/24
ipsec.conf rightsourceip=10.3.0.0/28,2001:db8::3:0/24

As used in the ikev2/ip-two-pools-v4v6 test scenario.

DNS servers

DNS servers and other attributes can be assigned by plugins (e.g. the attr plugin) or since 5.0.1 directly in ipsec.conf by use of the rightdns option. In swanctl.conf each pool in the pools section may define a list of attributes to assign to clients.

In-memory backend

A non-persistent memory-based backend is the default (the configuration for swanctl.conf and ipsec.conf is described above). This backend is suitable for environments where pools are not shared across multiple gateways, server restarts are rare, and direct administration of the pools is not needed (though there are some provisions for non-destructively reloading pool configurations in a running server when using swanctl.conf.) To preserve IP address affinity, the remote IKE identity (as defined for the connection in question) is used. This maintains the same IP for a client (most of the time) even across brief teardowns of connections, approximating the behavior of a DHCP server without the stricture of lease expiry timers, but prevents clients from intentionally attempting to get a different IP address as there is no corresponding release mechanism.

Database backend

The ipsec pool utility allows easy management of IP address pools and other attributes, like DNS servers, stored in an SQL database using the attr-sql plugin.

DHCP backend

With the dhcp plugin the responder can request virtual IP addresses for clients from a DHCP server using broadcasts, or a designated server.

DNS/WINS server information is additionally served to clients if the DHCP server provides such information.

The plugin is used by setting

Configuration File IPv4
swanctl.conf connections.<conn>.pools = dhcp
ipsec.conf rightsourceip=%dhcp

The farp plugin might also be of use when using the dhcp plugin. It allows the responder to fake ARP responses for virtual IP addresses handed out to clients. This lets a road-warrior act as a client on the local LAN of the responder.

RADIUS backend

Since 5.0.3 the RADIUS plugin can provide virtual IP addresses assigned to RADIUS clients via the Framed-IP-Address attribute. Forwarding of other RADIUS attributes has been added in later releases.

The plugin is used by setting

Configuration File IPv4 & IPv6
swanctl.conf connections.<conn>.pools = radius
ipsec.conf rightsourceip=%radius

Multiple pools, different backends

If multiple pools are defined from different backends, for instance

Configuration File IPv4
swanctl.conf connections.<conn>.pools = radius, v4pool
pools.v4pool.addrs = 10.3.0.0/24
ipsec.conf rightsourceip=%radius,10.3.0.0/24

the order in which they are queried for virtual IPs depends on the plugin load order (in-memory pools are provided by the stroke and vici plugins, respectively). The order in rightsourceip or pools is irrelevant unless multiple in-memory pools from the same backend are defined.

Versions before 5.0.0

The description above covers the features of the charon daemon, which handled only IKEv2 connections in earlier releases. The pluto daemon that handled IKEv1 connections provided a similar feature set but not everything was supported (for instance, the dhcp and farp plugins).

The pluto daemon did not request virtual IP addresses from the responder if they were explicitly configured with leftsourceip (but it still installed it on the system, which charon does not do). In that case, that is, if the virtual IP was not assigned by the responder with rightsourceip one may had to use the rightsubnetwithin directive (refer to this example). That's not required in charon due to narrowing.

The IKEv2 daemon charon supports address pools since version 4.2.1, the IKEv1 daemon pluto gained support for this in 4.4.0.