flushing OpenVPN routes to prevent temporary incorrect routing

An OpenVPN client routes 192.168.2.0/24.

root@controller:~# ip route show 192.168.2.0/24
192.168.2.0/24 via 192.168.0.21 dev tun0

When the OpenVPN client is down, IP in the 192.168.2.0/24 network will be cached to go thru the default route instead:

root@controller:~# ip route show cache 192.168.2.42
192.168.2.42 via 10.145.4.4 dev eth0  src 10.145.4.5
 

When the OpenVPN client is back, the cache needs to be flushed to prevent temporary incorrect routing.

root@controller:~# ip route flush cache

Context

The route cache has been removed from recent ( >= 3.6 http://article.gmane.org/gmane.linux.network/238256 ) linux kernels. The context of the problem involves a Debian GNU/Linux wheezy distribution with:

root@controller:/etc# uname -a
Linux controller.vm.april-int 3.2.0-3-amd64 #1 SMP Mon Jul 23 02:45:17 UTC 2012 x86_64 GNU/Linux
root@controller:/etc# dpkg -l iproute
ii  iproute                   20120521-3

Flushing the route

An up script is added to the OpenVPN client configuration to flush the route each time the client connects.

diff --git a/openvpn/client.conf b/openvpn/client.conf
index 743a6fa..168f74a 100644
--- a/openvpn/client.conf
+++ b/openvpn/client.conf
@@ -133,4 +133,6 @@ mute 20
 log         /var/log/openvpn/openvpn.log
 log-append  /var/log/openvpn/openvpn.log

-
+script-security 2
+# for more information https://agir.april.org/issues/1115
+up /etc/openvpn/route-flush
diff --git a/openvpn/route-flush b/openvpn/route-flush
new file mode 100755
index 0000000..384dc57
--- /dev/null
+++ b/openvpn/route-flush
@@ -0,0 +1,2 @@
+#!/bin/bash
+/sbin/ip route flush cache

Disabling ICMP redirects

If the OpenVPN client routes packets on behalf of other machines

diff --git a/sysctl.conf b/sysctl.conf
index 9c0861a..1ec3b09 100644
--- a/sysctl.conf
+++ b/sysctl.conf
@@ -25,7 +25,7 @@
 #net.ipv4.tcp_syncookies=1

 # Uncomment the next line to enable packet forwarding for IPv4
-#net.ipv4.ip_forward=1
+net.ipv4.ip_forward=1

It should also avoid sending ICMP redirects. If the OpenVPN is down and a machine asks for 192.168.2.42, an ICMP redirect will be sent.

# ping -c 1 192.168.2.42
PING 192.168.2.42 (192.168.2.42) 56(84) bytes of data.
From 192.168.4.1: icmp_seq=1 Redirect Host(New nexthop: 10.145.4.4)
...

As a result, the machine will record an alternate route for 192.168.2.42 in its own route cache.

root@jenkins:~# ip route show cache  192.168.2.42
192.168.2.42 from 192.168.4.3 via 10.145.4.4 dev eth0
    cache <redirected>  ipid 0x5614

And it will stay there until the cache expires. The OpenVPN client machine is configured to disable sending ICMP redirects.

--- a/sysctl.conf
+++ b/sysctl.conf
@@ -25,7 +25,7 @@
 # Uncomment the next line to enable packet forwarding for IPv6
 #  Enabling this option disables Stateless Address Autoconfiguration
@@ -49,7 +49,7 @@
 # net.ipv4.conf.all.secure_redirects = 1
 #
 # Do not send ICMP redirects (we are not a router)
-#net.ipv4.conf.all.send_redirects = 0
+net.ipv4.conf.all.send_redirects = 0
 #
 # Do not accept IP source route packets (we are not a router)
 #net.ipv4.conf.all.accept_source_route = 0

To dynamically change this for the eth0 interface instead of rebooting the machine:

# sysctl net.ipv4.conf.eth0.send_redirects=0