[strongSwan-dev] patch proposal: ignore acquire
tobias at strongswan.org
Tue Oct 13 17:41:06 CEST 2015
> It seems the solution you suggested works fine as long as there is no traffic selector narrowing involved.
> On the responder -> 192.168.120.0/24 === 192.168.110.0/24
> On the initiator -> 192.168.110.0/25 === 192.168.120.0/25
> But packets are never sent, they seem to be dropped by the kernel (the lastused of the out discard policy is refreshed)
This is due to how the FreeBSD kernel stores and matches policies.
strongSwan's PF_KEY plugin will only install one policy for each unique
traffic selector and direction (duplicate policies are not allowed by
the kernel), so all equal policies are internally assigned a priority
based on their type and size and sorted (more specific/smaller TS are
preferred, and passthrough > IPsec > trap > drop). Only the policy with
the highest priority is installed in the kernel.
Therefore, the actual IPsec policy will replace the installed drop
policy if no narrowing occurs (if you'd call `ipsec unroute <dropconn>`
afterwards nothing would change in the kernel as that drop policy is not
installed, only the cached data in the plugin would get removed).
But if the traffic selectors are narrowed the negotiated IPsec policy
won't match the drop policy and no conflict occurs, so both policies end
up installed in the kernel. However, they obviously overlap.
If the underlying kernel stores policies in a simple list where entries
are added at the end and are matched against packets from the front,
stopping at the first match (as the FreeBSD kernel does) this poses a
problem. Because the drop policy is installed first and is a superset
of the following IPsec policy, packets matching the IPsec policy will
always be dropped, the IPsec policy will never be considered.
On the other hand, on Linux this works fine because policies in the
kernel are ordered by a priority that may be assigned by the IKE daemon
(we just use the priorities we internally use). This even works when
using PF_KEY on Linux (via sadb_x_policy_priority member of the
sadb_x_policy struct). That way narrowed regular IPsec policies always
win over drop, trap or wider policies.
The reason it works with the trap policy/ignore acquire approach is that
the reqids assigned to trap policies are reused even for narrowed
CHILD_SAs and even as responder (the lookup is based on the name of the
selected child config). So the wider trap policy, which is installed
first and, thus, always gets used, will just send all matching traffic
through the IPsec tunnel with the matching reqid (this could tunnel more
traffic than the inbound policy on the other peer allows, though).
If you can't ensure that the traffic selectors are the same on both
peers there are some options:
1) You could continue to use the trap/ignore acquire approach (with
appropriate system settings to avoid too many acquires).
2) The FreeBSD kernel could be extended so policies may optionally be
ordered by priorities provided by the IKE daemon. Instead of just
appending new policies at the end of the list they would get
inserted based on the assigned priority (after policies with the
same priority, so nothing would change if an IKE daemon does not
assign priorities). If policies were sorted by increasing priority
and if the same member were added to the sadb_x_policy struct that
is used on Linux (sadb_x_policy_priority) there wouldn't even be
any changes required in strongSwan's PF_KEY plugin.
3) The PF_KEY plugin could theoretically split the policies before
installing them in the kernel, so they don't overlap. Not sure how
feasible this really is, though.
More information about the Dev