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 <rafael.olive...@venturus.org.br> List-Post: openvpn-devel@lists.sourceforge.net 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 <rafael.olive...@venturus.org.br> --- 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 <a...@rfc2549.org> 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 >