Skip to contentSkip to conversation

NOTE: unable to redirect default gateway -- Cannot read current default gateway from system

Openvpn-devel New Thomas Schäfer 3 participants 10 messages Jan 18, 2017 – Mar 31, 2017

lore
Share & tools
lore
#0 lore raw

Hi,

In case of being totally wrong here, please redirect me to the right place (bug-systems, forum,...).

Some words about the configuration:

Server: shares a private IPv4-Network and ula-IPv6-Network IPv4-Adresses also NATed to the public.

proto udp6
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh2048.pem
server 192.168.178.128 255.255.255.128
server-ipv6 fd00::1:1/112
push "route 192.168.178.0 255.255.255.0"
push "route-ipv6 fd00::/64"
keepalive 10 120
verb 3

Client:
client
dev tun
proto udp6
remote raspberrypi.XXXXXXXX.myfritz.net 1194 udp6
ca ca.crt
cert client.crt
key client.key
remote-cert-tls server
redirect-gateway
verb 3

This works perfectly as long the client has still an IPv4-connection.

But in case of an IPv6-only-client (not system-wide disabled, just not getting IPv4-addresses by the ISP, e.g. eduroam-IPv6) the client doesn't set the IPv4-default route, since it can not find the old one.

Regards,
Thomas

openvpn --config client.ovpn
Wed Jan 18 16:11:34 2017 OpenVPN 2.4.0 x86_64-suse-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Dec 27 2016
Wed Jan 18 16:11:34 2017 library versions: OpenSSL 1.0.2j-fips 26 Sep 2016, LZO 2.08
Wed Jan 18 16:11:34 2017 TCP/UDP: Preserving recently used remote address: [AF_INET6]2003:63:2417:f900:ba27:ebff:feb6:f293:1194
Wed Jan 18 16:11:34 2017 Socket Buffers: R=[212992->212992] S=[212992->212992]
Wed Jan 18 16:11:34 2017 setsockopt(IPV6_V6ONLY=0)
Wed Jan 18 16:11:34 2017 UDPv6 link local (bound): [AF_INET6][undef]:1194
Wed Jan 18 16:11:34 2017 UDPv6 link remote: [AF_INET6]2003:63:2417:f900:ba27:ebff:feb6:f293:1194
Wed Jan 18 16:11:34 2017 TLS: Initial packet from [AF_INET6]2003:63:2417:f900:ba27:ebff:feb6:f293:1194, sid=f70817fa 1f034096
Wed Jan 18 16:11:34 2017 VERIFY OK: depth=1, C=KG, ST=NA, L=BISHKEK, O=OpenVPN-TEST, [email protected]...
Wed Jan 18 16:11:34 2017 Validating certificate key usage
Wed Jan 18 16:11:34 2017 ++ Certificate has key usage 00a0, expects 00a0
Wed Jan 18 16:11:34 2017 VERIFY KU OK
Wed Jan 18 16:11:34 2017 Validating certificate extended key usage
Wed Jan 18 16:11:34 2017 ++ Certificate has EKU (str) TLS Web Server Authentication, expects TLS Web Server Authentication
Wed Jan 18 16:11:34 2017 VERIFY EKU OK
Wed Jan 18 16:11:34 2017 VERIFY OK: depth=0, C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server, [email protected]...
Wed Jan 18 16:11:34 2017 Control Channel: TLSv1.2, cipher TLSv1/SSLv3 ECDHE-RSA-AES256-GCM-SHA384, 2048 bit RSA
Wed Jan 18 16:11:34 2017 [Test-Server] Peer Connection Initiated with [AF_INET6]2003:63:2417:f900:ba27:ebff:feb6:f293:1194
Wed Jan 18 16:11:36 2017 SENT CONTROL [Test-Server]: 'PUSH_REQUEST' (status=1)
Wed Jan 18 16:11:36 2017 PUSH: Received control message: 'PUSH_REPLY,route 192.168.178.0 255.255.255.0,route-ipv6 fd00::/64,tun-ipv6,route 192.168.178.129,topology net30,ping 10,ping-restart 120,ifconfig-ipv6 fd00::1:1001/112 fd00::1:2,ifconfig 192.168.178.134 192.168.178.133,peer-id 0,cipher AES-256-GCM' Wed Jan 18 16:11:36 2017 Note: option tun-ipv6 is ignored because modern operating systems do not need special IPv6 tun handling anymore.
Wed Jan 18 16:11:36 2017 OPTIONS IMPORT: timers and/or timeouts modified
Wed Jan 18 16:11:36 2017 OPTIONS IMPORT: --ifconfig/up options modified
Wed Jan 18 16:11:36 2017 OPTIONS IMPORT: route options modified
Wed Jan 18 16:11:36 2017 OPTIONS IMPORT: peer-id set
Wed Jan 18 16:11:36 2017 OPTIONS IMPORT: adjusting link_mtu to 1624
Wed Jan 18 16:11:36 2017 OPTIONS IMPORT: data channel crypto options modified
Wed Jan 18 16:11:36 2017 Data Channel Encrypt: Cipher 'AES-256-GCM' initialized with 256 bit key
Wed Jan 18 16:11:36 2017 Data Channel Decrypt: Cipher 'AES-256-GCM' initialized with 256 bit key
Wed Jan 18 16:11:36 2017 ROUTE: default_gateway=UNDEF
Wed Jan 18 16:11:36 2017 GDG6: remote_host_ipv6=2003:63:2417:f900:ba27:ebff:feb6:f293
Wed Jan 18 16:11:36 2017 ROUTE6_GATEWAY fe80::da67:d9ff:fe6e:a242 IFACE=wlan0
Wed Jan 18 16:11:36 2017 TUN/TAP device tun0 opened
Wed Jan 18 16:11:36 2017 TUN/TAP TX queue length set to 100
Wed Jan 18 16:11:36 2017 do_ifconfig, tt->did_ifconfig_ipv6_setup=1
Wed Jan 18 16:11:36 2017 /bin/ip link set dev tun0 up mtu 1500
Wed Jan 18 16:11:36 2017 /bin/ip addr add dev tun0 local 192.168.178.134 peer 192.168.178.133
Wed Jan 18 16:11:36 2017 /bin/ip -6 addr add fd00::1:1001/112 dev tun0
Wed Jan 18 16:11:36 2017 NOTE: unable to redirect default gateway -- Cannot read current default gateway from system
Wed Jan 18 16:11:36 2017 /bin/ip route add 192.168.178.0/24 via 192.168.178.133
Wed Jan 18 16:11:36 2017 /bin/ip route add 192.168.178.129/32 via 192.168.178.133
Wed Jan 18 16:11:36 2017 add_route_ipv6(fd00::/64 -> fd00::1:2 metric -1) dev tun0
Wed Jan 18 16:11:36 2017 /bin/ip -6 route add fd00::/64 dev tun0
Wed Jan 18 16:11:36 2017 Initialization Sequence Completed

#1 lore raw

Servus,

Quoted 5 lines · Thomas Schäfer

Client:
client
dev tun
proto udp6
remote raspberrypi.XXXXXXXX.myfritz.net 1194 udp6

[..]

Quoted 8 lines

redirect-gateway
verb 3

This works perfectly as long the client has still an IPv4-connection.

But in case of an IPv6-only-client (not system-wide disabled, just not getting IPv4-addresses by the ISP, e.g. eduroam-IPv6) the client doesn't set the IPv4-default route, since it can not find the old one.

I can see the problem.

The most elegant solution might be to use "redirect-gateway def1". The
"def1" flag instructs the code to not add a 0.0.0.0/0 route (replacing and later restoring the existing default route) but to add 0.0.0.0/1 and 128.0.0.0/1 routes - which cover "the default" as well, but do not need to interfere with the existing /0 route.

It might *still* fail, as the code might still want to check and install a v4 /32 host route for the VPN gateway, pointing to the existing default gateway. Which is arguably something that should not be done if we're not talking v4 in the first place, but I'm not sure that part of the code was ever adapted (I'd love to see a log with "def1" :-) ) - the v6 part is smart enough to only try looking at v6 routing tables if we're connecting over v6.

In case "def1" is not enough, please try "redirect-gateway def1 local", which is a hack (but a documented one). "local" signals "do not install a host route pointing to the default gateway, because the VPN server is in the same locally connected network" (think "university wifi"). So that should make things succeed.

If that is still not working, use brute force, and replace "redirect-gateway" with

route 0.0.0.0/1
route 128.0.0.0/1

in the client config - that is the same thing as "def1 local" should give you, but explicitely only the "two half-default routes".

(Whatever the outcome of your tests, I think our code should be smarter
- the v4 code is 10+ years old, and has grown over time, and parts of it have been contributed by non-networking folks...)

gert

Signature · 4 lines
USENET is *not* the non-clickable part of WWW!
                                                           //www.muc.de/~gert/
Gert Doering - Munich, Germany                             [email protected]...
fax: +49-89-35655025                        [email protected]...
#2 lore raw

Am 18.01.2017 um 20:35 schrieb Gert Doering:

Quoted 18 lines

Servus,

Quoted 5 lines · Thomas Schäfer

Client:
client
dev tun
proto udp6
remote raspberrypi.XXXXXXXX.myfritz.net 1194 udp6

[..]

Quoted 8 lines

redirect-gateway
verb 3

This works perfectly as long the client has still an IPv4-connection.

But in case of an IPv6-only-client (not system-wide disabled, just not getting IPv4-addresses by the ISP, e.g. eduroam-IPv6) the client doesn't set the IPv4-default route, since it can not find the old one.

Quoted 7 lines

I can see the problem.

The most elegant solution might be to use "redirect-gateway def1". The
"def1" flag instructs the code to not add a 0.0.0.0/0 route (replacing and later restoring the existing default route) but to add 0.0.0.0/1 and 128.0.0.0/1 routes - which cover "the default" as well, but do not need to interfere with the existing /0 route.

This did not work. Same error as before.

Quoted 6 lines

In case "def1" is not enough, please try "redirect-gateway def1 local", which is a hack (but a documented one). "local" signals "do not install a host route pointing to the default gateway, because the VPN server is in the same locally connected network" (think "university wifi"). So that should make things succeed.

This did not work. Same error as before.

Quoted 7 lines

If that is still not working, use brute force, and replace "redirect-gateway" with

route 0.0.0.0/1
route 128.0.0.0/1

This leads to:

Thu Jan 19 14:10:43 2017 RESOLVE: Cannot resolve host address: 128.0.0.0/1: (Name or service not known) Thu Jan 19 14:10:43 2017 OpenVPN ROUTE: failed to parse/resolve route for host/network: 128.0.0.0/1 Thu Jan 19 14:10:43 2017 RESOLVE: Cannot resolve host address: 0.0.0.0/1: (Name or service not known) Thu Jan 19 14:10:43 2017 OpenVPN ROUTE: failed to parse/resolve route for host/network: 0.0.0.0/1

Quoted 3 lines

in the client config - that is the same thing as "def1 local" should give you, but explicitely only the "two half-default routes".

But

route 0.0.0.0 128.0.0.0
route 128.0.0.0 128.0.0.0

works.

Thomas

#3 lore raw

Hi,

Quoted 6 lines · Thomas Schäfer
Quoted 5 lines

In case "def1" is not enough, please try "redirect-gateway def1 local", which is a hack (but a documented one). "local" signals "do not install a host route pointing to the default gateway, because the VPN server is in the same locally connected network" (think "university wifi"). So that should make things succeed.

This did not work. Same error as before.

This is a bit annoying. It does not need the default gateway when it's not going to use it. *Flag as bug*.

Quoted 10 lines
Quoted 5 lines

If that is still not working, use brute force, and replace "redirect-gateway" with

route 0.0.0.0/1
route 128.0.0.0/1

This leads to:

Thu Jan 19 14:10:43 2017 RESOLVE: Cannot resolve host address:
128.0.0.0/1: (Name or service not known)

Uh. Sorry. Forgot that this is still netmask-land.

Quoted 6 lines

But

route 0.0.0.0 128.0.0.0
route 128.0.0.0 128.0.0.0

works.

This is how the syntax should be. Thanks for testing, happy to finally reach a working solution :-) - and I'll put "rework that v4 stuff" on my limitless TODO list...

gert

Signature · 4 lines
USENET is *not* the non-clickable part of WWW!
                                                           //www.muc.de/~gert/
Gert Doering - Munich, Germany                             [email protected]...
fax: +49-89-35655025                        [email protected]...
#4 lore raw

PATCH 1/1 fix redirect-gateway behaviour when "local" is specified

When no IPv4 default route exists, the "redirect-gateway" routine aborts even if the sub-option "local" was specified.

This is not expected because in this case OpenVPN should not bother checking the existence of the default route at all (as specified in the documentation).

Therefore, avoid the unsolicited abort by skipping the default GW check when "local" is specified.

---

This patch addresses the "*Flag as bug*" concern raised by Gert.

Tested by connecting to a VPN server in the same network/LAN and by removing the default route.

Observed behaviour when "redirect-gateway local" is specified:
- without the patch: no new default route over the VPN is added;
- with the patch: the new default route over the VPN is properly added.

As Gert pointed out, the IPv6-endpoint case needs to be considered as well while applying any routing-table-mangling logic. However, such change will probably affect a larger portion of the code and therefore it is worth its own patch.

Cheers,

 src/openvpn/route.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)
src/openvpn/route.c +9 -10
index 0c93dcd..e439fea 100644
@@ -983,6 +983,7 @@ static void
 redirect_default_route_to_vpn(struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
 {
     const char err[] = "NOTE: unable to redirect default gateway --";
+    bool local = BOOL_CAST(rl->flags & RG_LOCAL);
 
     if (rl && rl->flags & RG_ENABLE)
     {
@@ -990,7 +991,7 @@ redirect_default_route_to_vpn(struct route_list *rl, const struct tuntap *tt, un
         {
             msg(M_WARN, "%s VPN gateway parameter (--route-gateway or --ifconfig) is missing", err);
         }
-        else if (!(rl->rgi.flags & RGI_ADDR_DEFINED))
+        else if (!(rl->rgi.flags & RGI_ADDR_DEFINED) && !local)
         {
             msg(M_WARN, "%s Cannot read current default gateway from system", err);
         }
@@ -1001,7 +1002,6 @@ redirect_default_route_to_vpn(struct route_list *rl, const struct tuntap *tt, un
         else
         {
 #ifndef TARGET_ANDROID
-            bool local = BOOL_CAST(rl->flags & RG_LOCAL);
             if (rl->flags & RG_AUTO_LOCAL)
             {
                 const int tla = rl->spec.remote_host_local;
@@ -1066,14 +1066,13 @@ redirect_default_route_to_vpn(struct route_list *rl, const struct tuntap *tt, un
                 }
                 else
                 {
-                    /* delete default route */
-                    del_route3(0,
-                               0,
-                               rl->rgi.gateway.addr,
-                               tt,
-                               flags | ROUTE_REF_GW,
-                               &rl->rgi,
-                               es);
+                    /* don't try to remove the def route if it does not exist */
+                    if (rl->rgi.flags & RGI_ADDR_DEFINED)
+                    {
+                        /* delete default route */
+                        del_route3(0, 0, rl->rgi.gateway.addr, tt,
+                                   flags | ROUTE_REF_GW, &rl->rgi, es);
+                    }
 
                     /* add new default route */
                     add_route3(0,
Signature · 1 line
2.11.0
#5 lore raw

PATCH v2 1/1 fix redirect-gateway behaviour when an IPv4 default route does not exist

When no IPv4 default route exists, the "redirect-gateway" routine aborts even if the sub-option "local" was specified or if we are connecting to the remote host using IPv6.

This is not expected because in either case OpenVPN should not bother checking the existence of the default route as it is not required at all.

Therefore, skip the IPv4 default route check when "local" is specified or we are connecting to an IPv6 remote host.

---

Actually, the fix required to consider the IPv6 case was not as big as expected, therefore I included it in this v2.

Changes since v1:
- don't perform the default route check if remote host is IPv6
- on shutdown, don't try to re-add default route if it never existed
- move local var to narrower scope

This patch (v2) has been tested under following conditions:

Scenario 1: remove the default route and connect to an IPv4 VPN server within the same network/LAN.

Observed behaviour when "redirect-gateway local" is specified:
- without the patch: no new default route over the VPN is added;
- with the patch: the new default route over the VPN is properly added.

Scenario 2: remove the default route and connect to an IPv6 VPN server.

Observed behaviour when "redirect-gateway" is specified:
- without the patch: no IPv4 default route over the VPN is added;
- with the patch: the IPv4 default route over the VPN is properly added.

Cheers,

 src/openvpn/route.c | 41 ++++++++++++++++++++++-------------------
 1 file changed, 22 insertions(+), 19 deletions(-)
src/openvpn/route.c +22 -19
index 0c93dcd..e23f79a 100644
@@ -986,11 +986,19 @@ redirect_default_route_to_vpn(struct route_list *rl, const struct tuntap *tt, un
 
     if (rl && rl->flags & RG_ENABLE)
     {
+        bool local = rl->flags & RG_LOCAL;
+
         if (!(rl->spec.flags & RTSA_REMOTE_ENDPOINT) && (rl->flags & RG_REROUTE_GW))
         {
             msg(M_WARN, "%s VPN gateway parameter (--route-gateway or --ifconfig) is missing", err);
         }
-        else if (!(rl->rgi.flags & RGI_ADDR_DEFINED))
+        /*
+         * check if a default route is defined, unless:
+         * - we are connecting to a remote host in our network
+         * - we are connecting to a non-IPv4 remote host (i.e. we use IPv6)
+         */
+        else if (!(rl->rgi.flags & RGI_ADDR_DEFINED) && !local
+                 && (rl->spec.remote_host != IPV4_INVALID_ADDR))
         {
             msg(M_WARN, "%s Cannot read current default gateway from system", err);
         }
@@ -1001,7 +1009,6 @@ redirect_default_route_to_vpn(struct route_list *rl, const struct tuntap *tt, un
         else
         {
 #ifndef TARGET_ANDROID
-            bool local = BOOL_CAST(rl->flags & RG_LOCAL);
             if (rl->flags & RG_AUTO_LOCAL)
             {
                 const int tla = rl->spec.remote_host_local;
@@ -1066,14 +1073,13 @@ redirect_default_route_to_vpn(struct route_list *rl, const struct tuntap *tt, un
                 }
                 else
                 {
-                    /* delete default route */
-                    del_route3(0,
-                               0,
-                               rl->rgi.gateway.addr,
-                               tt,
-                               flags | ROUTE_REF_GW,
-                               &rl->rgi,
-                               es);
+                    /* don't try to remove the def route if it does not exist */
+                    if (rl->rgi.flags & RGI_ADDR_DEFINED)
+                    {
+                        /* delete default route */
+                        del_route3(0, 0, rl->rgi.gateway.addr, tt,
+                                   flags | ROUTE_REF_GW, &rl->rgi, es);
+                    }
 
                     /* add new default route */
                     add_route3(0,
@@ -1145,15 +1151,12 @@ undo_redirect_default_route_to_vpn(struct route_list *rl, const struct tuntap *t
                            flags,
                            &rl->rgi,
                            es);
-
-                /* restore original default route */
-                add_route3(0,
-                           0,
-                           rl->rgi.gateway.addr,
-                           tt,
-                           flags | ROUTE_REF_GW,
-                           &rl->rgi,
-                           es);
+                /* restore original default route if there was any */
+                if (rl->rgi.flags & RGI_ADDR_DEFINED)
+                {
+                    add_route3(0, 0, rl->rgi.gateway.addr, tt,
+                               flags | ROUTE_REF_GW, &rl->rgi, es);
+                }
             }
         }
 
Signature · 1 line
2.11.0
#6 lore raw

[Openvpn-devel] [PATCH applied] Re: fix redirect-gateway behaviour when an IPv4 default route does not exist

ACK.

Verified the problematic behaviour (connected from a FreeBSD 11 system without an IPv4 default route to a v6-transport VPN server, and it refused "redirect-gateway", with or without "def1") - and with the patch, it does the expected thing.

Also, stared at the code :-)

Your patch has been applied to the master and release/2.4 branch.

commit 14670a9d654be48f92b58ac47e6f74d3dcfe1733 (master) commit 5340f56b62c9fe7ad892e815029321f378660714 (release/2.4)

Author: Antonio Quartulli
Date:   Fri Jan 20 00:25:18 2017 +0800
     fix redirect-gateway behaviour when an IPv4 default route does not exist

     Signed-off-by: Antonio Quartulli <[email protected]...>
     Acked-by: Gert Doering <[email protected]...>
     Message-Id: <[email protected]...>
     URL: https://www.mail-archive.com/[email protected]/msg13905.html
     Signed-off-by: Gert Doering <[email protected]...>

--
kind regards,

Gert Doering

#7 lore raw
In reply to Thomas Schäfer

Hi,

following up on the thread starter...

Quoted 5 lines · Thomas Schäfer

This works perfectly as long the client has still an IPv4-connection.

But in case of an IPv6-only-client (not system-wide disabled, just not getting IPv4-addresses by the ISP, e.g. eduroam-IPv6) the client doesn't set the IPv4-default route, since it can not find the old one.

This has been fixed (thanks, Antonio), and the fix will be in the upcoming 2.4.1 release - no fixed date has been set but "in the next few weeks" or so.

Thanks for reporting this application silliness :-)

gert

Signature · 4 lines
USENET is *not* the non-clickable part of WWW!
                                                           //www.muc.de/~gert/
Gert Doering - Munich, Germany                             [email protected]...
fax: +49-89-35655025                        [email protected]...
#9 lore raw
Quoted 2 lines · Thomas Schäfer

By the way.
It works. (with 2.4.1)

Glad to hear that!

Thanks for reporting back.

Cheers,

Signature · 1 line
Antonio Quartulli