Red Hat Bugzilla – Bug 140654
ifup-ipsec attempts to set incorrect route
Last modified: 2014-03-16 22:50:49 EDT
Description of problem:
lines 140 and 194 of ifup-ipsec contain the command:
'ip route add to $DSTNET via $DST' which is incorrect. Traffic routed
over the VPN needs to be routed through the address which serves
as the local (internal) endpoint to the VPN, rather than $DST, which
is the external address of the remote endpoint.
Version-Release number of selected component (if applicable):
Steps to Reproduce:
1. ifup <your ipsec vpn>
route addition fails, VPN is usually non-functional.
I managed to make the script work correctly by replacing the offending
ip route add to $DSTNET via $SRCGW
where $SRCGW is a variable set by system-config-network, but
apparently unused by ifup and ifdown. This may not be the approprate
use of $SRCGW, since it isn't clear what that variable is actually
The following ASCII art should help explain what needs to be fixed:
Net 1 Host1 Internet Host 2 Net 2
-----------\ +------+ /--------------\ +------+ /-----------\
10.1.0.0/16 --=A B=-- X.X.X.X --=C D=-- 10.2.0.0/16 |
-----------/ +------+ \--------------/ +------+ \-----------/
+------- IPsec Tunnel ------+
Where Host 1 and Host 2 are IPsec tunnel endpoints which join Net 1
and Net 2 across the hostile Internet. Interface IPs are as follows:
The IPsec tunnel goes from 10.1.0.1 to 10.2.0.1. Therefore, Host 1
needs to route traffic going to 10.2.0.0/16 through 10.1.0.1.
The current scripts attempts to add the route:
10.2.0.0/16 via 220.127.116.11
when it should add the route
10.2.0.0/16 via 10.1.0.1
In fact, the script as it is causes the route addition to fail with
the response "RTNETLINK answers: Network is unreachable", since you
can't route through an IP that isn't on your broadcast network.
The solution I've used (using $SRCGW) seems suboptimal and
error-prone, as it requires the user to supply the required values. A
possible way to retrieve the needev value would be to parse the result
of the command:
ip route get $SRCNET
*** Bug 146169 has been marked as a duplicate of this bug. ***
I seem to be suffering from the same problem. This seems similar to
bug#126646, but from the comments it isn't clear how he worked his
config out to bring the tunnel up.
Actually, looking at this again, I'm not convinced the route needs to
be set at all. If you just remove the 'ip route add...' does it work?
*** Bug 128208 has been marked as a duplicate of this bug. ***
When I tested it before, it would not work without the route. The
reason for that was that it would try to send the packet the "normal"
way without using the IPSec tunnel. I.e., it would send the packet for
10.2.1.1 to my default gateway.
Admittedly, telling it to route through its local interface looks and
smells a lot like a hack--it shouldn't be necessary since the kernel
already has all the routing information it needs. Adding the route
seems to trigger it to follow the correct behavior.
It may have been fixed in more recent kernels, I don't know. All of my
IPSec endpoints are on production machines, so testing out theories is
out of the question where I work.
In order to test any theories properly, though, you need two IPSec
endpoints on different networks at least, I think.
You wouldn't happen to have (or had):
net.ipv4.conf.default.rp_filter = 1
in /etc/sysctl.conf, would you?
I do the same thing that the RH ipsec scripts do, but I do it
manually. My setup needs the route or it doesn't work. It makes
sense if the 2 networks you are VPN'ing are non-routable private IP
spaces (192.168.*, 10.*), doesn't it?
I just ip route del'd the routes on my 2 test boxes and instantly I
can no longer ping the other side's network. Add the routes and
instantly it works again.
I remember that when I used to use freeswan, it too added its own
routes in order to function (but it did it automatically for you).
The reason I asked is because I've tested without the route between
disparate networks, and it works for me; the key was turning off
echo 1 > /proc/sys/net/ipv4/conf/default/rp_filter
on both systems and now, yes, it does work without the route present.
Now I'll have to go research what the heck rp_filter means and why it
was on by default and what it will mean if I have it off! Perhaps
having an extra route in there isn't too bad a solution?
Yes, it was set to 1 in /etc/sysctl.conf, but I don't ever remember
changing it so it must be the RH default?
rp_filter - BOOLEAN
1 - do source validation by reversed path, as specified in RFC1812
Recommended option for single homed hosts and stub network
routers. Could cause troubles for complicated (not loop free)
networks running a slow unreliable protocol (sort of RIP),
or using static routes.
0 - No source validation.
conf/all/rp_filter must also be set to TRUE to do source
on the interface
Default value is 0. Note that some distributions enable it
in startup scripts.
Yes, it's set this way as RH default, because it's better for end-user
machines (much like ip_forward.)
I suppose it could be argued that tunnel mode should automatically
turn this (and ip_forwarding) on. I'll check with the networking gurus
which is preferred.
Do you know what section of RFC1812 specifically talks about
rp_filter? I've found lots of stuff in there about validation and rp
but nothing about an "rp filter" and the docs above seem opposite to
what the RFC describes (option value is inverted?).
Why does it work with no static route when rp_filter=1?? Doesn't it
make sense that rp_filter=1 would drop the packets and rp_filter=0
would let them through? It seems reversed to me.
Do I lose or gain any useful security on my FC firewall/router by
Actually, what I would expect is that it would *require* rp_filter=0
But adding the routes is probably simpler.
To clarify, I was asking if you had rp_filter=1, because in that case,
I would expect the route to be needed.
OK, now I am completely lost. I reread the entire bug and reran some
tests and now nothing makes sense.
On my test setup I tried changing all/rp_filter, default/rp_filter
*and* eth0/rp_filter and eth1/rp_filter on the fly first to all 0 then
to all 1. I deleted my static route.
Now for all my tests the route seems unnecessary?!? I can ping
network-to-network no matter what I set rp_filter to -- without any
Does this make any sense? I verified those values with cat and
verified the route was gone with ip route show. Once you change these
values, do you have to reboot or ifdown/ifup to make them take effect?
I saw the same behavior at one point; it didn't work, I turned
rp_filter off; it worked, I turned it back on, it *still* worked.
Should that be opened as a separate bug? If the kernel is not obeying rp_filter
settings on the fly, that may even be considered a security bug?
At the very least, it makes testing and diagnosing this bug's issue quite difficult!
I'm adding the attached in CVS. As to the rp_filter issue, the network
maintainer says that's probably the route cache kicking in, and he suggests that
using routes, as opposed to messing with rp_filter, is the proper solution.
Created attachment 112400 [details]
Patch to add/remove routes
Should be in 8.06-1.