Hello everyone,

I’m resubmitting the client-nat network option patch with the changes
suggested by the community. The main updates include:

- Replaced the network token from "localhost" to "assigned-ip". Example:

client-nat snat assigned-ip 255.255.255.255 172.19.80.17

- Formatted the code according to the uncrustify.conf syntax.

- Updated client-options.rst to reflect the changes in client-nat
parameters. The examples were also corrected as they were syntactically
incorrect.

The code was successfully built on GitHub without warnings, including
passing the Check code style verification.

Additionally, based on Arne’s comments, the patch was successfully tested
using a P2P configuration (openvpn-examples man page - Example 2: A tunnel
with self-signed certificates and fingerprint). Below is the configuration
used to validate the patch. Some parameters were added to test the
client-nat scenario:

Server-side:

The server has an additional NIC with IP address set to: 10.0.2.15.

openvpn --ifconfig 10.4.0.1 10.4.0.2 --tls-server --dev tun --dh none \
--cert ../../../bob.pem --key ../../../bob.pem --cipher AES-256-GCM \
--peer-fingerprint
"C8:07:53:8C:42:80:11:85:C5:F0:E2:23:CD:EF:26:2A:26:13:28:23:FB:FD:00:FF:2F:22:88:E4:B4:96:47:67"
\
--push "route 10.0.2.0 255.255.255.0 10.4.0.1" --route 10.0.2.16
255.255.255.255 10.4.0.1

Client-side:

openvpn --remote 192.168.58.115 --tls-client --dev tun --ifconfig 10.4.0.2
10.4.0.1 \
--cipher AES-256-GCM --cert alice.pem --key alice.pem \
--peer-fingerprint
"51:FC:7B:96:74:57:0E:EF:0E:A7:C4:DD:72:B4:C7:13:2E:2B:72:8E:BE:77:15:C8:7E:D1:64:44:DA:C7:7C:6C"
\
--client-nat snat assigned-ip 255.255.255.255 10.0.2.16 --client

The client was able to ping both server IPs, 10.4.0.1 and 10.0.2.15, as it
was source NATing to 10.0.2.16.


Please let me know if you have any questions.

Best regards,
Rafael

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

>From 4005dce58440e44bbade4da6cce93da56d12e9ed Mon Sep 17 00:00:00 2001
From: Rafael Gava <gava...@gmail.com>
Date: Mon, 24 Feb 2025 20:24:20 +0000
Subject: [PATCH] Added the assigned-ip token to the client-nat network
option,
 enabling the application to dynamically use the client IP provided by the
 server.

Signed-off-by: Rafael Gava <gava...@gmail.com>
---
 doc/man-sections/client-options.rst | 18 +++++++----
 src/openvpn/clinat.c                | 50 ++++++++++++++++++++++++++---
 src/openvpn/clinat.h                |  2 ++
 src/openvpn/init.c                  |  2 ++
 src/openvpn/options.c               |  1 +
 5 files changed, 62 insertions(+), 11 deletions(-)

diff --git a/doc/man-sections/client-options.rst
b/doc/man-sections/client-options.rst
index 0aee9e24..cb951640 100644
--- a/doc/man-sections/client-options.rst
+++ b/doc/man-sections/client-options.rst
@@ -135,17 +135,21 @@ configuration.
   Examples:
   ::

-      client-nat snat 192.168.0.0/255.255.0.0
-      client-nat dnat 10.64.0.0/255.255.0.0
-
-  ``network/netmask`` (for example :code:`192.168.0.0/255.255.0.0`) defines
-  the local view of a resource from the client perspective, while
-  ``alias/netmask`` (for example :code:`10.64.0.0/255.255.0.0`) defines the
-  remote view from the server perspective.
+      client-nat snat assigned-ip 255.255.255.255 172.17.80.17
+      client-nat snat 192.168.100.102 255.255.255.255 172.17.80.18
+      client-nat dnat 10.64.0.0 255.255.0.0 192.168.0.0

   Use :code:`snat` (source NAT) for resources owned by the client and
   :code:`dnat` (destination NAT) for remote resources.

+  ``network`` defines the local view of a resource from the client
perspective.
+  Use :code:`assigned-ip` to instruct openvpn to use the assigned ip
address
+  received from the server.
+
+  ``netmask`` specifies the local mask.
+
+  ``alias`` defines the remote view from the server perspective.
+
   Set ``--verb 6`` for debugging info showing the transformation of
   src/dest addresses in packets.

diff --git a/src/openvpn/clinat.c b/src/openvpn/clinat.c
index 2d3b359f..d377f0a0 100644
--- a/src/openvpn/clinat.c
+++ b/src/openvpn/clinat.c
@@ -127,12 +127,21 @@ add_client_nat_to_option_list(struct
client_nat_option_list *dest,
         return;
     }

-    e.network = getaddr(0, network, 0, &ok, NULL);
-    if (!ok)
+    if (network && !strcmp(network, "assigned-ip"))
     {
-        msg(msglevel, "client-nat: bad network: %s", network);
-        return;
+        msg(M_INFO, "*** client-nat assigned-ip detected...");
+        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)
     {
@@ -274,3 +283,36 @@ client_nat_transform(const struct
client_nat_option_list *list,
         }
     }
 }
+
+/*
+ * Replaces the assigned-ip token with the IP received from OpenVPN
+ */
+bool
+update_assignedip_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, "CNAT - Updating NAT table from assigned-ip to:
%s", dot_ip);
+            ret = true;
+        }
+    }
+
+    return ret;
+}
diff --git a/src/openvpn/clinat.h b/src/openvpn/clinat.h
index 94141f51..24663a7c 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_assignedip_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 b57e5f8a..c6547c76 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -2052,6 +2052,8 @@ do_open_tun(struct context *c, int *error_flags)
             *error_flags |= (status ? 0 : ISC_ROUTE_ERRORS);
         }

+        update_assignedip_nat(c->options.client_nat, c->c1.tuntap->local);
+
         ret = true;
         static_context = c;
     }
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 6b2dfa58..6c401f6b 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -254,6 +254,7 @@ static const char usage_message[] =
     "                   (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"
+    "                  set the network to 'assigned-ip' to use the client
ip received from the server.\n"
     "--push-peer-info : (client only) push client info to server.\n"
     "--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"
-- 
2.39.5
_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to