"Generally IPsec processing is based on policies. After regular route
lookups are done the OS kernel consults its Security Policy Database for a matching policy
and if one is found that is associated with an IPsec SA the packet is
processed.
Depending on the operating system it is also possible to configure
route-based VPNs. Here IPsec processing does not (only) depend on
negotiated policies but may e.g. be controlled by routing packets to a
specific interface."
Source: RouteBasedVPN
So policy based routing has nothing to do with the routing table of the OS but it's using a separate "database" so ip route
and such does not play here. You set up these policies with the IPSec config. IPSec can do the tunneling on its own.
Here is the output of my ip route
and swanctl --list-sas
(I'm using swanctl to configure and control strongswan):

As you can see I have an IPSec connection between my hosted server called sv1 (37.17.x.x) and my home router (87.97.x.x). The server's routing table has only the default settings but you can see the IPSec policies called home-invitel
, home-securewifi
and home-lan
that routes every traffic from the server to the home LAN subnets 192.168.100.0/24
, 192.168.87.0/28
and 192.168.88.0/24
respectively. A fourth policy called sv1-local routes the traffic between my home endpoint and the 10.1.1.0/24
local subnet on the server.
Here is the swanctl config I use on the server:
connections {
home {
local_addrs = 37.17.x.x
remote_addrs = vpn.example.org
version = 2
proposals = aes256-sha256-ecp384
keyingtries = 0
dpd_delay = 60s
local1 {
auth = psk
}
remote1 {
auth = psk
}
children {
sv1-local {
local_ts = 10.1.1.0/24
esp_proposals = aes256gcm16-ecp384
dpd_action = restart
close_action = start
start_action = start
}
home-securewifi {
remote_ts = 192.168.87.0/28
esp_proposals = aes256gcm16-ecp384
dpd_action = restart
close_action = start
start_action = start
}
home-lan {
remote_ts = 192.168.88.0/24
esp_proposals = aes256gcm16-ecp384
dpd_action = restart
close_action = start
start_action = start
}
home-invitel {
remote_ts = 192.168.100.0/24
esp_proposals = aes256gcm16-ecp384
dpd_action = restart
close_action = start
start_action = start
}
}
}
}
secrets {
ike-local {
id = 37.17.x.x
secret = "preshared-secret-key-goes-here"
}
ike-remote {
id = vpn.example.org
secret = "preshared-secret-key-goes-here"
}
}
For example when I ping home to 192.168.88.5 from sv1 then:
- the OS checks the route table but found no 192.168.88.5 specific rule
- the OS then checks the IPSec policy database for a matching policy
- the home-lan policy matches so the OS hands out the packet to IPSec
- IPSec encapsulates (encrypt) the packet and sends it over the home-lan tunnel
- my home router receives the encapsulated (encrypted) packet, finds a matching policy in its own IPSec policy database, decapsulate (decrypt) the packet and sends the now unencrypten packet to 192.168.88.5