Dear OpenVPN Community, I am submitting this patch to introduce a 'localhost' token to the `client-nat` network option, allowing OpenVPN clients to dynamically use the IP address provided by the server. This enhancement is particularly useful in scenarios where OpenVPN is deployed as a VPN gateway bridging a local network and a VPN tunnel.
Currently, the `client-nat` option requires a static client IP, which limits its flexibility when dealing with dynamically assigned IP addresses. By introducing a 'localhost' token, OpenVPN can automatically substitute it with the current client-assigned IP address, streamlining network configurations in dynamic environments. Example: client-nat snat localhost 255.255.255.255 172.19.80.17 I believe this feature will be beneficial for many OpenVPN users, improving automation and simplifying VPN gateway configurations. Please find the patch inline for review and feedback. Best regards, Rafael Gava ---- >From fbc7045d652b5f11e2aa043aa2af9ca14f36b604 Mon Sep 17 00:00:00 2001 From: Rafael Gava <gava...@gmail.com> Date: Thu, 20 Feb 2025 19:19:39 +0000 Subject: [PATCH] Added the localhost 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> --- src/openvpn/clinat.c | 47 +++++++++++++++++++++++++++++++++++++++---- src/openvpn/clinat.h | 3 +++ src/openvpn/init.c | 2 ++ src/openvpn/options.c | 1 + 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/openvpn/clinat.c b/src/openvpn/clinat.c index 2d3b359f..1c79b20d 100644 --- a/src/openvpn/clinat.c +++ b/src/openvpn/clinat.c @@ -127,12 +127,19 @@ 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, "localhost")) { - msg(msglevel, "client-nat: bad network: %s", network); - return; + msg (M_INFO, "*** client-nat localhost 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 +281,35 @@ client_nat_transform(const struct client_nat_option_list *list, } } } + +/* +* Replaces the localhost token with the IP received from OpenVPN +*/ +bool +update_localhost_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 localhost to: %s", dot_ip); + ret = true; + } + } + + return ret; +} diff --git a/src/openvpn/clinat.h b/src/openvpn/clinat.h index 94141f51..06afa3b4 100644 --- a/src/openvpn/clinat.h +++ b/src/openvpn/clinat.h @@ -64,4 +64,7 @@ void client_nat_transform(const struct client_nat_option_list *list, struct buffer *ipbuf, const int direction); +bool update_localhost_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..dadc10dc 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_localhost_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..f7161931 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 'localhost' 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