Reapplying client-ip NAT patch fixing the following issues raised by Arne
Schwabe:
- Fixing TABs and whitespaces;
- Added comments to the Client IP Marker.
Thanks
Rafael
--------
>From 6bc85f6ef89f27771c48e1e6d837302d5dad0910 Mon Sep 17 00:00:00 2001
From: vntraol <[email protected]>
List-Post: [email protected]
Date: Wed, 4 May 2016 13:48:36 -0300
Subject: [PATCH] Allow the user to use the string 'client-ip' on the
client-nat network configuration as a convenient way to use
the leased IP address received from the OpenVPN server.
Usage example:
client-nat snat client-ip 255.255.255.255 172.20.1.15 # replaces the
'client-ip' string with the leased IP address received from the OpenVPN
server
Signed-off-by: vntraol <[email protected]>
---
src/openvpn/clinat.c | 168
++++++++++++++++++++++++++++++-------------------
src/openvpn/clinat.h | 24 ++++---
src/openvpn/init.c | 2 +
src/openvpn/options.c | 1 +
4 files changed, 124 insertions(+), 71 deletions(-)
mode change 100644 => 100755 src/openvpn/clinat.c
mode change 100644 => 100755 src/openvpn/clinat.h
mode change 100644 => 100755 src/openvpn/init.c
mode change 100644 => 100755 src/openvpn/options.c
diff --git a/src/openvpn/clinat.c b/src/openvpn/clinat.c
old mode 100644
new mode 100755
index ddefe12..b03dbf6
--- a/src/openvpn/clinat.c
+++ b/src/openvpn/clinat.c
@@ -37,7 +37,7 @@
static bool
add_entry(struct client_nat_option_list *dest,
- const struct client_nat_entry *e)
+ const struct client_nat_entry *e)
{
if (dest->n >= MAX_CLIENT_NAT)
{
@@ -61,15 +61,15 @@ print_client_nat_list(const struct
client_nat_option_list *list, int msglevel)
if (list)
{
for (i = 0; i < list->n; ++i)
- {
- const struct client_nat_entry *e = &list->entries[i];
- msg (msglevel, " CNAT[%d] t=%d %s/%s/%s",
- i,
- e->type,
- print_in_addr_t (e->network, IA_NET_ORDER, &gc),
- print_in_addr_t (e->netmask, IA_NET_ORDER, &gc),
- print_in_addr_t (e->foreign_network, IA_NET_ORDER, &gc));
- }
+ {
+ const struct client_nat_entry *e = &list->entries[i];
+ msg (msglevel, " CNAT[%d] t=%d %s/%s/%s",
+ i,
+ e->type,
+ print_in_addr_t (e->network, IA_NET_ORDER, &gc),
+ print_in_addr_t (e->netmask, IA_NET_ORDER, &gc),
+ print_in_addr_t (e->foreign_network, IA_NET_ORDER, &gc));
+ }
}
gc_free (&gc);
}
@@ -93,23 +93,23 @@ clone_client_nat_option_list (const struct
client_nat_option_list *src, struct g
void
copy_client_nat_option_list (struct client_nat_option_list *dest,
- const struct client_nat_option_list *src)
+ const struct client_nat_option_list *src)
{
int i;
for (i = 0; i < src->n; ++i)
{
if (!add_entry(dest, &src->entries[i]))
- break;
+ break;
}
}
void
add_client_nat_to_option_list (struct client_nat_option_list *dest,
- const char *type,
- const char *network,
- const char *netmask,
- const char *foreign_network,
- int msglevel)
+ const char *type,
+ const char *network,
+ const char *netmask,
+ const char *foreign_network,
+ int msglevel)
{
struct client_nat_entry e;
bool ok;
@@ -124,12 +124,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, "client-ip"))
{
- msg(msglevel, "client-nat: bad network: %s", network);
- return;
+ // To be replaced later on with the leased IP Address received from
Openvpn Server.
+ e.network = CLIENT_IP_MARKER;
+ }
+ 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)
{
@@ -184,8 +193,8 @@ print_pkt (struct openvpn_iphdr *iph, const char
*prefix, const int direction, c
void
client_nat_transform (const struct client_nat_option_list *list,
- struct buffer *ipbuf,
- const int direction)
+ struct buffer *ipbuf,
+ const int direction)
{
struct ip_tcp_udp_hdr *h = (struct ip_tcp_udp_hdr *) BPTR (ipbuf);
int i;
@@ -202,64 +211,95 @@ client_nat_transform (const struct
client_nat_option_list *list,
{
const struct client_nat_entry *e = &list->entries[i]; /* current NAT
rule */
if (e->type ^ direction)
- {
- addr = *(addr_ptr = &h->ip.daddr);
- amask = 2;
- }
+ {
+ addr = *(addr_ptr = &h->ip.daddr);
+ amask = 2;
+ }
else
- {
- addr = *(addr_ptr = &h->ip.saddr);
- amask = 1;
- }
+ {
+ addr = *(addr_ptr = &h->ip.saddr);
+ amask = 1;
+ }
if (direction)
- {
- from = &e->foreign_network;
- to = &e->network;
- }
+ {
+ from = &e->foreign_network;
+ to = &e->network;
+ }
else
- {
- from = &e->network;
- to = &e->foreign_network;
- }
+ {
+ from = &e->network;
+ to = &e->foreign_network;
+ }
if (((addr & e->netmask) == *from) && !(amask & alog))
- {
- /* pre-adjust IP checksum */
- ADD_CHECKSUM_32(accumulate, addr);
+ {
+ /* pre-adjust IP checksum */
+ ADD_CHECKSUM_32(accumulate, addr);
- /* do NAT transform */
- addr = (addr & ~e->netmask) | *to;
+ /* do NAT transform */
+ addr = (addr & ~e->netmask) | *to;
- /* post-adjust IP checksum */
- SUB_CHECKSUM_32(accumulate, addr);
+ /* post-adjust IP checksum */
+ SUB_CHECKSUM_32(accumulate, addr);
- /* write the modified address to packet */
- *addr_ptr = addr;
+ /* write the modified address to packet */
+ *addr_ptr = addr;
- /* mark as modified */
- alog |= amask;
- }
+ /* mark as modified */
+ alog |= amask;
+ }
}
if (alog)
{
if (check_debug_level (D_CLIENT_NAT))
- print_pkt (&h->ip, "AFTER", direction, D_CLIENT_NAT);
+ print_pkt (&h->ip, "AFTER", direction, D_CLIENT_NAT);
ADJUST_CHECKSUM(accumulate, h->ip.check);
if (h->ip.protocol == OPENVPN_IPPROTO_TCP)
- {
- if (BLEN(ipbuf) >= sizeof(struct openvpn_iphdr) + sizeof(struct
openvpn_tcphdr))
- {
- ADJUST_CHECKSUM(accumulate, h->u.tcp.check);
- }
- }
+ {
+ if (BLEN(ipbuf) >= sizeof(struct openvpn_iphdr) + sizeof(struct
openvpn_tcphdr))
+ {
+ ADJUST_CHECKSUM(accumulate, h->u.tcp.check);
+ }
+ }
else if (h->ip.protocol == OPENVPN_IPPROTO_UDP)
- {
- if (BLEN(ipbuf) >= sizeof(struct openvpn_iphdr) + sizeof(struct
openvpn_udphdr))
- {
- ADJUST_CHECKSUM(accumulate, h->u.udp.check);
- }
- }
+ {
+ if (BLEN(ipbuf) >= sizeof(struct openvpn_iphdr) + sizeof(struct
openvpn_udphdr))
+ {
+ ADJUST_CHECKSUM(accumulate, h->u.udp.check);
+ }
+ }
}
}
+
+/*
+* Replaces the CLIENT_IP_MARKER with the leased IP address 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 == CLIENT_IP_MARKER)
+ {
+ 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 client-ip to: %s",
dot_ip);
+ ret = true;
+ }
+ }
+
+ return ret;
+}
diff --git a/src/openvpn/clinat.h b/src/openvpn/clinat.h
old mode 100644
new mode 100755
index a5779e1..8c84005
--- a/src/openvpn/clinat.h
+++ b/src/openvpn/clinat.h
@@ -32,6 +32,11 @@
#define CN_OUTGOING 0
#define CN_INCOMING 1
+/*
+ Used as a marker to replace with the leased IP address received from
OpenVPN server.
+*/
+#define CLIENT_IP_MARKER 0xFFFFFFFF
+
struct client_nat_entry {
# define CN_SNAT 0
# define CN_DNAT 1
@@ -52,14 +57,19 @@ void copy_client_nat_option_list (struct
client_nat_option_list *dest, const str
void print_client_nat_list(const struct client_nat_option_list *list, int
msglevel);
void add_client_nat_to_option_list (struct client_nat_option_list *dest,
- const char *type,
- const char *network,
- const char *netmask,
- const char *foreign_network,
- int msglevel);
+ const char *type,
+ const char *network,
+ const char *netmask,
+ const char *foreign_network,
+ int msglevel);
void client_nat_transform (const struct client_nat_option_list *list,
- struct buffer *ipbuf,
- const int direction);
+ struct buffer *ipbuf,
+ const int direction);
+
+/*
+* Replaces the CLIENT_IP_MARKER with the leased IP address received from
OpenVPN Server.
+*/
+bool update_client_ip_nat(struct client_nat_option_list *dest, in_addr_t
local_ip);
#endif
diff --git a/src/openvpn/init.c b/src/openvpn/init.c
old mode 100644
new mode 100755
index 42baf97..8359b29
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -1526,6 +1526,8 @@ do_open_tun (struct context *c)
c->c1.tuntap->post_open_mtu,
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
old mode 100644
new mode 100755
index 764ca74..e81d525
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -223,6 +223,7 @@ static const char usage_message[] =
"--redirect-private [flags]: Like --redirect-gateway, but omit actually
changing\n"
" the default gateway. Useful when pushing private
subnets.\n"
"--client-nat snat|dnat network netmask alias : on client add 1-to-1 NAT
rule.\n"
+ " Set the network parameter to 'client-ip' to use the
received ip from OpenVPN Server.\n"
#ifdef ENABLE_PUSH_PEER_INFO
"--push-peer-info : (client only) push client info to server.\n"
#endif
--
1.7.9.5
On Thu, Apr 28, 2016 at 1:20 PM, Arne Schwabe <[email protected]> wrote:
> Am 28.04.16 um 04:01 schrieb Rafael Gava:
> > Hi Arne,
> >
> > what a surprise I thought that the NAT patch had been dropped. :-)
>
> More or less forgotten. IIrc the active FTP part was controversal. This
> part is okay.
>
> > So, please, should I change the code based on your comments and resend
> > the patch?
>
> Yes, please.
>
> Arne
>