kernel-wfp Plugin
Purpose
The kernel-wfp
plugin for libcharon
is an interface to the IPsec backend
in the Windows Filter Platform on Windows. It installs and
maintains Security Associations and Policies to the Windows Kernel.
The plugin is disabled by default and can be enabled with the
./configure
option
--enable-kernel-wfp
Supported ciphers
This kernel backend supports both AH
, ESP
and ESP-in-UDP
for both tunnel
and transport mode Security Associations.
The following integrity algorithms are supported for both AH
and ESP
:
md5 sha1 sha256 aes128gmac aes192gmac aes256gmac
The following encryption algorithms for ESP
:
null des 3des aes128 aes192 aes256
and these AEAD
mode ciphers for ESP
:
aes128gcm16 aes192gcm16 aes256gcm16
Behavior
The Windows Filtering platform is a firewalling framework on the Windows operating system. It supports the installation of arbitrary filters from userland applications. Windows native IPsec is managed through the WFP API by associating filters to IPsec SA information.
The kernel-wfp
plugin implements an IPsec backend using the WFP API. As it
seems that there is no support to register custom keying modules in Windows 7,
$ the backend installs SA and policy information directly after negotiation.
This means that strongSwan does not install Main Mode or Quick Mode policies in
WFP in a way the Windows native keying modules do. Instead we maintain such
information locally in our IKE daemon and just install negotiated information.
The Windows kernel handles the IPsec ruleset using so called SA contexts,
managed by IPsecSaContextCreate0 and associated functions. An SA context knows
exactly one inbound and one outbound IPsec SA bundle for processing traffic,
associated using the IPsecSaContextAddInbound0
and IPsecSaContextAddOutbound0
functions. Each SA bundle contains algorithm and other configurations and the
associated encryption and integrity protection keys.
Transport Mode
In Transport mode, an SA context is directly tied to an outbound filter rule
during construction. The inbound filter rule is associated to the SA context by
calling IPsecSaContextGetSpi0
. Filter rules get installed using the
FwpmFilterAdd0
function.
Together with the inbound and outbound filters acting as policies, the SA context
with the inbound and the outbound SA bundles form the kernel-level object that
got negotiated for a CHILD SA
.
Tunnel Mode
Configuring tunnel mode in WFP works very similarly to transport mode. An SA context is used to attach inbound and outbound SA bundles.
A tunnel mode, however, usually has more than just an inbound and an outbound IPsec policy. It also needs forward policies, and multiple different in, out and forward policies for different selectors are desirable.
To install the required filter set for a tunnel mode SA, the WFP API provides a
FwpmIPsecTunnelAdd0
function. This function implicitly creates multiple
filter rules from the passed traffic selectors, which can be associated to an SA
context. The internals of this function, however, are somewhat unclear and it
limits the flexibility of policy installation.
To allow the installation of multiple selectors and policies, the kernel-wfp
plugin installs filter rules manually for tunnel mode. To do so, a provider
context is required to associate an arbitrary number of filters to it. The
provider context is then referenced by the SA context to link all filters to the
SA bundles.
State and SPI Management
The strongSwan IPsec kernel abstraction layer is loosely defined for the PF_KEY
and similar interfaces, working on SA and policy granular level. It usually
installs in- and outbound Security Associations, and then attaches IPsec policies
using a unique reqid
identifier.
For the WFP interface, this paradigm does not work very well. It expects the policy information first, followed by the SA context and the in- and outbound Security Associations. The WFP interface can’t allocate SPIs without creating policy entries and an SA context first. In strongSwan, however, we must allocate SPIs before installing policies, as this information is negotiated in IKEv2.
To work around these interface differences, the kernel-wfp
plugin caches any
policy or SA addition. Once all this information has been collected, it installs
it in a single batch. Instead of using kernel allocated SPIs using
IPsecSaContextGetSpi0
, it allocates SPIs in userland pseudo-randomly and uses
IPsecSaContextSetSpi0
to set it.
All policy and SA information installed by strongSwan is non-persistent. A system reboot or a restart of the Base Filtering Engine service removes any rule installed by the plugin.
Bypass Policies
When installing IPsec policies, an IKE daemon must ensure that the policies don’t cover IKE packets. This makes sure that IKE packets are never encapsulated in ESP.
While WFP has built-in support for IKE bypass filters, these cover policies
installed by FwpmIpsecTunnelAdd0
only. We therefore install global bypass
filter rules for the IKE socket. These filter use a high priority to have
precedence over any IPsec policy negotiated.
Trap Policies and Events
strongSwan can install IPsec policies not having Security Associations attached to it, the trap policies. If the kernel layer processes a packet matching such a policy, it raises an event to strongSwan. strongSwan then negotiates an SA for this policy, protecting traffic on demand.
In WFP, strongSwan uses drop firewall rules for trap policies and registers for
firewalling events using FwpmNetEventSubscribe0
to register for drop events.
If the Windows kernel raises an event for a drop rule, it informs strongSwan
which in turn looks for the corresponding trap policy and starts SA negotiation.
The firewall event subscription is also used to catch other IPsec related rocessing errors, which get logged by strongSwan.
ipsecdump Utility
For development and debugging purposes, the plugin comes with an ipsecdump.exe
utility. By default it dumps Security Associations currently installed on the
system. When invoked with a filters
argument, it dumps any IPsec related
firewall filters.
Known Issues and Limitations
The following limitations apply to the kernel-wfp
plugin:
Accessing Gateway Internal Address in a net-to-net Tunnel
When a Windows Gateway offers IPsec protected access to an internal subnet in
tunnel mode, an IPsec client is currently unable to access any internal IP
address of the gateway itself, even if it is part of the covered subnet. The
kernel raises a STATUS_IPSEC_CLEAR_TEXT_DROP
event if such a packet is received.
The Microsoft Knowledge Base entry KB2502685 exactly describes this
issue and provides a hotfix, but is related to a Forefront TMG server. It is
currently not clear if the same issue applies to the Windows 7 product family or
if it can be worked around from userland.
Protocol/Port Restrictions on Forwarding net-to-net Connections
The Windows Kernel does not parse transport layer IP packet headers when forwarding packets. Therefore it does not support protocol or port selectors in IPsec forwarding policies, but only in policies for a local address. In practice strongSwan currently just ignores protocol/port restrictions in forwarding policies, but enforces them for inbound/outbound policies. Forwarding policies therefore may cover more traffic than negotiated in IKE.
Unsolicited Inbound Traffic in UDP-Encapsulated ESP Packets
When receiving traffic on an UDP-encapsulated ESP tunnel mode connection, any
unsolicited inbound traffic gets dropped by the kernel with a
STATUS_INTERNAL_ERROR
event. This applies to UDP-encapsulated connections only
and does not affect traffic that the kernel can associate to a known connection.
For example, the return path works fine if the Windows host initiates a TCP
connection over such a tunnel.
It is currently unknown if this is a kernel related issue or if it can be worked around by configuring UDP encapsulation in a slightly different fashion.
Multiple Traffic Selectors for Transport Mode Connections
Due the design of SA context information in the Windows kernel, in transport
mode only a single inbound and outbound filter can be applied. This means that a
single CHILD SA
can have a single selector only. In practice, this is usually
not much of a problem, as transport mode SAs can cover a single host pair only.
Defining multiple protocols or address ranges is currently not possible, though.
SA Usage, Lifetime and Volumes
The Windows kernel does not seem to provide any means of getting per-SA statistics.
IPsecGetSaStatistics0
works on a global level only and the IPsecSaEnum0
and IPsecSaContextEnum0
return configured lifetime values only.
For strongSwan this implies that no usage counters are available, and that DPD checking and keep-alive messages can’t be reduced based on IPsec SA activity.
It is currently not possible to configure volume based rekeying. Time based rekeying is managed by strongSwan in userland, but hard SA lifetimes ensure that the kernel rejects packets even if userland does not renew connections as expected.