Your message dated Tue, 03 Oct 2017 23:35:55 +0200
with message-id <[email protected]>
and subject line Re: openvpn: redirect-gateway fails when default route does 
not use a gateway
has caused the Debian Bug report #592088,
regarding openvpn: redirect-gateway fails when default route does not use a 
gateway
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
592088: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=592088
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Package: openvpn
Version: 2.1.0-3
Severity: normal
Tags: patch

In this situation:

master@doggy:~$ /sbin/ip route list exact 0.0.0.0/0
default dev ppp0  scope link
master@doggy:~$ head -n1 /proc/net/route; awk '$2==00000000' /proc/net/route
Iface   Destination     Gateway         Flags   RefCnt  Use     Metric  Mask    
        MTU     Window  IRTT
ppp0    00000000        00000000        0001    0       0       0       
00000000        0       0       0

the "redirect-gateway" option fails:

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

While that option is indeed called "redirect-gateway", I feel its
expected behaviour is better described by "redirect-default-route".

The attached patch makes it work in this scenario, on Linux only. It
makes the minimal work to make this scenario work cleanly; the full
work would probably be to expand the notion of route everywhere in the
code not to expect a gateway, but a gateway, a device or both.

-- System Information:
Debian Release: 5.0.5
  APT prefers stable
  APT policy: (500, 'stable'), (400, 'testing'), (300, 'unstable')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.32-5-amd64 (SMP w/2 CPU cores)
Locale: LANG=fr_LU.UTF-8, LC_CTYPE=fr_LU.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages openvpn depends on:
ii  debconf [debconf-2.0]     1.5.24         Debian configuration management sy
ii  libc6                     2.11.2-2       Embedded GNU C Library: Shared lib
ii  liblzo2-2                 2.03-1         data compression library
ii  libpam0g                  1.0.1-5+lenny1 Pluggable Authentication Modules l
ii  libpkcs11-helper1         1.05-1         library that simplifies the intera
ii  libssl0.9.8               0.9.8o-1       SSL shared libraries
ii  net-tools                 1.60-22        The NET-3 networking toolkit
ii  openssl-blacklist         0.5-2          list of blacklisted OpenSSL RSA ke
ii  openvpn-blacklist         0.4            list of blacklisted OpenVPN RSA sh

openvpn recommends no packages.

Versions of packages openvpn suggests:
ii  openssl                 0.9.8g-15+lenny7 Secure Socket Layer (SSL) binary a
ii  resolvconf              1.46             name server information handler

-- debconf information:
  openvpn/vulnerable_prng:
  openvpn/create_tun: false
Index: openvpn-2.1.0.lio/route.c
===================================================================
--- openvpn-2.1.0.lio.orig/route.c      2010-08-07 12:50:11.000000000 +0200
+++ openvpn-2.1.0.lio/route.c   2010-08-07 12:50:33.000000000 +0200
@@ -140,7 +140,7 @@
 }
 
 static void
-setenv_route_addr (struct env_set *es, const char *key, const in_addr_t addr, 
int i)
+setenv_route_str (struct env_set *es, const char *key, const char *str, int i)
 {
   struct gc_arena gc = gc_new ();
   struct buffer name = alloc_buf_gc (256, &gc);
@@ -148,7 +148,15 @@
     buf_printf (&name, "route_%s_%d", key, i);
   else
     buf_printf (&name, "route_%s", key);
-  setenv_str (es, BSTR (&name), print_in_addr_t (addr, 0, &gc));
+  setenv_str (es, BSTR (&name), str);
+  gc_free (&gc);
+}
+
+static void
+setenv_route_addr (struct env_set *es, const char *key, const in_addr_t addr, 
int i)
+{
+  struct gc_arena gc = gc_new ();
+  setenv_route_str (es, key, print_in_addr_t (addr, 0, &gc), i);
   gc_free (&gc);
 }
 
@@ -180,7 +188,7 @@
       if (spec)
        {
          if (spec->net_gateway_defined)
-           *out = spec->net_gateway;
+           *out = spec->net_gateway.net_gateway_addr;
          else
            {
              msg (M_INFO, PACKAGE_NAME " ROUTE: net_gateway undefined -- 
unable to get default gateway from system");
@@ -397,8 +405,12 @@
   rl->spec.net_gateway_defined = get_default_gateway (&rl->spec.net_gateway, 
NULL);
   if (rl->spec.net_gateway_defined)
     {
-      setenv_route_addr (es, "net_gateway", rl->spec.net_gateway, -1);
-      dmsg (D_ROUTE, "ROUTE default_gateway=%s", print_in_addr_t 
(rl->spec.net_gateway, 0, &gc));
+      setenv_route_addr (es, "net_gateway", 
rl->spec.net_gateway.net_gateway_addr, -1);
+      setenv_route_str (es, "net_gateway_dev", 
rl->spec.net_gateway.net_gateway_dev, -1);
+      dmsg (D_ROUTE,
+           "ROUTE default_gateway=%s dev=%s",
+           print_in_addr_t (rl->spec.net_gateway.net_gateway_addr, 0, &gc),
+           rl->spec.net_gateway.net_gateway_dev);
     }
   else
     {
@@ -474,6 +486,7 @@
   r.network = network;
   r.netmask = netmask;
   r.gateway = gateway;
+  r.dev[0] = '\0';
   add_route (&r, tt, flags, es);
 }
 
@@ -495,8 +508,44 @@
 }
 
 static void
+add_route4 (in_addr_t network,
+           in_addr_t netmask,
+           net_gateway_t gateway,
+           const struct tuntap *tt,
+           unsigned int flags,
+           const struct env_set *es)
+{
+  struct route r;
+  CLEAR (r);
+  r.defined = true;
+  r.network = network;
+  r.netmask = netmask;
+  r.gateway = gateway.net_gateway_addr;
+  strncpy(r.dev,gateway.net_gateway_dev, IF_NAME_SIZE);
+  add_route (&r, tt, flags, es);
+}
+
+static void
+del_route4 (in_addr_t network,
+           in_addr_t netmask,
+           net_gateway_t gateway,
+           const struct tuntap *tt,
+           unsigned int flags,
+           const struct env_set *es)
+{
+  struct route r;
+  CLEAR (r);
+  r.defined = true;
+  r.network = network;
+  r.netmask = netmask;
+  r.gateway = gateway.net_gateway_addr;
+  strncpy(r.dev,gateway.net_gateway_dev, IF_NAME_SIZE);
+  delete_route (&r, tt, flags, es);
+}
+
+static void
 add_bypass_routes (struct route_bypass *rb,
-                  in_addr_t gateway,
+                  net_gateway_t gateway,
                   const struct tuntap *tt,
                   unsigned int flags,
                   const struct env_set *es)
@@ -504,8 +553,8 @@
   int i;
   for (i = 0; i < rb->n_bypass; ++i)
     {
-      if (rb->bypass[i] != gateway)
-       add_route3 (rb->bypass[i],
+      if (rb->bypass[i] != gateway.net_gateway_addr)
+       add_route4 (rb->bypass[i],
                    ~0,
                    gateway,
                    tt,
@@ -516,7 +565,7 @@
 
 static void
 del_bypass_routes (struct route_bypass *rb,
-                  in_addr_t gateway,
+                  net_gateway_t gateway,
                   const struct tuntap *tt,
                   unsigned int flags,
                   const struct env_set *es)
@@ -524,8 +573,8 @@
   int i;
   for (i = 0; i < rb->n_bypass; ++i)
     {
-      if (rb->bypass[i] != gateway)
-       del_route3 (rb->bypass[i],
+      if (rb->bypass[i] != gateway.net_gateway_addr)
+       del_route4 (rb->bypass[i],
                    ~0,
                    gateway,
                    tt,
@@ -577,7 +626,7 @@
               * adding this special /32 route */
              if (rl->spec.remote_host != IPV4_INVALID_ADDR) {
 #endif
-               add_route3 (rl->spec.remote_host,
+               add_route4 (rl->spec.remote_host,
                            ~0,
                            rl->spec.net_gateway,
                            tt,
@@ -617,7 +666,7 @@
              else
                {
                  /* delete default route */
-                 del_route3 (0,
+                 del_route4 (0,
                              0,
                              rl->spec.net_gateway,
                              tt,
@@ -648,7 +697,7 @@
       /* delete remote host route */
       if (rl->did_local)
        {
-         del_route3 (rl->spec.remote_host,
+         del_route4 (rl->spec.remote_host,
                      ~0,
                      rl->spec.net_gateway,
                      tt,
@@ -691,7 +740,7 @@
                          es);
 
              /* restore original default route */
-             add_route3 (0,
+             add_route4 (0,
                          0,
                          rl->spec.net_gateway,
                          tt,
@@ -814,6 +863,7 @@
       setenv_route_addr (es, "network", r->network, i);
       setenv_route_addr (es, "netmask", r->netmask, i);
       setenv_route_addr (es, "gateway", r->gateway, i);
+      setenv_route_str (es, "device", r->dev, i);
 
       if (r->metric_defined)
        {
@@ -870,15 +920,20 @@
              network,
              count_netmask_bits(netmask),
              gateway);
+  if (r->dev[0])
+    argv_printf_cat (&argv, "dev %s", r->dev);
   if (r->metric_defined)
     argv_printf_cat (&argv, "metric %d", r->metric);
 
 #else
-  argv_printf (&argv, "%s add -net %s netmask %s gw %s",
+  argv_printf (&argv, "%s add -net %s netmask %s",
                ROUTE_PATH,
              network,
-             netmask,
-             gateway);
+             netmask);
+  if (r->gateway)
+    argv_printf_cat (&argv, "gw %s", gateway);
+  if (r->dev[0])
+    argv_printf_cat (&argv, "dev %s", r->dev);
   if (r->metric_defined)
     argv_printf_cat (&argv, "metric %d", r->metric);
 #endif  /*CONFIG_FEATURE_IPROUTE*/
@@ -1313,7 +1368,7 @@
 }
 
 bool
-get_default_gateway (in_addr_t *gw, in_addr_t *netmask)
+get_default_gateway (net_gateway_t *gw, in_addr_t *netmask)
 {
   struct gc_arena gc = gc_new ();
   bool ret_bool = false;
@@ -1535,7 +1590,7 @@
 #elif defined(TARGET_LINUX)
 
 bool
-get_default_gateway (in_addr_t *gateway, in_addr_t *netmask)
+get_default_gateway (net_gateway_t *gateway, in_addr_t *netmask)
 {
   struct gc_arena gc = gc_new ();
   bool ret = false;
@@ -1546,7 +1601,7 @@
       int count = 0;
       int best_count = 0;
       unsigned int lowest_metric = ~0;
-      in_addr_t best_gw = 0;
+      net_gateway_t best_gw = NET_GATEWAY_NULL;
       while (fgets (line, sizeof (line), fp) != NULL)
        {
          if (count)
@@ -1555,27 +1610,32 @@
              unsigned int mask_x = 0;
              unsigned int gw_x = 0;
              unsigned int metric = 0;
-             const int np = sscanf (line, "%*s\t%x\t%x\t%*s\t%*s\t%*s\t%d\t%x",
+             char dev[IF_NAME_SIZE];
+             dev[0] = '\0';
+             const int np = sscanf (line, "%s\t%x\t%x\t%*s\t%*s\t%*s\t%d\t%x",
+                                    dev,
                                     &net_x,
                                     &gw_x,
                                     &metric,
                                     &mask_x);
-             if (np == 4)
+             if (np == 5)
                {
                  const in_addr_t net = ntohl (net_x);
                  const in_addr_t mask = ntohl (mask_x);
-                 const in_addr_t gw = ntohl (gw_x);
+                 const in_addr_t gw_addr = ntohl (gw_x);
 
-                 dmsg (D_ROUTE_DEBUG, "GDG: route[%d] %s/%s/%s m=%u",
+                 dmsg (D_ROUTE_DEBUG, "GDG: route[%d] %s/%s/%s m=%u dev=%s",
                        count,
                        print_in_addr_t ((in_addr_t) net, 0, &gc),
                        print_in_addr_t ((in_addr_t) mask, 0, &gc),
-                       print_in_addr_t ((in_addr_t) gw, 0, &gc),
-                       metric);
+                       print_in_addr_t ((in_addr_t) gw_addr, 0, &gc),
+                       metric,
+                       dev);
 
                  if (!net && !mask && metric < lowest_metric)
                    {
-                     best_gw = gw;
+                     best_gw.net_gateway_addr = gw_addr;
+                     strncpy(best_gw.net_gateway_dev, dev, IF_NAME_SIZE);
                      lowest_metric = metric;
                      best_count = count;
                    }
@@ -1585,7 +1645,7 @@
        }
       fclose (fp);
 
-      if (best_gw)
+      if (best_gw.net_gateway_addr || best_gw.net_gateway_dev[0])
        {
          *gateway = best_gw;
          if (netmask)
@@ -1595,8 +1655,9 @@
          ret = true;
        }
 
-      dmsg (D_ROUTE_DEBUG, "GDG: best=%s[%d] lm=%u",
-           print_in_addr_t ((in_addr_t) best_gw, 0, &gc),
+      dmsg (D_ROUTE_DEBUG, "GDG: best=%s dev '%s' [%d] lm=%u",
+           print_in_addr_t ((in_addr_t) best_gw.net_gateway_addr, 0, &gc),
+           best_gw.net_gateway_dev,
            best_count,
            (unsigned int)lowest_metric);
     }
Index: openvpn-2.1.0.lio/route.h
===================================================================
--- openvpn-2.1.0.lio.orig/route.h      2010-08-07 12:50:11.000000000 +0200
+++ openvpn-2.1.0.lio/route.h   2010-08-07 12:50:33.000000000 +0200
@@ -56,11 +56,18 @@
   in_addr_t bypass[N_ROUTE_BYPASS];
 };
 
+#define IF_NAME_SIZE 128
+typedef struct {
+  in_addr_t net_gateway_addr;
+  char net_gateway_dev[IF_NAME_SIZE];
+} net_gateway_t;
+#define NET_GATEWAY_NULL {0, ""}
+
 struct route_special_addr
 {
   in_addr_t remote_endpoint;
   bool remote_endpoint_defined;
-  in_addr_t net_gateway;
+  net_gateway_t net_gateway;
   bool net_gateway_defined;
   in_addr_t remote_host;
   bool remote_host_defined;
@@ -98,6 +105,7 @@
   in_addr_t network;
   in_addr_t netmask;
   in_addr_t gateway;
+  char dev[IF_NAME_SIZE];
   bool metric_defined;
   int metric;
 };
@@ -161,7 +169,7 @@
 
 bool is_special_addr (const char *addr_str);
 
-bool get_default_gateway (in_addr_t *ip, in_addr_t *netmask);
+bool get_default_gateway (net_gateway_t *gateway, in_addr_t *netmask);
 
 /*
  * Test if addr is reachable via a local interface (return ILA_LOCAL),
Index: openvpn-2.1.0.lio/tun.c
===================================================================
--- openvpn-2.1.0.lio.orig/tun.c        2010-08-07 12:56:04.000000000 +0200
+++ openvpn-2.1.0.lio/tun.c     2010-08-07 12:56:46.000000000 +0200
@@ -271,12 +271,12 @@
                       const char *prefix)
 {
   struct gc_arena gc = gc_new ();
-  in_addr_t lan_gw = 0;
+  net_gateway_t lan_gw = NET_GATEWAY_NULL;
   in_addr_t lan_netmask = 0;
 
   if (get_default_gateway (&lan_gw, &lan_netmask))
     {
-      const in_addr_t lan_network = lan_gw & lan_netmask; 
+      const in_addr_t lan_network = lan_gw.net_gateway_addr & lan_netmask;
       const in_addr_t network = ip & netmask;
 
       /* do the two subnets defined by network/netmask and 
lan_network/lan_netmask intersect? */
@@ -298,12 +298,12 @@
 warn_on_use_of_common_subnets (void)
 {
   struct gc_arena gc = gc_new ();
-  in_addr_t lan_gw = 0;
+  net_gateway_t lan_gw = NET_GATEWAY_NULL;
   in_addr_t lan_netmask = 0;
 
   if (get_default_gateway (&lan_gw, &lan_netmask))
     {
-      const in_addr_t lan_network = lan_gw & lan_netmask; 
+      const in_addr_t lan_network = lan_gw.net_gateway_addr & lan_netmask;
       if (lan_network == 0xC0A80000 || lan_network == 0xC0A80100)
        msg (M_WARN, "NOTE: your local LAN uses the extremely common subnet 
address 192.168.0.x or 192.168.1.x.  Be aware that this might create routing 
conflicts if you connect to the VPN server from public locations such as 
internet cafes that use the same subnet.");
     }

--- End Message ---
--- Begin Message ---
Hello Lionel,

first thank you for spending your time helping to make Debian better
with this bug report.

You patch is currently[1] broken. So we can't apply them and I close
this bug.


CU
Jörg


[1] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=592088#20

-- 
New:
GPG Fingerprint: 63E0 075F C8D4 3ABB 35AB  30EE 09F8 9F3C 8CA1 D25D
GPG key (long) : 09F89F3C8CA1D25D
GPG Key        : 8CA1D25D
CAcert Key S/N : 0E:D4:56

Old pgp Key: BE581B6E (revoked since 2014-12-31).

Jörg Frings-Fürst
D-54470 Lieser

Threema: SYR8SJXB
Wire:  @joergfringsfuerst
Skype: joergpenguin
Ring:  jff

IRC: [email protected]
     [email protected]

My wish list: 
 - Please send me a picture from the nature at your home.

Attachment: signature.asc
Description: This is a digitally signed message part


--- End Message ---

Reply via email to