mirror of
https://github.com/OpenVPN/openvpn.git
synced 2026-02-20 08:20:28 -05:00
Added redirect-gateway block-local flag, with support for
Linux, Mac OS X, and Linux. This flag (which is pushable from server) blocks client access to local LAN while VPN session is active. Added standalone --show-gateway option to show info about default gateway. Extensively refactored get_default_gateway function in route.c to ease implementation of block-local. Removed "Experimental" disclaimer from redirect-gateway man page. Version 2.1.3y. git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@7334 e7ae566f-a301-0410-adde-c780ea21d3b5
This commit is contained in:
parent
7598730340
commit
7fb0e07ec3
9 changed files with 825 additions and 609 deletions
|
|
@ -1015,7 +1015,7 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
|
|||
if (!c->options.passtos)
|
||||
flags &= ~PIPV4_PASSTOS;
|
||||
#endif
|
||||
if (!c->options.route_gateway_via_dhcp || !route_list_default_gateway_needed (c->c1.route_list))
|
||||
if (!c->options.route_gateway_via_dhcp || !route_list_vpn_gateway_needed (c->c1.route_list))
|
||||
flags &= ~PIPV4_EXTRACT_DHCP_ROUTER;
|
||||
|
||||
if (buf->len > 0)
|
||||
|
|
@ -1056,7 +1056,7 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
|
|||
{
|
||||
const in_addr_t dhcp_router = dhcp_extract_router_msg (&ipbuf);
|
||||
if (dhcp_router)
|
||||
route_list_add_default_gateway (c->c1.route_list, c->c2.es, dhcp_router);
|
||||
route_list_add_vpn_gateway (c->c1.route_list, c->c2.es, dhcp_router);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
20
init.c
20
init.c
|
|
@ -603,21 +603,9 @@ init_static (void)
|
|||
|
||||
#ifdef TEST_GET_DEFAULT_GATEWAY
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
in_addr_t addr;
|
||||
char macaddr[6];
|
||||
|
||||
if (get_default_gateway(&addr, NULL))
|
||||
msg (M_INFO, "GW %s", print_in_addr_t(addr, 0, &gc));
|
||||
else
|
||||
msg (M_INFO, "GDG ERROR");
|
||||
|
||||
if (get_default_gateway_mac_addr(macaddr))
|
||||
msg (M_INFO, "MAC %s", format_hex_ex (macaddr, 6, 0, 1, ":", &gc));
|
||||
else
|
||||
msg (M_INFO, "GDGMA ERROR");
|
||||
|
||||
gc_free (&gc);
|
||||
struct route_gateway_info rgi;
|
||||
get_default_gateway(&rgi);
|
||||
print_default_gateway(M_INFO, &rgi);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1201,7 +1189,7 @@ do_route (const struct options *options,
|
|||
if (!options->route_noexec && route_list)
|
||||
{
|
||||
add_routes (route_list, tt, ROUTE_OPTION_FLAGS (options), es);
|
||||
setenv_int (es, "redirect_gateway", route_list->did_redirect_default_gateway);
|
||||
setenv_int (es, "redirect_gateway", route_did_redirect_default_gateway(route_list));
|
||||
}
|
||||
#ifdef ENABLE_MANAGEMENT
|
||||
if (management)
|
||||
|
|
|
|||
16
openvpn.8
16
openvpn.8
|
|
@ -1093,8 +1093,8 @@ 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.
|
||||
Automatically execute routing commands to cause all outgoing IP traffic
|
||||
to be redirected over the VPN. This is a client-side option.
|
||||
|
||||
This option performs three steps:
|
||||
|
||||
|
|
@ -1126,13 +1126,18 @@ Option flags:
|
|||
.B local --
|
||||
Add the
|
||||
.B local
|
||||
flag if both OpenVPN servers are directly connected via a common subnet,
|
||||
flag if both OpenVPN nodes are directly connected via a common subnet,
|
||||
such as with wireless. The
|
||||
.B local
|
||||
flag will cause step
|
||||
.B 1
|
||||
above to be omitted.
|
||||
|
||||
.B autolocal --
|
||||
Try to automatically determine whether to enable
|
||||
.B local
|
||||
flag above.
|
||||
|
||||
.B def1 --
|
||||
Use this flag to override
|
||||
the default gateway by using 0.0.0.0/1 and 128.0.0.0/1
|
||||
|
|
@ -1151,7 +1156,10 @@ bypasses the tunnel
|
|||
(Available on Windows clients, may not be available
|
||||
on non-Windows clients).
|
||||
|
||||
Using the def1 flag is highly recommended.
|
||||
.B block-local --
|
||||
Block access to local LAN when the tunnel is active, except for
|
||||
the LAN gateway itself. This is accomplished by routing the local
|
||||
LAN (except for the LAN gateway address) into the tunnel.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B --link-mtu n
|
||||
|
|
|
|||
13
options.c
13
options.c
|
|
@ -670,6 +670,9 @@ static const char usage_message[] =
|
|||
"--show-pkcs11-ids provider [cert_private] : Show PKCS#11 available ids.\n"
|
||||
" --verb option can be added *BEFORE* this.\n"
|
||||
#endif /* ENABLE_PKCS11 */
|
||||
"\n"
|
||||
"General Standalone Options:\n"
|
||||
"--show-gateway : Show info about default gateway.\n"
|
||||
;
|
||||
|
||||
#endif /* !ENABLE_SMALL */
|
||||
|
|
@ -3611,6 +3614,14 @@ add_option (struct options *options,
|
|||
|
||||
read_config_file (options, p[1], level, file, line, msglevel, permission_mask, option_types_found, es);
|
||||
}
|
||||
else if (streq (p[0], "show-gateway"))
|
||||
{
|
||||
struct route_gateway_info rgi;
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
get_default_gateway(&rgi);
|
||||
print_default_gateway(M_INFO, &rgi);
|
||||
openvpn_exit (OPENVPN_EXIT_STATUS_GOOD); /* exit point */
|
||||
}
|
||||
#if 0
|
||||
else if (streq (p[0], "foreign-option") && p[1])
|
||||
{
|
||||
|
|
@ -4768,6 +4779,8 @@ add_option (struct options *options,
|
|||
options->routes->flags |= RG_BYPASS_DHCP;
|
||||
else if (streq (p[j], "bypass-dns"))
|
||||
options->routes->flags |= RG_BYPASS_DNS;
|
||||
else if (streq (p[j], "block-local"))
|
||||
options->routes->flags |= RG_BLOCK_LOCAL;
|
||||
else
|
||||
{
|
||||
msg (msglevel, "unknown --%s flag: %s", p[0], p[j]);
|
||||
|
|
|
|||
100
route.h
100
route.h
|
|
@ -29,6 +29,7 @@
|
|||
#ifndef ROUTE_H
|
||||
#define ROUTE_H
|
||||
|
||||
#include "basic.h"
|
||||
#include "tun.h"
|
||||
#include "misc.h"
|
||||
|
||||
|
|
@ -58,15 +59,17 @@ struct route_bypass
|
|||
|
||||
struct route_special_addr
|
||||
{
|
||||
/* bits indicating which members below are defined */
|
||||
# define RTSA_REMOTE_ENDPOINT (1<<0)
|
||||
# define RTSA_REMOTE_HOST (1<<1)
|
||||
# define RTSA_DEFAULT_METRIC (1<<2)
|
||||
unsigned int flags;
|
||||
|
||||
in_addr_t remote_endpoint;
|
||||
bool remote_endpoint_defined;
|
||||
in_addr_t net_gateway;
|
||||
bool net_gateway_defined;
|
||||
in_addr_t remote_host;
|
||||
bool remote_host_defined;
|
||||
int remote_host_local; /* TLA_x value */
|
||||
struct route_bypass bypass;
|
||||
int default_metric;
|
||||
bool default_metric_defined;
|
||||
};
|
||||
|
||||
struct route_option {
|
||||
|
|
@ -84,30 +87,68 @@ struct route_option {
|
|||
#define RG_BYPASS_DNS (1<<4)
|
||||
#define RG_REROUTE_GW (1<<5)
|
||||
#define RG_AUTO_LOCAL (1<<6)
|
||||
#define RG_BLOCK_LOCAL (1<<7)
|
||||
|
||||
struct route_option_list {
|
||||
unsigned int flags;
|
||||
unsigned int flags; /* RG_x flags */
|
||||
int capacity;
|
||||
int n;
|
||||
struct route_option routes[EMPTY_ARRAY_SIZE];
|
||||
};
|
||||
|
||||
struct route {
|
||||
bool defined;
|
||||
# define RT_DEFINED (1<<0)
|
||||
# define RT_ADDED (1<<1)
|
||||
# define RT_METRIC_DEFINED (1<<2)
|
||||
unsigned int flags;
|
||||
const struct route_option *option;
|
||||
in_addr_t network;
|
||||
in_addr_t netmask;
|
||||
in_addr_t gateway;
|
||||
bool metric_defined;
|
||||
int metric;
|
||||
};
|
||||
|
||||
struct route_list {
|
||||
bool routes_added;
|
||||
struct route_special_addr spec;
|
||||
struct route_gateway_address {
|
||||
in_addr_t addr;
|
||||
in_addr_t netmask;
|
||||
};
|
||||
|
||||
struct route_gateway_info {
|
||||
# define RGI_ADDR_DEFINED (1<<0) /* set if gateway.addr defined */
|
||||
# define RGI_NETMASK_DEFINED (1<<1) /* set if gateway.netmask defined */
|
||||
# define RGI_HWADDR_DEFINED (1<<2) /* set if hwaddr is defined */
|
||||
# define RGI_IFACE_DEFINED (1<<3) /* set if iface is defined */
|
||||
# define RGI_OVERFLOW (1<<4) /* set if more interface addresses than will fit in addrs */
|
||||
unsigned int flags;
|
||||
bool did_redirect_default_gateway;
|
||||
bool did_local;
|
||||
|
||||
/* gateway interface */
|
||||
# ifdef WIN32
|
||||
DWORD adapter_index; /* interface or ~0 if undefined */
|
||||
#else
|
||||
char iface[16]; /* interface name (null terminated), may be empty */
|
||||
#endif
|
||||
|
||||
/* gateway interface hardware address */
|
||||
uint8_t hwaddr[6];
|
||||
|
||||
/* gateway/router address */
|
||||
struct route_gateway_address gateway;
|
||||
|
||||
/* address/netmask pairs bound to interface */
|
||||
# define RGI_N_ADDRESSES 8
|
||||
int n_addrs; /* len of addrs, may be 0 */
|
||||
struct route_gateway_address addrs[RGI_N_ADDRESSES]; /* local addresses attached to iface */
|
||||
};
|
||||
|
||||
struct route_list {
|
||||
# define RL_DID_REDIRECT_DEFAULT_GATEWAY (1<<0)
|
||||
# define RL_DID_LOCAL (1<<1)
|
||||
# define RL_ROUTES_ADDED (1<<2)
|
||||
unsigned int iflags;
|
||||
|
||||
struct route_special_addr spec;
|
||||
struct route_gateway_info rgi;
|
||||
unsigned int flags; /* RG_x flags */
|
||||
int capacity;
|
||||
int n;
|
||||
struct route routes[EMPTY_ARRAY_SIZE];
|
||||
|
|
@ -128,7 +169,11 @@ void copy_route_option_list (struct route_option_list *dest, const struct route_
|
|||
|
||||
struct route_list *new_route_list (const int max_routes, struct gc_arena *a);
|
||||
|
||||
void add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
|
||||
void add_route (struct route *r,
|
||||
const struct tuntap *tt,
|
||||
unsigned int flags,
|
||||
const struct route_gateway_info *rgi,
|
||||
const struct env_set *es);
|
||||
|
||||
void add_route_to_option_list (struct route_option_list *l,
|
||||
const char *network,
|
||||
|
|
@ -143,9 +188,9 @@ bool init_route_list (struct route_list *rl,
|
|||
in_addr_t remote_host,
|
||||
struct env_set *es);
|
||||
|
||||
void route_list_add_default_gateway (struct route_list *rl,
|
||||
struct env_set *es,
|
||||
const in_addr_t addr);
|
||||
void route_list_add_vpn_gateway (struct route_list *rl,
|
||||
struct env_set *es,
|
||||
const in_addr_t addr);
|
||||
|
||||
void add_routes (struct route_list *rl,
|
||||
const struct tuntap *tt,
|
||||
|
|
@ -161,7 +206,8 @@ void setenv_routes (struct env_set *es, const struct route_list *rl);
|
|||
|
||||
bool is_special_addr (const char *addr_str);
|
||||
|
||||
bool get_default_gateway (in_addr_t *ip, in_addr_t *netmask);
|
||||
void get_default_gateway (struct route_gateway_info *rgi);
|
||||
void print_default_gateway(const int msglevel, const struct route_gateway_info *rgi);
|
||||
|
||||
/*
|
||||
* Test if addr is reachable via a local interface (return ILA_LOCAL),
|
||||
|
|
@ -172,11 +218,7 @@ bool get_default_gateway (in_addr_t *ip, in_addr_t *netmask);
|
|||
#define TLA_NOT_IMPLEMENTED 0
|
||||
#define TLA_NONLOCAL 1
|
||||
#define TLA_LOCAL 2
|
||||
int test_local_addr (const in_addr_t addr);
|
||||
|
||||
#if AUTO_USERID || defined(ENABLE_PUSH_PEER_INFO)
|
||||
bool get_default_gateway_mac_addr (unsigned char *macaddr);
|
||||
#endif
|
||||
int test_local_addr (const in_addr_t addr, const struct route_gateway_info *rgi);
|
||||
|
||||
#ifdef ENABLE_DEBUG
|
||||
void print_route_options (const struct route_option_list *rol,
|
||||
|
|
@ -189,7 +231,7 @@ void print_routes (const struct route_list *rl, int level);
|
|||
|
||||
void show_routes (int msglev);
|
||||
bool test_routes (const struct route_list *rl, const struct tuntap *tt);
|
||||
bool add_route_ipapi (const struct route *r, const struct tuntap *tt);
|
||||
bool add_route_ipapi (const struct route *r, const struct tuntap *tt, DWORD adapter_index);
|
||||
bool del_route_ipapi (const struct route *r, const struct tuntap *tt);
|
||||
|
||||
#else
|
||||
|
|
@ -209,12 +251,18 @@ netbits_to_netmask (const int netbits)
|
|||
}
|
||||
|
||||
static inline bool
|
||||
route_list_default_gateway_needed (const struct route_list *rl)
|
||||
route_list_vpn_gateway_needed (const struct route_list *rl)
|
||||
{
|
||||
if (!rl)
|
||||
return false;
|
||||
else
|
||||
return !rl->spec.remote_endpoint_defined;
|
||||
return !(rl->spec.flags & RTSA_REMOTE_ENDPOINT);
|
||||
}
|
||||
|
||||
static inline int
|
||||
route_did_redirect_default_gateway(const struct route_list *rl)
|
||||
{
|
||||
return BOOL_CAST(rl->iflags & RL_DID_REDIRECT_DEFAULT_GATEWAY);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
9
ssl.c
9
ssl.c
|
|
@ -49,6 +49,7 @@
|
|||
#include "pkcs11.h"
|
||||
#include "list.h"
|
||||
#include "base64.h"
|
||||
#include "route.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include "cryptoapi.h"
|
||||
|
|
@ -3899,10 +3900,10 @@ push_peer_info(struct buffer *buf, struct tls_session *session)
|
|||
|
||||
/* push mac addr */
|
||||
{
|
||||
bool get_default_gateway_mac_addr (unsigned char *macaddr);
|
||||
uint8_t macaddr[6];
|
||||
get_default_gateway_mac_addr (macaddr);
|
||||
buf_printf (&out, "IV_HWADDR=%s\n", format_hex_ex (macaddr, 6, 0, 1, ":", &gc));
|
||||
struct route_gateway_info rgi;
|
||||
get_default_gateway (&rgi);
|
||||
if (rgi.flags & RGI_HWADDR_DEFINED)
|
||||
buf_printf (&out, "IV_HWADDR=%s\n", format_hex_ex (rgi.hwaddr, 6, 0, 1, ":", &gc));
|
||||
}
|
||||
|
||||
/* push LZO status */
|
||||
|
|
|
|||
17
tun.c
17
tun.c
|
|
@ -270,11 +270,12 @@ check_subnet_conflict (const in_addr_t ip,
|
|||
const in_addr_t netmask,
|
||||
const char *prefix)
|
||||
{
|
||||
#if 0 /* too many false positives */
|
||||
struct gc_arena gc = gc_new ();
|
||||
in_addr_t lan_gw = 0;
|
||||
in_addr_t lan_netmask = 0;
|
||||
|
||||
if (get_default_gateway (&lan_gw, &lan_netmask))
|
||||
if (get_default_gateway (&lan_gw, &lan_netmask) && lan_netmask)
|
||||
{
|
||||
const in_addr_t lan_network = lan_gw & lan_netmask;
|
||||
const in_addr_t network = ip & netmask;
|
||||
|
|
@ -292,18 +293,20 @@ check_subnet_conflict (const in_addr_t ip,
|
|||
}
|
||||
}
|
||||
gc_free (&gc);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
warn_on_use_of_common_subnets (void)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
in_addr_t lan_gw = 0;
|
||||
in_addr_t lan_netmask = 0;
|
||||
struct route_gateway_info rgi;
|
||||
const int needed = (RGI_ADDR_DEFINED|RGI_NETMASK_DEFINED);
|
||||
|
||||
if (get_default_gateway (&lan_gw, &lan_netmask))
|
||||
get_default_gateway (&rgi);
|
||||
if ((rgi.flags & needed) == needed)
|
||||
{
|
||||
const in_addr_t lan_network = lan_gw & lan_netmask;
|
||||
const in_addr_t lan_network = rgi.gateway.addr & rgi.gateway.netmask;
|
||||
if (lan_network == 0xC0A80000 || lan_network == 0xC0A80100)
|
||||
msg (M_WARN, "NOTE: your local LAN uses the extremely common subnet address 192.168.0.x or 192.168.1.x. Be aware that this might create routing conflicts if you connect to the VPN server from public locations such as internet cafes that use the same subnet.");
|
||||
}
|
||||
|
|
@ -841,11 +844,11 @@ do_ifconfig (struct tuntap *tt,
|
|||
{
|
||||
struct route r;
|
||||
CLEAR (r);
|
||||
r.defined = true;
|
||||
r.flags = RT_DEFINED;
|
||||
r.network = tt->local & tt->remote_netmask;
|
||||
r.netmask = tt->remote_netmask;
|
||||
r.gateway = tt->local;
|
||||
add_route (&r, tt, 0, es);
|
||||
add_route (&r, tt, 0, NULL, es);
|
||||
}
|
||||
|
||||
#elif defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
dnl define the OpenVPN version
|
||||
define(PRODUCT_VERSION,[2.1.3x1])
|
||||
define(PRODUCT_VERSION,[2.1.3y])
|
||||
dnl define the TAP version
|
||||
define(PRODUCT_TAP_ID,[tap0901])
|
||||
define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])
|
||||
|
|
|
|||
Loading…
Reference in a new issue