[Openvpn-devel] NAT client-ip

Message ID CAAWBBYMu6mT+H3atWxx1Stqt63kvTj-MGpUiM_2uDnAjbqNb=w@mail.gmail.com
State Changes Requested
Headers show
Series [Openvpn-devel] NAT client-ip | expand

Commit Message

Rafael Gava Sept. 13, 2020, 3:23 p.m. UTC
Hello guys,

A couple years ago I submitted this patch which allows the user to set the
'client-ip' as a convenient way to use the leased IP address received from
OpenVPN server in NAT configuration. For example:

client-nat snat client-ip 255.255.255.255 172.20.1.15

, where 'client-ip' string is replaced with the leased IP address received
from OpenVPN server.

At that time, it was NACKED due to the fact that I was using both client-ip
and localhost strings. So, it's changed now and I'd like to re-submit it
again for appreciation.

Thanks

Gava

-------------------------------------

From e273b13bc10da8f917a981957cf2c43ba6bd1e10 Mon Sep 17 00:00:00 2001
From: Rafael Gava de Oliveira <Rafael.Oliveira@venturus.org.br>
Date: Sat, 12 Sep 2020 19:27:25 -0300
Subject: [PATCH] Allows the usage of the string 'client-ip' in the
client-nat
 network configuration in a way that is not necessary to inform the IP
address
 beforehand. Openvpn will dynamically set the received IP from DHCP.

Example:

client-nat snat client-ip 255.255.255.255 172.20.1.15

Replaces the 'client-ip' string with the DHCP address received from
the openvpn server.
---
 src/openvpn/clinat.c  | 45 ++++++++++++++++++++++++++++++++++++++++-----
 src/openvpn/clinat.h  |  2 ++
 src/openvpn/init.c    |  2 ++
 src/openvpn/options.c |  2 +-
 4 files changed, 45 insertions(+), 6 deletions(-)
 mode change 100644 => 100755 src/openvpn/clinat.c

     "--setenv name value : Set a custom environmental variable to pass to
script.\n"
     "--setenv FORWARD_COMPATIBLE 1 : Relax config file syntax checking to
allow\n"

Comments

Arne Schwabe Oct. 1, 2020, 1:39 a.m. UTC | #1
Am 14.09.20 um 03:23 schrieb Rafael Gava:
> Hello guys,
> 
> A couple years ago I submitted this patch which allows the user to set
> the 'client-ip' as a convenient way to use the leased IP address
> received from OpenVPN server in NAT configuration. For example:
> 
> client-nat snat client-ip 255.255.255.255 172.20.1.15
> 
> , where 'client-ip' string is replaced with the leased IP address
> received from OpenVPN server.
> 
> At that time, it was NACKED due to the fact that I was using both
> client-ip and localhost strings. So, it's changed now and I'd like to
> re-submit it again for appreciation.


The patch is not easy to apply since it seems to be copy&pasted inline
and not as attachment or via git-send-email and my git does not like it
at all and quits with 'Patch is empty.' Even after copying and pasting
the patch manually I get:

error: corrupt patch at line 21



> diff --git a/src/openvpn/clinat.c b/src/openvpn/clinat.c
> old mode 100644
> new mode 100755
> index b08fd54..865b0e2
> --- a/src/openvpn/clinat.c
> +++ b/src/openvpn/clinat.c
> @@ -128,12 +128,16 @@ add_client_nat_to_option_list(struct
> client_nat_option_list *dest,
>          msg(msglevel, "client-nat: type must be 'snat' or 'dnat'");
>          return;
>      }
> -
> -    e.network = getaddr(0, network, 0, &ok, NULL);
> -    if (!ok)
> +    if (network && !strcmp(network, "client-ip"))
>      {
> -        msg(msglevel, "client-nat: bad network: %s", network);
> -        return;
> +        e.network = 0xFFFFFFFF;

I am not happy about abusing 255.255.255.255 with any netmask as a
standin for localhost. Is there any need to have any other netmask than
/32 for client-ip? And if we are using a network for the IP I would
rather use a special IP from the 127/8 block with a define here. Or
maybe even add new flag like CN_SNAT_CLIENT_IP/CN_DNAT_CLIENT_IP that
get replaced with the real information later.


> +    } else {
> +        e.network = getaddr(0, network, 0, &ok, NULL);
> +        if (!ok)
> +        {
> +            msg(msglevel, "client-nat: bad network: %s", network);
> +            return;
> +        }
>      }
>      e.netmask = getaddr(0, netmask, 0, &ok, NULL);
>      if (!ok)
> @@ -276,3 +280,34 @@ client_nat_transform(const struct
> client_nat_option_list *list,
>          }
>      }
>  }
> +
> +/*
> +* Replaces the client-ip token with the IP received from OpenVPN Server
> +*/
> +bool
> +update_client_ip_nat(struct client_nat_option_list *dest, in_addr_t
> local_ip)
> +{
> +    int i;
> +    bool ret = false;
> +

Please use C99 inline declaration, i.e. move the int i into the for loop.


> +    if (!dest)
> +        return ret;
> +
> +    for (i=0; i <= dest->n; i++)
> +    {
> +        struct client_nat_entry *nat_entry = &dest->entries[i];
> +        if (nat_entry && nat_entry->network == 0xFFFFFFFF)
> +        {
> +            struct in_addr addr;
> +
> +            nat_entry->network = ntohl(local_ip);
> +            addr.s_addr = nat_entry->network;
> +            char *dot_ip = inet_ntoa(addr);
> +
> +            msg (M_INFO, "Updating NAT table client-ip to: %s", dot_ip);

Logging this always with M_INFO feel excessive.

Arne

Patch

diff --git a/src/openvpn/clinat.c b/src/openvpn/clinat.c
old mode 100644
new mode 100755
index b08fd54..865b0e2
--- a/src/openvpn/clinat.c
+++ b/src/openvpn/clinat.c
@@ -128,12 +128,16 @@  add_client_nat_to_option_list(struct
client_nat_option_list *dest,
         msg(msglevel, "client-nat: type must be 'snat' or 'dnat'");
         return;
     }
-
-    e.network = getaddr(0, network, 0, &ok, NULL);
-    if (!ok)
+    if (network && !strcmp(network, "client-ip"))
     {
-        msg(msglevel, "client-nat: bad network: %s", network);
-        return;
+        e.network = 0xFFFFFFFF;
+    } else {
+        e.network = getaddr(0, network, 0, &ok, NULL);
+        if (!ok)
+        {
+            msg(msglevel, "client-nat: bad network: %s", network);
+            return;
+        }
     }
     e.netmask = getaddr(0, netmask, 0, &ok, NULL);
     if (!ok)
@@ -276,3 +280,34 @@  client_nat_transform(const struct
client_nat_option_list *list,
         }
     }
 }
+
+/*
+* Replaces the client-ip token with the IP received from OpenVPN Server
+*/
+bool
+update_client_ip_nat(struct client_nat_option_list *dest, in_addr_t
local_ip)
+{
+    int i;
+    bool ret = false;
+
+    if (!dest)
+        return ret;
+
+    for (i=0; i <= dest->n; i++)
+    {
+        struct client_nat_entry *nat_entry = &dest->entries[i];
+        if (nat_entry && nat_entry->network == 0xFFFFFFFF)
+        {
+            struct in_addr addr;
+
+            nat_entry->network = ntohl(local_ip);
+            addr.s_addr = nat_entry->network;
+            char *dot_ip = inet_ntoa(addr);
+
+            msg (M_INFO, "Updating NAT table client-ip to: %s", dot_ip);
+            ret = true;
+        }
+    }
+
+    return ret;
+}
diff --git a/src/openvpn/clinat.h b/src/openvpn/clinat.h
index eec7a03..c2941b9 100644
--- a/src/openvpn/clinat.h
+++ b/src/openvpn/clinat.h
@@ -64,4 +64,6 @@  void client_nat_transform(const struct
client_nat_option_list *list,
                           struct buffer *ipbuf,
                           const int direction);

+bool update_client_ip_nat(struct client_nat_option_list *dest, in_addr_t
local_ip);
+
 #endif /* if !defined(CLINAT_H) */
diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index a785934..8d6f9a8 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -1920,6 +1920,8 @@  do_open_tun(struct context *c)
                               SET_MTU_TUN | SET_MTU_UPPER_BOUND);
     }

+    update_client_ip_nat(c->options.client_nat, c->c1.tuntap->local);
+
     ret = true;
     static_context = c;
 #ifndef TARGET_ANDROID
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 8bf82c5..26f11fa 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -231,7 +231,7 @@  static const char usage_message[] =
     "                   ICMPv6 host unreachable messages on the client.\n"
     "                   (Server) Instead of forwarding IPv6 packets send\n"
     "                   ICMPv6 host unreachable packets to the client.\n"
-    "--client-nat snat|dnat network netmask alias : on client add 1-to-1
NAT rule.\n"
+    "--client-nat snat|dnat network|'client-ip' netmask alias : on client
add 1-to-1 NAT rule.\n"
     "--push-peer-info : (client only) push client info to server.\n"