Project

General

Profile

Bug #599

passthrough connections subnet rules

Added by Yves-Alexis Perez over 6 years ago. Updated over 6 years ago.

Status:
Closed
Priority:
Normal
Category:
libhydra
Target version:
Start date:
22.05.2014
Due date:
Estimated time:
Affected version:
5.1.3
Resolution:
Fixed

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.
destination-net-lookup-shunt-policies.patch (11.9 KB) destination-net-lookup-shunt-policies.patch file name fixed Tobias Brunner, 22.05.2014 18:40

Associated revisions

Revision 93c68fcd
Added by Tobias Brunner over 6 years ago

Merge branch 'shunt-policies-routes'

Fixes #599.

History

#1 Updated by Tobias Brunner over 6 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 6 years ago

  • File destination-net-lookup-shunt-policies.path added

#3 Updated by Tobias Brunner over 6 years ago

  • File deleted (destination-net-lookup-shunt-policies.path)

#5 Updated by Tobias Brunner over 6 years ago

  • File deleted (destination-net-lookup-shunt-policies.path)

#6 Updated by Yves-Alexis Perez over 6 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 over 6 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.

Also available in: Atom PDF