mirror of
https://github.com/OpenVPN/openvpn.git
synced 2024-09-20 03:52:28 +02:00
Added "client-nat" option for stateless, one-to-one
NAT on the client side. Version 2.1.3i. git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@6944 e7ae566f-a301-0410-adde-c780ea21d3b5
This commit is contained in:
parent
7ae5fb20d7
commit
581bef8708
@ -78,7 +78,9 @@ openvpn_SOURCES = \
|
||||
basic.h \
|
||||
buffer.c buffer.h \
|
||||
circ_list.h \
|
||||
clinat.c clinat.h \
|
||||
common.h \
|
||||
config-win32.h \
|
||||
crypto.c crypto.h \
|
||||
dhcp.c dhcp.h \
|
||||
errlevel.h \
|
||||
|
263
clinat.c
Normal file
263
clinat.c
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* OpenVPN -- An application to securely tunnel IP networks
|
||||
* over a single TCP/UDP port, with support for SSL/TLS-based
|
||||
* session authentication and key exchange,
|
||||
* packet encryption, packet authentication, and
|
||||
* packet compression.
|
||||
*
|
||||
* Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program (see the file COPYING included with this
|
||||
* distribution); if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "syshead.h"
|
||||
|
||||
#if defined(ENABLE_CLIENT_NAT)
|
||||
|
||||
#include "clinat.h"
|
||||
#include "proto.h"
|
||||
#include "socket.h"
|
||||
#include "memdbg.h"
|
||||
|
||||
static bool
|
||||
add_entry(struct client_nat_option_list *dest,
|
||||
const struct client_nat_entry *e)
|
||||
{
|
||||
if (dest->n >= MAX_CLIENT_NAT)
|
||||
{
|
||||
msg (M_WARN, "WARNING: client-nat table overflow (max %d entries)", MAX_CLIENT_NAT);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest->entries[dest->n++] = *e;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_client_nat_list(const struct client_nat_option_list *list, int msglevel)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
int i;
|
||||
|
||||
msg (msglevel, "*** CNAT list");
|
||||
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));
|
||||
}
|
||||
}
|
||||
gc_free (&gc);
|
||||
}
|
||||
|
||||
struct client_nat_option_list *
|
||||
new_client_nat_list (struct gc_arena *gc)
|
||||
{
|
||||
struct client_nat_option_list *ret;
|
||||
ALLOC_OBJ_CLEAR_GC (ret, struct client_nat_option_list, gc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct client_nat_option_list *
|
||||
clone_client_nat_option_list (const struct client_nat_option_list *src, struct gc_arena *gc)
|
||||
{
|
||||
struct client_nat_option_list *ret;
|
||||
ALLOC_OBJ_GC (ret, struct client_nat_option_list, gc);
|
||||
*ret = *src;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
copy_client_nat_option_list (struct client_nat_option_list *dest,
|
||||
const struct client_nat_option_list *src)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < src->n; ++i)
|
||||
{
|
||||
if (!add_entry(dest, &src->entries[i]))
|
||||
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)
|
||||
{
|
||||
struct client_nat_entry e;
|
||||
bool ok;
|
||||
|
||||
if (!strcmp(type, "snat"))
|
||||
e.type = CN_SNAT;
|
||||
else if (!strcmp(type, "dnat"))
|
||||
e.type = CN_DNAT;
|
||||
else
|
||||
{
|
||||
msg(msglevel, "client-nat: type must be 'snat' or 'dnat'");
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
msg(msglevel, "client-nat: bad netmask: %s", netmask);
|
||||
return;
|
||||
}
|
||||
e.foreign_network = getaddr(0, foreign_network, 0, &ok, NULL);
|
||||
if (!ok)
|
||||
{
|
||||
msg(msglevel, "client-nat: bad foreign network: %s", foreign_network);
|
||||
return;
|
||||
}
|
||||
|
||||
add_entry(dest, &e);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
print_checksum (struct openvpn_iphdr *iph, const char *prefix)
|
||||
{
|
||||
uint16_t *sptr;
|
||||
unsigned int sum = 0;
|
||||
int i = 0;
|
||||
for (sptr = (uint16_t *)iph; (uint8_t *)sptr < (uint8_t *)iph + sizeof(struct openvpn_iphdr); sptr++)
|
||||
{
|
||||
i += 1;
|
||||
sum += *sptr;
|
||||
}
|
||||
msg (M_INFO, "** CKSUM[%d] %s %08x", i, prefix, sum);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
print_pkt (struct openvpn_iphdr *iph, const char *prefix, const int direction, const int msglevel)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
|
||||
char *dirstr = "???";
|
||||
if (direction == CN_OUTGOING)
|
||||
dirstr = "OUT";
|
||||
else if (direction == CN_INCOMING)
|
||||
dirstr = "IN";
|
||||
|
||||
msg(msglevel, "** CNAT %s %s %s -> %s",
|
||||
dirstr,
|
||||
prefix,
|
||||
print_in_addr_t (iph->saddr, IA_NET_ORDER, &gc),
|
||||
print_in_addr_t (iph->daddr, IA_NET_ORDER, &gc));
|
||||
|
||||
gc_free (&gc);
|
||||
}
|
||||
|
||||
void
|
||||
client_nat_transform (const struct client_nat_option_list *list,
|
||||
struct buffer *ipbuf,
|
||||
const int direction)
|
||||
{
|
||||
struct ip_tcp_udp_hdr *h = (struct ip_tcp_udp_hdr *) BPTR (ipbuf);
|
||||
int i;
|
||||
uint32_t addr, *addr_ptr;
|
||||
const uint32_t *from, *to;
|
||||
int accumulate = 0;
|
||||
unsigned int amask;
|
||||
unsigned int alog = 0;
|
||||
|
||||
if (check_debug_level (D_CLIENT_NAT))
|
||||
print_pkt (&h->ip, "BEFORE", direction, D_CLIENT_NAT);
|
||||
|
||||
for (i = 0; i < list->n; ++i)
|
||||
{
|
||||
const struct client_nat_entry *e = &list->entries[i]; /* current NAT rule */
|
||||
if (e->type ^ direction)
|
||||
{
|
||||
addr = *(addr_ptr = &h->ip.daddr);
|
||||
amask = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = *(addr_ptr = &h->ip.saddr);
|
||||
amask = 1;
|
||||
}
|
||||
if (direction)
|
||||
{
|
||||
from = &e->foreign_network;
|
||||
to = &e->network;
|
||||
}
|
||||
else
|
||||
{
|
||||
from = &e->network;
|
||||
to = &e->foreign_network;
|
||||
}
|
||||
|
||||
if (((addr & e->netmask) == *from) && !(amask & alog))
|
||||
{
|
||||
/* pre-adjust IP checksum */
|
||||
ADD_CHECKSUM_32(accumulate, addr);
|
||||
|
||||
/* do NAT transform */
|
||||
addr = (addr & ~e->netmask) | *to;
|
||||
|
||||
/* post-adjust IP checksum */
|
||||
SUB_CHECKSUM_32(accumulate, addr);
|
||||
|
||||
/* write the modified address to packet */
|
||||
*addr_ptr = addr;
|
||||
|
||||
/* mark as modified */
|
||||
alog |= amask;
|
||||
}
|
||||
}
|
||||
if (alog)
|
||||
{
|
||||
if (check_debug_level (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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
65
clinat.h
Normal file
65
clinat.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* OpenVPN -- An application to securely tunnel IP networks
|
||||
* over a single TCP/UDP port, with support for SSL/TLS-based
|
||||
* session authentication and key exchange,
|
||||
* packet encryption, packet authentication, and
|
||||
* packet compression.
|
||||
*
|
||||
* Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program (see the file COPYING included with this
|
||||
* distribution); if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if !defined(CLINAT_H) && defined(ENABLE_CLIENT_NAT)
|
||||
#define CLINAT_H
|
||||
|
||||
#include "buffer.h"
|
||||
|
||||
#define MAX_CLIENT_NAT 64
|
||||
|
||||
#define CN_OUTGOING 0
|
||||
#define CN_INCOMING 1
|
||||
|
||||
struct client_nat_entry {
|
||||
# define CN_SNAT 0
|
||||
# define CN_DNAT 1
|
||||
int type;
|
||||
in_addr_t network;
|
||||
in_addr_t netmask;
|
||||
in_addr_t foreign_network;
|
||||
};
|
||||
|
||||
struct client_nat_option_list {
|
||||
int n;
|
||||
struct client_nat_entry entries[MAX_CLIENT_NAT];
|
||||
};
|
||||
|
||||
struct client_nat_option_list *new_client_nat_list (struct gc_arena *gc);
|
||||
struct client_nat_option_list *clone_client_nat_option_list (const struct client_nat_option_list *src, struct gc_arena *gc);
|
||||
void copy_client_nat_option_list (struct client_nat_option_list *dest, const struct client_nat_option_list *src);
|
||||
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);
|
||||
|
||||
void client_nat_transform (const struct client_nat_option_list *list,
|
||||
struct buffer *ipbuf,
|
||||
const int direction);
|
||||
|
||||
#endif
|
@ -111,6 +111,7 @@
|
||||
#define D_LINK_RW LOGLEV(6, 60, M_DEBUG) /* show TCP/UDP reads/writes (terse) */
|
||||
#define D_TUN_RW LOGLEV(6, 60, M_DEBUG) /* show TUN/TAP reads/writes */
|
||||
#define D_TAP_WIN32_DEBUG LOGLEV(6, 60, M_DEBUG) /* show TAP-Win32 driver debug info */
|
||||
#define D_CLIENT_NAT LOGLEV(6, 60, M_DEBUG) /* show client NAT debug info */
|
||||
|
||||
#define D_SHOW_KEYS LOGLEV(7, 70, M_DEBUG) /* show data channel encryption keys */
|
||||
#define D_SHOW_KEY_SOURCE LOGLEV(7, 70, M_DEBUG) /* show data channel key source entropy */
|
||||
|
12
forward.c
12
forward.c
@ -977,7 +977,7 @@ process_incoming_tun (struct context *c)
|
||||
* The --passtos and --mssfix options require
|
||||
* us to examine the IPv4 header.
|
||||
*/
|
||||
process_ipv4_header (c, PIPV4_PASSTOS|PIPV4_MSSFIX, &c->c2.buf);
|
||||
process_ipv4_header (c, PIPV4_PASSTOS|PIPV4_MSSFIX|PIPV4_CLIENT_NAT, &c->c2.buf);
|
||||
|
||||
#ifdef PACKET_TRUNCATION_CHECK
|
||||
/* if (c->c2.buf.len > 1) --c->c2.buf.len; */
|
||||
@ -1035,6 +1035,14 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
|
||||
if (flags & PIPV4_MSSFIX)
|
||||
mss_fixup (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame)));
|
||||
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
/* possibly do NAT on packet */
|
||||
if ((flags & PIPV4_CLIENT_NAT) && c->options.client_nat)
|
||||
{
|
||||
const int direction = (flags & PIPV4_OUTGOING) ? CN_INCOMING : CN_OUTGOING;
|
||||
client_nat_transform (c->options.client_nat, &ipbuf, direction);
|
||||
}
|
||||
#endif
|
||||
/* possibly extract a DHCP router message */
|
||||
if (flags & PIPV4_EXTRACT_DHCP_ROUTER)
|
||||
{
|
||||
@ -1196,7 +1204,7 @@ process_outgoing_tun (struct context *c)
|
||||
* The --mssfix option requires
|
||||
* us to examine the IPv4 header.
|
||||
*/
|
||||
process_ipv4_header (c, PIPV4_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_OUTGOING, &c->c2.to_tun);
|
||||
process_ipv4_header (c, PIPV4_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_CLIENT_NAT|PIPV4_OUTGOING, &c->c2.to_tun);
|
||||
|
||||
if (c->c2.to_tun.len <= MAX_RW_SIZE_TUN (&c->c2.frame))
|
||||
{
|
||||
|
@ -76,6 +76,7 @@ bool send_control_channel_string (struct context *c, const char *str, int msglev
|
||||
#define PIPV4_MSSFIX (1<<1)
|
||||
#define PIPV4_OUTGOING (1<<2)
|
||||
#define PIPV4_EXTRACT_DHCP_ROUTER (1<<3)
|
||||
#define PIPV4_CLIENT_NAT (1<<4)
|
||||
|
||||
void process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf);
|
||||
|
||||
|
3
multi.c
3
multi.c
@ -1200,6 +1200,9 @@ multi_select_virtual_addr (struct multi_context *m, struct multi_instance *mi)
|
||||
mi->context.c2.push_ifconfig_defined = true;
|
||||
mi->context.c2.push_ifconfig_local = mi->context.options.push_ifconfig_local;
|
||||
mi->context.c2.push_ifconfig_remote_netmask = mi->context.options.push_ifconfig_remote_netmask;
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
mi->context.c2.push_ifconfig_local_alias = mi->context.options.push_ifconfig_local_alias;
|
||||
#endif
|
||||
}
|
||||
else if (m->ifconfig_pool && mi->vaddr_handle < 0) /* otherwise, choose a pool address */
|
||||
{
|
||||
|
36
openvpn.8
36
openvpn.8
@ -1067,6 +1067,31 @@ and
|
||||
.B --route-gateway.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B --client-nat snat|dnat network netmask alias
|
||||
This pushable client option sets up a stateless one-to-one NAT
|
||||
rule on packet addresses (not ports), and is useful in cases
|
||||
where routes or ifconfig settings pushed to the client would
|
||||
create an IP numbering conflict.
|
||||
|
||||
.B network/netmask
|
||||
(for example 192.168.0.0/255.255.0.0)
|
||||
defines the local view of a resource from the client perspective, while
|
||||
.B alias/netmask
|
||||
(for example 10.64.0.0/255.255.0.0)
|
||||
defines the remote view from the server perspective.
|
||||
|
||||
Use
|
||||
.B snat
|
||||
(source NAT) for resources owned by the client and
|
||||
.B dnat
|
||||
(destination NAT) for remote resources.
|
||||
|
||||
Set
|
||||
.B --verb 6
|
||||
for debugging info showing the transformation of src/dest
|
||||
addresses in packets.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B --redirect-gateway flags...
|
||||
(Experimental) Automatically execute routing commands to cause all outgoing IP traffic
|
||||
to be redirected over the VPN.
|
||||
@ -2706,7 +2731,7 @@ This option is deprecated, and should be replaced with
|
||||
which is functionally equivalent.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B --ifconfig-push local remote-netmask
|
||||
.B --ifconfig-push local remote-netmask [alias]
|
||||
Push virtual IP endpoints for client tunnel,
|
||||
overriding the --ifconfig-pool dynamic allocation.
|
||||
|
||||
@ -2725,6 +2750,15 @@ are from the perspective of the client, not the server. They may be
|
||||
DNS names rather than IP addresses, in which case they will be resolved
|
||||
on the server at the time of client connection.
|
||||
|
||||
The optional
|
||||
.B alias
|
||||
parameter may be used in cases where NAT causes the client view
|
||||
of its local endpoint to differ from the server view. In this case
|
||||
.B local/remote-netmask
|
||||
will refer to the server view while
|
||||
.B alias/remote-netmask
|
||||
will refer to the client view.
|
||||
|
||||
This option must be associated with a specific client instance,
|
||||
which means that it must be specified either in a client
|
||||
instance config file using
|
||||
|
@ -416,6 +416,9 @@ struct context_2
|
||||
bool push_ifconfig_defined;
|
||||
in_addr_t push_ifconfig_local;
|
||||
in_addr_t push_ifconfig_remote_netmask;
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
in_addr_t push_ifconfig_local_alias;
|
||||
#endif
|
||||
|
||||
/* client authentication state, CAS_SUCCEEDED must be 0 */
|
||||
# define CAS_SUCCEEDED 0
|
||||
|
49
options.c
49
options.c
@ -198,6 +198,9 @@ static const char usage_message[] =
|
||||
" Add 'bypass-dns' flag to similarly bypass tunnel for DNS.\n"
|
||||
"--redirect-private [flags]: Like --redirect-gateway, but omit actually changing\n"
|
||||
" the default gateway. Useful when pushing private subnets.\n"
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
"--client-nat snat|dnat network netmask alias : on client add 1-to-1 NAT rule.\n"
|
||||
#endif
|
||||
#ifdef ENABLE_PUSH_PEER_INFO
|
||||
"--push-peer-info : (client only) push client info to server.\n"
|
||||
#endif
|
||||
@ -1086,6 +1089,9 @@ options_detach (struct options *o)
|
||||
{
|
||||
gc_detach (&o->gc);
|
||||
o->routes = NULL;
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
o->client_nat = NULL;
|
||||
#endif
|
||||
#if P2MP_SERVER
|
||||
clone_push_list(o);
|
||||
#endif
|
||||
@ -1098,6 +1104,15 @@ rol_check_alloc (struct options *options)
|
||||
options->routes = new_route_option_list (options->max_routes, &options->gc);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
static void
|
||||
cnol_check_alloc (struct options *options)
|
||||
{
|
||||
if (!options->client_nat)
|
||||
options->client_nat = new_client_nat_list (&options->gc);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_DEBUG
|
||||
static void
|
||||
show_connection_entry (const struct connection_entry *o)
|
||||
@ -1288,6 +1303,11 @@ show_settings (const struct options *o)
|
||||
SHOW_BOOL (allow_pull_fqdn);
|
||||
if (o->routes)
|
||||
print_route_options (o->routes, D_SHOW_PARMS);
|
||||
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
if (o->client_nat)
|
||||
print_client_nat_list(o->client_nat, D_SHOW_PARMS);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MANAGEMENT
|
||||
SHOW_STR (management_addr);
|
||||
@ -2337,6 +2357,13 @@ pre_pull_save (struct options *o)
|
||||
o->pre_pull->routes = clone_route_option_list(o->routes, &o->gc);
|
||||
o->pre_pull->routes_defined = true;
|
||||
}
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
if (o->client_nat)
|
||||
{
|
||||
o->pre_pull->client_nat = clone_client_nat_option_list(o->client_nat, &o->gc);
|
||||
o->pre_pull->client_nat_defined = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -2358,6 +2385,16 @@ pre_pull_restore (struct options *o)
|
||||
else
|
||||
o->routes = NULL;
|
||||
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
if (pp->client_nat_defined)
|
||||
{
|
||||
cnol_check_alloc (o);
|
||||
copy_client_nat_option_list (o->client_nat, pp->client_nat);
|
||||
}
|
||||
else
|
||||
o->client_nat = NULL;
|
||||
#endif
|
||||
|
||||
o->foreign_option_index = pp->foreign_option_index;
|
||||
}
|
||||
|
||||
@ -4564,6 +4601,14 @@ add_option (struct options *options,
|
||||
VERIFY_PERMISSION (OPT_P_PERSIST_IP);
|
||||
options->persist_remote_ip = true;
|
||||
}
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
else if (streq (p[0], "client-nat") && p[1] && p[2] && p[3] && p[4])
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_ROUTE);
|
||||
cnol_check_alloc (options);
|
||||
add_client_nat_to_option_list(options->client_nat, p[1], p[2], p[3], p[4], msglevel);
|
||||
}
|
||||
#endif
|
||||
else if (streq (p[0], "route") && p[1])
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_ROUTE);
|
||||
@ -5085,6 +5130,10 @@ add_option (struct options *options,
|
||||
options->push_ifconfig_defined = true;
|
||||
options->push_ifconfig_local = local;
|
||||
options->push_ifconfig_remote_netmask = remote_netmask;
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
if (p[3])
|
||||
options->push_ifconfig_local_alias = getaddr (GETADDR_HOST_ORDER|GETADDR_RESOLVE, p[3], 0, NULL, NULL);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
13
options.h
13
options.h
@ -41,6 +41,7 @@
|
||||
#include "proxy.h"
|
||||
#include "lzo.h"
|
||||
#include "pushlist.h"
|
||||
#include "clinat.h"
|
||||
|
||||
/*
|
||||
* Maximum number of parameters associated with an option,
|
||||
@ -67,6 +68,11 @@ struct options_pre_pull
|
||||
bool routes_defined;
|
||||
struct route_option_list *routes;
|
||||
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
bool client_nat_defined;
|
||||
struct client_nat_option_list *client_nat;
|
||||
#endif
|
||||
|
||||
int foreign_option_index;
|
||||
};
|
||||
|
||||
@ -329,6 +335,10 @@ struct options
|
||||
bool route_gateway_via_dhcp;
|
||||
bool allow_pull_fqdn; /* as a client, allow server to push a FQDN for certain parameters */
|
||||
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
struct client_nat_option_list *client_nat;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_OCC
|
||||
/* Enable options consistency check between peers */
|
||||
bool occ;
|
||||
@ -401,6 +411,9 @@ struct options
|
||||
bool push_ifconfig_defined;
|
||||
in_addr_t push_ifconfig_local;
|
||||
in_addr_t push_ifconfig_remote_netmask;
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
in_addr_t push_ifconfig_local_alias;
|
||||
#endif
|
||||
bool push_ifconfig_constraint_defined;
|
||||
in_addr_t push_ifconfig_constraint_network;
|
||||
in_addr_t push_ifconfig_constraint_netmask;
|
||||
|
37
proto.h
37
proto.h
@ -149,6 +149,14 @@ struct openvpn_tcphdr {
|
||||
#define OPENVPN_TCPOPT_MAXSEG 2
|
||||
#define OPENVPN_TCPOLEN_MAXSEG 4
|
||||
|
||||
struct ip_tcp_udp_hdr {
|
||||
struct openvpn_iphdr ip;
|
||||
union {
|
||||
struct openvpn_tcphdr tcp;
|
||||
struct openvpn_udphdr udp;
|
||||
} u;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
/*
|
||||
@ -160,19 +168,30 @@ struct openvpn_tcphdr {
|
||||
* is the checksum value to be updated.
|
||||
*/
|
||||
#define ADJUST_CHECKSUM(acc, cksum) { \
|
||||
(acc) += (cksum); \
|
||||
if ((acc) < 0) { \
|
||||
(acc) = -(acc); \
|
||||
(acc) = ((acc) >> 16) + ((acc) & 0xffff); \
|
||||
(acc) += (acc) >> 16; \
|
||||
(cksum) = (uint16_t) ~(acc); \
|
||||
int _acc = acc; \
|
||||
_acc += (cksum); \
|
||||
if (_acc < 0) { \
|
||||
_acc = -_acc; \
|
||||
_acc = (_acc >> 16) + (_acc & 0xffff); \
|
||||
_acc += _acc >> 16; \
|
||||
(cksum) = (uint16_t) ~_acc; \
|
||||
} else { \
|
||||
(acc) = ((acc) >> 16) + ((acc) & 0xffff); \
|
||||
(acc) += (acc) >> 16; \
|
||||
(cksum) = (uint16_t) (acc); \
|
||||
_acc = (_acc >> 16) + (_acc & 0xffff); \
|
||||
_acc += _acc >> 16; \
|
||||
(cksum) = (uint16_t) _acc; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ADD_CHECKSUM_32(acc, u32) { \
|
||||
acc += (u32) & 0xffff; \
|
||||
acc += (u32) >> 16; \
|
||||
}
|
||||
|
||||
#define SUB_CHECKSUM_32(acc, u32) { \
|
||||
acc -= (u32) & 0xffff; \
|
||||
acc -= (u32) >> 16; \
|
||||
}
|
||||
|
||||
/*
|
||||
* We are in a "liberal" position with respect to MSS,
|
||||
* i.e. we assume that MSS can be calculated from MTU
|
||||
|
15
push.c
15
push.c
@ -185,7 +185,7 @@ send_push_reply (struct context *c)
|
||||
struct push_entry *e = c->options.push_list.head;
|
||||
bool multi_push = false;
|
||||
static char cmd[] = "PUSH_REPLY";
|
||||
const int extra = 64; /* extra space for possible trailing ifconfig and push-continuation */
|
||||
const int extra = 84; /* extra space for possible trailing ifconfig and push-continuation */
|
||||
const int safe_cap = BCAP (&buf) - extra;
|
||||
|
||||
buf_printf (&buf, cmd);
|
||||
@ -218,9 +218,16 @@ send_push_reply (struct context *c)
|
||||
}
|
||||
|
||||
if (c->c2.push_ifconfig_defined && c->c2.push_ifconfig_local && c->c2.push_ifconfig_remote_netmask)
|
||||
buf_printf (&buf, ",ifconfig %s %s",
|
||||
print_in_addr_t (c->c2.push_ifconfig_local, 0, &gc),
|
||||
print_in_addr_t (c->c2.push_ifconfig_remote_netmask, 0, &gc));
|
||||
{
|
||||
in_addr_t ifconfig_local = c->c2.push_ifconfig_local;
|
||||
#ifdef ENABLE_CLIENT_NAT
|
||||
if (c->c2.push_ifconfig_local_alias)
|
||||
ifconfig_local = c->c2.push_ifconfig_local_alias;
|
||||
#endif
|
||||
buf_printf (&buf, ",ifconfig %s %s",
|
||||
print_in_addr_t (ifconfig_local, 0, &gc),
|
||||
print_in_addr_t (c->c2.push_ifconfig_remote_netmask, 0, &gc));
|
||||
}
|
||||
if (multi_push)
|
||||
buf_printf (&buf, ",push-continuation 1");
|
||||
|
||||
|
@ -692,4 +692,9 @@ socket_defined (const socket_descriptor_t sd)
|
||||
*/
|
||||
#define ENABLE_PUSH_PEER_INFO
|
||||
|
||||
/*
|
||||
* Do we support internal client-side NAT?
|
||||
*/
|
||||
#define ENABLE_CLIENT_NAT
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
dnl define the OpenVPN version
|
||||
define(PRODUCT_VERSION,[2.1.3h])
|
||||
define(PRODUCT_VERSION,[2.1.3i])
|
||||
dnl define the TAP version
|
||||
define(PRODUCT_TAP_ID,[tap0901])
|
||||
define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])
|
||||
|
Loading…
Reference in New Issue
Block a user