aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--misc.c38
-rw-r--r--misc.h3
-rw-r--r--options.c21
-rw-r--r--socket.c33
-rw-r--r--socket.h2
-rw-r--r--version.m42
6 files changed, 89 insertions, 10 deletions
diff --git a/misc.c b/misc.c
index d9735bc..33e6762 100644
--- a/misc.c
+++ b/misc.c
@@ -1186,6 +1186,44 @@ create_temp_filename (const char *directory, const char *prefix, struct gc_arena
return gen_path (directory, BSTR (&fname), gc);
}
+/*
+ * Add a random string to first DNS label of hostname to prevent DNS caching.
+ * For example, foo.bar.gov would be modified to <random-chars>.foo.bar.gov.
+ * Of course, this requires explicit support in the DNS server.
+ */
+const char *
+hostname_randomize(const char *hostname, struct gc_arena *gc)
+{
+ const int n_rnd_bytes = 6;
+
+ char *hst = string_alloc(hostname, gc);
+ char *dot = strchr(hst, '.');
+
+ if (dot)
+ {
+ uint8_t rnd_bytes[n_rnd_bytes];
+ const char *rnd_str;
+ struct buffer hname = alloc_buf_gc (strlen(hostname)+sizeof(rnd_bytes)*2+4, gc);
+
+ *dot++ = '\0';
+ prng_bytes (rnd_bytes, sizeof (rnd_bytes));
+ rnd_str = format_hex_ex (rnd_bytes, sizeof (rnd_bytes), 40, 0, NULL, gc);
+ buf_printf(&hname, "%s-0x%s.%s", hst, rnd_str, dot);
+ return BSTR(&hname);
+ }
+ else
+ return hostname;
+}
+
+#else
+
+const char *
+hostname_randomize(const char *hostname, struct gc_arena *gc)
+{
+ msg (M_WARN, "WARNING: hostname randomization disabled when crypto support is not compiled");
+ return hostname;
+}
+
#endif
/*
diff --git a/misc.h b/misc.h
index 8bc1e8f..bf51e89 100644
--- a/misc.h
+++ b/misc.h
@@ -230,6 +230,9 @@ bool delete_file (const char *filename);
/* return true if pathname is absolute */
bool absolute_pathname (const char *pathname);
+/* prepend a random prefix to hostname (need USE_CRYPTO) */
+const char *hostname_randomize(const char *hostname, struct gc_arena *gc);
+
/*
* Get and store a username/password
*/
diff --git a/options.c b/options.c
index a83c6a2..eba311b 100644
--- a/options.c
+++ b/options.c
@@ -90,6 +90,7 @@ static const char usage_message[] =
"--local host : Local host name or ip address. Implies --bind.\n"
"--remote host [port] : Remote host name or ip address.\n"
"--remote-random : If multiple --remote options specified, choose one randomly.\n"
+ "--remote-random-hostname : Add a random string to remote DNS name.\n"
"--mode m : Major mode, m = 'p2p' (default, point-to-point) or 'server'.\n"
"--proto p : Use protocol p for communicating with peer.\n"
" p = udp (default), tcp-server, or tcp-client\n"
@@ -4420,15 +4421,27 @@ add_option (struct options *options,
}
options->routes->flags |= RG_ENABLE;
}
+ else if (streq (p[0], "remote-random-hostname"))
+ {
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ options->sockflags |= SF_HOST_RANDOMIZE;
+ }
else if (streq (p[0], "setenv") && p[1])
{
VERIFY_PERMISSION (OPT_P_GENERAL);
- if (streq (p[1], "FORWARD_COMPATIBLE") && p[2] && streq (p[2], "1"))
+ if (streq (p[1], "REMOTE_RANDOM_HOSTNAME"))
+ {
+ options->sockflags |= SF_HOST_RANDOMIZE;
+ }
+ else
{
- options->forward_compatible = true;
- msglevel_fc = msglevel_forward_compatible (options, msglevel);
+ if (streq (p[1], "FORWARD_COMPATIBLE") && p[2] && streq (p[2], "1"))
+ {
+ options->forward_compatible = true;
+ msglevel_fc = msglevel_forward_compatible (options, msglevel);
+ }
+ setenv_str (es, p[1], p[2] ? p[2] : "");
}
- setenv_str (es, p[1], p[2] ? p[2] : "");
}
else if (streq (p[0], "setenv-safe") && p[1])
{
diff --git a/socket.c b/socket.c
index f3407bb..fecc398 100644
--- a/socket.c
+++ b/socket.c
@@ -32,6 +32,7 @@
#include "plugin.h"
#include "ps.h"
#include "manage.h"
+#include "misc.h"
#include "memdbg.h"
@@ -43,6 +44,19 @@ const int proto_overhead[] = { /* indexed by PROTO_x */
};
/*
+ * Convert sockflags/getaddr_flags into getaddr_flags
+ */
+static unsigned int
+sf2gaf(const unsigned int getaddr_flags,
+ const unsigned int sockflags)
+{
+ if (sockflags & SF_HOST_RANDOMIZE)
+ return getaddr_flags | GETADDR_RANDOMIZE;
+ else
+ return getaddr_flags;
+}
+
+/*
* Functions related to the translation of DNS names to IP addresses.
*/
@@ -79,6 +93,10 @@ getaddr (unsigned int flags,
int status;
int sigrec = 0;
int msglevel = (flags & GETADDR_FATAL) ? M_FATAL : D_RESOLVE_ERRORS;
+ struct gc_arena gc = gc_new ();
+
+ if (flags & GETADDR_RANDOMIZE)
+ hostname = hostname_randomize(hostname, &gc);
if (flags & GETADDR_MSG_VIRT_OUT)
msglevel |= M_MSG_VIRT_OUT;
@@ -225,6 +243,7 @@ getaddr (unsigned int flags,
msg (level, "RESOLVE: signal received during DNS resolution attempt");
}
+ gc_free (&gc);
return (flags & GETADDR_HOST_ORDER) ? ntohl (ia.s_addr) : ia.s_addr;
}
@@ -359,12 +378,13 @@ mac_addr_safe (const char *mac_addr)
static void
update_remote (const char* host,
struct openvpn_sockaddr *addr,
- bool *changed)
+ bool *changed,
+ const unsigned int sockflags)
{
if (host && addr)
{
const in_addr_t new_addr = getaddr (
- GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE,
+ sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sockflags),
host,
1,
NULL,
@@ -728,7 +748,7 @@ socket_listen_accept (socket_descriptor_t sd,
if (socket_defined (new_sd))
{
- update_remote (remote_dynamic, &remote_verify, remote_changed);
+ update_remote (remote_dynamic, &remote_verify, remote_changed, 0);
if (addr_defined (&remote_verify)
&& !addr_match (&remote_verify, &act->dest))
{
@@ -858,6 +878,7 @@ socket_connect (socket_descriptor_t *sd,
const int connect_retry_seconds,
const int connect_timeout,
const int connect_retry_max,
+ const unsigned int sockflags,
volatile int *signal_received)
{
struct gc_arena gc = gc_new ();
@@ -919,7 +940,7 @@ socket_connect (socket_descriptor_t *sd,
*sd = create_socket_tcp ();
if (bind_local)
socket_bind (*sd, local, "TCP Client");
- update_remote (remote_dynamic, remote, remote_changed);
+ update_remote (remote_dynamic, remote, remote_changed, sockflags);
}
msg (M_INFO, "TCP connection established with %s",
@@ -1023,7 +1044,7 @@ resolve_remote (struct link_socket *sock,
if (sock->remote_host)
{
- unsigned int flags = GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE;
+ unsigned int flags = sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sock->sockflags);
int retry = 0;
bool status = false;
@@ -1384,6 +1405,7 @@ link_socket_init_phase2 (struct link_socket *sock,
sock->connect_retry_seconds,
sock->connect_timeout,
sock->connect_retry_max,
+ sock->sockflags,
signal_received);
if (*signal_received)
@@ -1432,6 +1454,7 @@ link_socket_init_phase2 (struct link_socket *sock,
sock->connect_retry_seconds,
sock->connect_timeout,
sock->connect_retry_max,
+ sock->sockflags,
signal_received);
if (*signal_received)
diff --git a/socket.h b/socket.h
index e412f03..6877e66 100644
--- a/socket.h
+++ b/socket.h
@@ -198,6 +198,7 @@ struct link_socket
# define SF_USE_IP_PKTINFO (1<<0)
# define SF_TCP_NODELAY (1<<1)
# define SF_PORT_SHARE (1<<2)
+# define SF_HOST_RANDOMIZE (1<<3)
unsigned int sockflags;
/* for stream sockets */
@@ -447,6 +448,7 @@ bool unix_socket_get_peer_uid_gid (const socket_descriptor_t sd, int *uid, int *
#define GETADDR_MSG_VIRT_OUT (1<<6)
#define GETADDR_TRY_ONCE (1<<7)
#define GETADDR_UPDATE_MANAGEMENT_STATE (1<<8)
+#define GETADDR_RANDOMIZE (1<<9)
in_addr_t getaddr (unsigned int flags,
const char *hostname,
diff --git a/version.m4 b/version.m4
index 5c84929..dde430d 100644
--- a/version.m4
+++ b/version.m4
@@ -1,5 +1,5 @@
dnl define the OpenVPN version
-define(PRODUCT_VERSION,[2.1_rc19])
+define(PRODUCT_VERSION,[2.1_rc19a])
dnl define the TAP version
define(PRODUCT_TAP_ID,[tap0901])
define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])