Why are only 3 ip xfrm policies needed for a IPsec tunnel?

Solution 1:

The fwd policies are not automatically generated by the kernel but instead get installed by the keying daemon (strongSwan in this case).

They are required to allow traffic to get forwarded to and from hosts behind the VPN gateway in tunnel mode.

For an inbound packet that is addresses to an IP that's not installed on the gateway itself a fwd policy is searched after decryption. For local traffic a matching in policy is looked up. If none is found the packet is dropped.

For outbound traffic that was not generated on the VPN gateway itself a fwd policy is searched. If the packet was not encrypted it is no failure if no matching fwd policy is found. And if traffic is forwarded between two tunnels the inbound fwd policy installed with one will act as outbound fwd policy for the other and vice-versa. Afterwards, an out policy is looked up to decide whether to tunnel the packet. That's why a fwd policy in the outbound direction is often not required.

However, if there is e.g. a drop/block fwd policy with low priority that matches everything (e.g. to avoid cleartext traffic from passing the gateway if there are no tunnels established) a fwd policy in the outbound direction is explicitly required as the block policy will otherwise drop all unencrypted traffic. That's why strongSwan started installing fwd policies in both directions with 5.5.0.


A previous version of this answer stated that the single (inbound) fwd policy is symmetrical (i.e. that src and dst work in either direction). That's not true, but as explained above in many situations this doesn't matter.

Solution 2:

From this article by Andrej Stender:

security policy syntax meaning
“output policy” dir out SP works as a selector on outgoing packets to select which are to be encrypted+encapsulated and which not
“input policy” dir in SP works as a selector on incoming packets which already have been decrypted+decapsulated and have a destination IP local on the system
“forward policy” dir fwd SP works as a selector on incoming packets which already have been decrypted+decapsulated and have a destination IP which is not local, thereby packets which are to be forwarded (routed)

So:

  • out is used on outgoing traffic (both local and forwarded) that we want to encrypt+encapsulate with IPsec.
  • in and fwd are used on incoming IPsec traffic and are applied to packets encapsulated within IPsec:
    • in is applied to inner packets whose destination IP is this computer
    • fwd is applied to inner packets which should be forwarded further

EDIT: I conducted my own local experiments with ip xfrm on Linux 5.9.1 and results matched Andrej's table.

Solution 3:

This seems to confirm that there is actually no forward policy needed on site A's router to forward 10.10.0.0/16 to 10.50.0.0/16 over the IPsec tunnel, but I do not understand why.

That is because A wants to receive from B only IPsec traffic.

IPsec traffic from A to B has A's IP address as a destination IP address - so it is handled by dir in policy on A.
After encapsulated IP packets are extracted from IPsec, they are handed over to kernel to get standard linux processing of an incoming IP packet - no xfrm policy dir fwd is required here.

Policy src 10.10.0.0/16 dst 10.50.0.0/16 dir fwd ... on A could be added if you need to also receive non-IPsec traffic from B .