Bug #599
passthrough connections subnet rules
Description
Hi,
it seems that passthrough connection install wrong routing rules in the 220 routing table (using strongSwan 5.1.3)
IPv4¶
For example, on a network with routing table:
default via 192.168.28.254 dev eth0 proto static 192.168.28.0/24 dev eth0 proto kernel scope link src 192.168.28.56
and with other local subnets accessible in 192.168.0.0/16.
Installing a passthrough connection with:
conn pass leftsubnet=192.168.0.0/16 rightsubnet=192.168.0.0/16 type=passthrough auto=route
will setup a routing table like:
ip route show table 220 192.168.0.0/16 via 192.168.28.254 dev eth0 proto static src 192.168.28.56
so that means all traffic for 192.168.0.0/16 should be sent to 192.168.28.254. That will fail for trafic to the local subnet (192.168.28.0/24) since that gateway would like to resent that trafic through the same interface. That trafic should be sent directly after ARP resolution, table 220 lacks a rule like:
192.168.28.0/24 dev eth0
IPv6¶
On the opposite, on an IPv6 network with local address 2001:xxxx:yyyy:zz::1/64 and with the following routing table:
local ::1 dev lo proto kernel metric 256 2001:xxxx:yyyy:zz::/64 dev eth0 proto kernel metric 256 expires 86398sec fe80::/64 dev eth0 proto kernel metric 256 default via fe80::aaaa:aaff:feaa:aaaa dev eth0 proto ra metric 1024 expires 1798sec
and a “local” network 2001:xxxx:yyyy::/48 accessible through the fe80::aaaa:aaff:feaa:aaaa.
Adding a passthrough connection like:
conn pass6 rightsubnet=2001:xxxx:yyyy::0/48 leftsubnet=2001:xxxx:yyyy::0/48 type=passthrough auto=route
sets up a 220 routing table like:
2001:xxxx:yyyy::/48 dev eth0 proto static src 2001:xxxx:yyyy:zz::1
So that means the whole /48 is considered to be on the same subnet and ipv6 neighbor discoveries are sent for trafic which should instead be sent to the local gateway.
That means the 220 routing table should be like:
2001:xxxx:yyyy:zz::/64 dev eth0 2001:xxxx:yyyy::/48 via fe80::aaaa:aaff:feaa:aaaa dev eth0
Summary¶
So it seems that both IPv4 and IPv6 passtrhough connections are broken, but differently:
- on IPv4, all the passthrough traffic is sent to the default gateway, including trafic for the local subnet;
- on IPv6, all the passthrough traffic is sent locally, including traffic which sould be sent through the correct gateway.
History
#1 Updated by Tobias Brunner over 11 years ago
- File destination-net-lookup-shunt-policies.path added
- Category set to libhydra
- Status changed from New to Feedback
- Assignee set to Tobias Brunner
192.168.0.0/16 via 192.168.28.254 dev eth0 proto static src 192.168.28.56
Before installing a route for a passthrough policy a lookup for the next hop to reach the VPN gateway is done (i.e. the same thing that is done for regular IPsec policies). Since passthrough policies obviously have no VPN gateway associated with them, a lookup with 0.0.0.0
as destination is done, which only matches the default route with 192.168.28.254
as gateway, which is used in the installed route.
2001:xxxx:yyyy::/48 dev eth0 proto static src 2001:xxxx:yyyy:zz::1
Here again a lookup for the next hop is done. But not for ::
. Because the (undefined) destination address is IPv4 it is done for 0.0.0.0
. In this case a lookup for ::
might have helped, at least the gateway would be correct. But the /64 route would not be there so packets for anything in 2001:xxxx:yyyy:zz::/64
would also get sent to fe80::aaaa:aaff:feaa:aaaa
(basically the same thing that happens for IPv4 above). For that you probably will have to add a second passthrough policy for the /64 subnet (or maybe include it in left|rightsubnet in your existing pass6 section) to get the proper route in table 220.
Only since 5.0.3 are routes for passthrough/drop policies actually installed. But as mentioned above they are essentially installed like the routes for regular IPsec policies. That routes are even required is a side-effect of how virtual IPs are handled on Linux (as described in #543-10), so if you don't use virtual IPs you could disable route installation via charon.install_routes in strongswan.conf to work around the issue.
To fix this we should probably install the routes for shunt policies (passthrough|drop) a bit differently. Maybe we could try to find a matching route based on the destination subnet and copy the information (gateway, interface, source address) for the new route in table 220.
The attached patch (quick-and-dirty) implements something like this for the kernel-netlink plugin. It simply extends the lookup function for the next hop with a prefix parameter, which allows lookups for destinations != hosts.
#2 Updated by Tobias Brunner over 11 years ago
- File destination-net-lookup-shunt-policies.path added
#3 Updated by Tobias Brunner over 11 years ago
- File deleted (
destination-net-lookup-shunt-policies.path)
#4 Updated by Tobias Brunner over 11 years ago
#5 Updated by Tobias Brunner over 11 years ago
- File deleted (
destination-net-lookup-shunt-policies.path)
#6 Updated by Yves-Alexis Perez over 11 years ago
I tried to rebuild strongSwan with the patch, here are the results
with the previous config.¶
For IPv4¶
Routing table 220 is:
192.168.0.0/16 via 192.168.28.254 dev eth0 proto static src 192.168.28.56
.h3 For IPv6
2001:xxxx:yyyy::/48 via fe80::aaaa:aaff:feaa:aaaa dev eth0 proto static src 2001:xxxx:yyyy:zz:f2de::1 metric 1024
So at least the behavior is consistent now.
with narrower subnets (/64 and /24) corresponding to local ones¶
IPv4¶
192.168.28.0/24 dev eth0 proto static src 192.168.28.56
IPv6¶
2001:xxxx:yyyy:zz::/64 dev eth0 proto static src 2001:xxxx:yyyy:zz::1 metric 1024
So that looks good to.
With the four configs (/24, /16 and /64, /48)¶
IPv4¶
192.168.0.0/16 via 192.168.28.254 dev eth0 proto static src 192.168.28.56 192.168.28.0/24 dev eth0 proto static src 192.168.28.56
IPv6¶
2001:xxxx:yyyy:zz::/64 dev eth0 proto static src 2001:xxxx:yyyy:zz:f2de::1 metric 1024 2001:xxxx:yyyy::/48 via fe80::aaaa:aaff:feaa:aaaa dev eth0 proto static src 2001:xxxx:yyyy:zz::1 metric 1024
So they both look pretty good. And I confirm I can reach local hosts directly, and use IPsec for distant ones.
But that also mean I need to have multiple passthrough connections for each LAN I might connect too. It'd help having some kind of profiles here so I can only say "ipsec up <from>-<to>" and have a <from>-<to> “alias” which would up the IPsec connection as well as all the dependents passthrough connections.
But I guess that's for another ticket :)
Many thanks for the quick work.
#7 Updated by Tobias Brunner about 11 years ago
- Tracker changed from Issue to Bug
- Status changed from Feedback to Closed
- Target version set to 5.2.0
- Resolution set to Fixed
Merged to master.