In your StrongSwan-RouterOS IPsec setup, the three XFRM policies you're observing represent the fundamental security associations required for bidirectional tunneled communication. Let's dissect each component:
# Policy 1: Forward Path (site B → site A)
src 10.50.0.0/16 dst 10.10.0.0/16 dir fwd
# Policy 2: Inbound Path (site B → site A)
src 10.50.0.0/16 dst 10.10.0.0/16 dir in
# Policy 3: Outbound Path (site A → site B)
src 10.10.0.0/16 dst 10.50.0.0/16 dir out
The apparent "missing" forward policy for traffic from 10.10.0.0/16 to 10.50.0.0/16 isn't actually required because:
- Outbound traffic from site A initiates through the dir out policy
- The return path is handled by the dir in policy on site A
- Intermediate forwarding is managed by the existing dir fwd policy
Consider this packet journey when 10.10.0.89 pings 10.50.4.11:
1. Outbound phase:
[10.10.0.89] → (out policy match) → [IPsec encap] → [Public Internet]
2. Return phase:
[10.50.4.11] → (fwd policy match) → [IPsec decap] → [10.10.0.89]
Here's how you could explicitly define policies using ip xfrm
commands:
# Outbound policy
ip xfrm policy add src 10.10.0.0/16 dst 10.50.0.0/16 \\
dir out tmpl src PUBLIC_IP_A dst PUBLIC_IP_B \\
proto esp mode tunnel
# Inbound policy
ip xfrm policy add src 10.50.0.0/16 dst 10.10.0.0/16 \\
dir in tmpl src PUBLIC_IP_B dst PUBLIC_IP_A \\
proto esp mode tunnel
# Forward policy
ip xfrm policy add src 10.50.0.0/16 dst 10.10.0.0/16 \\
dir fwd tmpl src PUBLIC_IP_B dst PUBLIC_IP_A \\
proto esp mode tunnel
The architecture works because:
- Linux networking stack handles local delivery via
dir in
- Forwarded traffic only needs one direction defined (opposite to initiator)
- Route-based VPNs often require fewer policies than policy-based VPNs
To verify policy effectiveness, use:
ip xfrm policy count
ip xfrm monitor policy
When examining a functional site-to-site IPsec tunnel between StrongSwan (v5.2.0) and RouterOS, we observe an interesting policy configuration with only three XFRM policies instead of the expected four. Let's break down what each policy does:
# Policy 1: Forward direction (B→A)
src 10.50.0.0/16 dst 10.10.0.0/16
dir fwd priority 2947 ptype main
tmpl src PUBLIC_IP_B dst PUBLIC_IP_A
proto esp reqid 1 mode tunnel
# Policy 2: Input direction (B→A)
src 10.50.0.0/16 dst 10.10.0.0/16
dir in priority 2947 ptype main
tmpl src PUBLIC_IP_B dst PUBLIC_IP_A
proto esp reqid 1 mode tunnel
# Policy 3: Output direction (A→B)
src 10.10.0.0/16 dst 10.50.0.0/16
dir out priority 2947 ptype main
tmpl src PUBLIC_IP_A dst PUBLIC_IP_B
proto esp reqid 1 mode tunnel
The apparent missing forward policy from A→B isn't actually necessary due to how Linux routing works. When traffic originates from 10.10.0.0/16 destined for 10.50.0.0/16:
- The output policy matches and encrypts the traffic
- On the return path, the input policy handles decryption
- The forward policy only applies to transit traffic
The ping route trace reveals why:
ping -R 10.50.4.11
PING 10.50.4.11 (10.50.4.11): 56 data bytes
64 bytes from 10.50.4.11: icmp_seq=0 ttl=62 time=10.872 ms
RR: 10.10.0.89
10.50.0.1
10.50.4.11
10.50.4.11
10.50.4.11
10.10.0.2
10.10.0.89
This shows:
- Outbound traffic goes directly through the tunnel (no forward policy needed)
- Return traffic hits the forward policy (B→A)
- Local traffic uses input/output policies only
To verify your tunnel configuration, use these diagnostic commands:
# Check installed policies
ip xfrm policy
# View security associations
ip xfrm state
# Check routing table
ip route show table all
The complete policy set would look like this in a configuration:
# SPD configuration for StrongSwan
conn site-to-site
left=10.10.0.0/16
right=10.50.0.0/16
leftsubnet=10.10.0.0/16
rightsubnet=10.50.0.0/16
authby=secret
ike=aes256-sha1-modp1024!
esp=aes256-sha1!
keyingtries=0
ikelifetime=8h
lifetime=1h
type=tunnel
auto=start