aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--error.c29
-rw-r--r--event.c4
-rw-r--r--init.c4
-rw-r--r--openvpn.812
-rw-r--r--options.c6
-rw-r--r--options.h1
-rw-r--r--ps.c104
-rw-r--r--ps.h4
8 files changed, 131 insertions, 33 deletions
diff --git a/error.c b/error.c
index 873718c..9cf4547 100644
--- a/error.c
+++ b/error.c
@@ -353,7 +353,7 @@ void x_msg (const unsigned int flags, const char *format, ...)
}
if (flags & M_FATAL)
- msg (M_INFO, "Exiting");
+ msg (M_INFO, "Exiting due to fatal error");
mutex_unlock_static (L_MSG);
@@ -690,35 +690,38 @@ msg_thread_uninit (void)
void
openvpn_exit (const int status)
{
- void tun_abort();
+ if (!forked)
+ {
+ void tun_abort();
#ifdef ENABLE_PLUGIN
- void plugin_abort (void);
+ void plugin_abort (void);
#endif
- tun_abort();
+ tun_abort();
#ifdef WIN32
- uninit_win32 ();
+ uninit_win32 ();
#endif
- close_syslog ();
+ close_syslog ();
#ifdef ENABLE_PLUGIN
- plugin_abort ();
+ plugin_abort ();
#endif
#if PORT_SHARE
- if (port_share)
- port_share_abort (port_share);
+ if (port_share)
+ port_share_abort (port_share);
#endif
#ifdef ABORT_ON_ERROR
- if (status == OPENVPN_EXIT_STATUS_ERROR)
- abort ();
+ if (status == OPENVPN_EXIT_STATUS_ERROR)
+ abort ();
#endif
- if (status == OPENVPN_EXIT_STATUS_GOOD)
- perf_output_results ();
+ if (status == OPENVPN_EXIT_STATUS_GOOD)
+ perf_output_results ();
+ }
exit (status);
}
diff --git a/event.c b/event.c
index 6a9161b..51b17b3 100644
--- a/event.c
+++ b/event.c
@@ -522,10 +522,10 @@ ep_ctl (struct event_set *es, event_t event, unsigned int rwflags, void *arg)
if (errno == ENOENT)
{
if (epoll_ctl (eps->epfd, EPOLL_CTL_ADD, event, &ev) < 0)
- msg (M_ERR, "EVENT: epoll_ctl EPOLL_CTL_ADD failed");
+ msg (M_ERR, "EVENT: epoll_ctl EPOLL_CTL_ADD failed, sd=%d", (int)event);
}
else
- msg (M_ERR, "EVENT: epoll_ctl EPOLL_CTL_MOD failed");
+ msg (M_ERR, "EVENT: epoll_ctl EPOLL_CTL_MOD failed, sd=%d", (int)event);
}
}
diff --git a/init.c b/init.c
index 70357e1..4214233 100644
--- a/init.c
+++ b/init.c
@@ -520,7 +520,9 @@ init_port_share (struct context *c)
if (!port_share && (c->options.port_share_host && c->options.port_share_port))
{
port_share = port_share_open (c->options.port_share_host,
- c->options.port_share_port);
+ c->options.port_share_port,
+ MAX_RW_SIZE_LINK (&c->c2.frame),
+ c->options.port_share_journal_dir);
if (port_share == NULL)
msg (M_FATAL, "Fatal error: Port sharing failed");
}
diff --git a/openvpn.8 b/openvpn.8
index c5eb3ca..037ba7e 100644
--- a/openvpn.8
+++ b/openvpn.8
@@ -3240,7 +3240,7 @@ disable the remapping feature. Don't use this option unless you
know what you are doing!
.\"*********************************************************
.TP
-.B --port-share host port
+.B --port-share host port [dir]
When run in TCP server mode, share the OpenVPN port with
another application, such as an HTTPS server. If OpenVPN
senses a connection to its port which is using a non-OpenVPN
@@ -3250,6 +3250,16 @@ Currently only designed to work with HTTP/HTTPS,
though it would be theoretically possible to extend to
other protocols such as ssh.
+.B dir
+specifies an optional directory where a temporary file with name N
+containing content C will be dynamically generated for each proxy
+connection, where N is the source IP:port of the client connection
+and C is the source IP:port of the connection to the proxy
+receiver. This directory can be used as a dictionary by
+the proxy receiver to determine the origin of the connection.
+Each generated file will be automatically deleted when the proxied
+connection is torn down.
+
Not implemented on Windows.
.\"*********************************************************
.SS Client Mode
diff --git a/options.c b/options.c
index e8e0d7a..8ace13f 100644
--- a/options.c
+++ b/options.c
@@ -427,8 +427,9 @@ static const char usage_message[] =
"--max-clients n : Allow a maximum of n simultaneously connected clients.\n"
"--max-routes-per-client n : Allow a maximum of n internal routes per client.\n"
#if PORT_SHARE
- "--port-share host port : When run in TCP mode, proxy incoming HTTPS sessions\n"
- " to a web server at host:port.\n"
+ "--port-share host port [dir] : When run in TCP mode, proxy incoming HTTPS\n"
+ " sessions to a web server at host:port. dir specifies an\n"
+ " optional directory to write origin IP:port data.\n"
#endif
#endif
"\n"
@@ -5101,6 +5102,7 @@ add_option (struct options *options,
options->port_share_host = p[1];
options->port_share_port = port;
+ options->port_share_journal_dir = p[3];
}
#endif
else if (streq (p[0], "client-to-client"))
diff --git a/options.h b/options.h
index fd9eb7c..74ba9d4 100644
--- a/options.h
+++ b/options.h
@@ -430,6 +430,7 @@ struct options
#if PORT_SHARE
char *port_share_host;
int port_share_port;
+ const char *port_share_journal_dir;
#endif
#endif
diff --git a/ps.c b/ps.c
index c77e769..26cf4cb 100644
--- a/ps.c
+++ b/ps.c
@@ -69,6 +69,7 @@ struct proxy_connection {
bool buffer_initial;
int rwflags;
int sd;
+ char *jfn;
};
#if 0
@@ -226,7 +227,7 @@ port_share_sendmsg (const socket_descriptor_t sd,
status = sendmsg (sd, &mesg, MSG_NOSIGNAL);
if (status == -1)
- msg (M_WARN, "PORT SHARE: sendmsg failed (unable to communicate with background process)");
+ msg (M_WARN|M_ERRNO_SOCK, "PORT SHARE: sendmsg failed (unable to communicate with background process)");
close_socket_if_defined (sd_null[0]);
close_socket_if_defined (sd_null[1]);
@@ -273,6 +274,12 @@ proxy_entry_mark_for_close (struct proxy_connection *pc, struct event_set *es)
pc->buffer_initial = false;
pc->rwflags = 0;
pc->defined = false;
+ if (pc->jfn)
+ {
+ unlink (pc->jfn);
+ free (pc->jfn);
+ pc->jfn = NULL;
+ }
if (cp && cp->defined && cp->counterpart == pc)
proxy_entry_mark_for_close (cp, es);
}
@@ -309,6 +316,48 @@ proxy_list_housekeeping (struct proxy_connection **list)
}
/*
+ * Record IP/port of client in filesystem, so that server receiving
+ * the proxy can determine true client origin.
+ */
+static void
+journal_add (const char *journal_dir, struct proxy_connection *pc, struct proxy_connection *cp)
+{
+ struct gc_arena gc = gc_new ();
+ struct openvpn_sockaddr from, to;
+ socklen_t slen, dlen;
+ int fnlen;
+ char *jfn;
+ int fd;
+
+ slen = sizeof(from.sa);
+ dlen = sizeof(to.sa);
+ if (!getpeername (pc->sd, (struct sockaddr *) &from.sa, &slen)
+ && !getsockname (cp->sd, (struct sockaddr *) &to.sa, &dlen))
+ {
+ const char *f = print_sockaddr_ex (&from, ":", PS_SHOW_PORT, &gc);
+ const char *t = print_sockaddr_ex (&to, ":", PS_SHOW_PORT, &gc);
+ fnlen = strlen(journal_dir) + strlen(t) + 2;
+ jfn = (char *) malloc(fnlen);
+ check_malloc_return (jfn);
+ openvpn_snprintf (jfn, fnlen, "%s/%s", journal_dir, t);
+ dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: client origin %s -> %s", jfn, f);
+ fd = open (jfn, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
+ if (fd != -1)
+ {
+ write(fd, f, strlen(f));
+ close (fd);
+ cp->jfn = jfn;
+ }
+ else
+ {
+ msg (M_WARN|M_ERRNO, "PORT SHARE: unable to write journal file in %s", jfn);
+ free (jfn);
+ }
+ }
+ gc_free (&gc);
+}
+
+/*
* Cleanup function, on proxy process exit.
*/
static void
@@ -361,7 +410,8 @@ proxy_entry_new (struct proxy_connection **list,
const in_addr_t server_addr,
const int server_port,
const socket_descriptor_t sd_client,
- struct buffer *initial_data)
+ struct buffer *initial_data,
+ const char *journal_dir)
{
struct openvpn_sockaddr osaddr;
socket_descriptor_t sd_server;
@@ -371,7 +421,11 @@ proxy_entry_new (struct proxy_connection **list,
/* connect to port share server */
sock_addr_set (&osaddr, server_addr, server_port);
- sd_server = create_socket_tcp ();
+ if ((sd_server = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+ {
+ msg (M_WARN|M_ERRNO_SOCK, "PORT SHARE PROXY: cannot create socket");
+ return false;
+ }
status = openvpn_connect (sd_server, &osaddr, 5, NULL);
if (status)
{
@@ -408,6 +462,10 @@ proxy_entry_new (struct proxy_connection **list,
/* add to list */
*list = pc;
+
+ /* add journal entry */
+ if (journal_dir)
+ journal_add (journal_dir, pc, cp);
dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: NEW CONNECTION [c=%d s=%d]", (int)sd_client, (int)sd_server);
@@ -429,9 +487,14 @@ control_message_from_parent (const socket_descriptor_t sd_control,
struct proxy_connection **list,
struct event_set *es,
const in_addr_t server_addr,
- const int server_port)
+ const int server_port,
+ const int max_initial_buf,
+ const char *journal_dir)
{
- struct buffer buf = alloc_buf (PROXY_CONNECTION_BUFFER_SIZE);
+ /* this buffer needs to be large enough to handle the largest buffer
+ that might be returned by the link_socket_read call in read_incoming_link. */
+ struct buffer buf = alloc_buf (max_initial_buf);
+
struct msghdr mesg;
struct cmsghdr* h;
struct iovec iov[2];
@@ -467,7 +530,7 @@ control_message_from_parent (const socket_descriptor_t sd_control,
|| h->cmsg_level != SOL_SOCKET
|| h->cmsg_type != SCM_RIGHTS )
{
- ret = false;
+ msg (M_WARN, "PORT SHARE PROXY: received unknown message");
}
else
{
@@ -482,7 +545,8 @@ control_message_from_parent (const socket_descriptor_t sd_control,
server_addr,
server_port,
received_fd,
- &buf))
+ &buf,
+ journal_dir))
{
CLEAR (buf); /* we gave the buffer to proxy_entry_new */
}
@@ -517,6 +581,7 @@ proxy_connection_io_recv (struct proxy_connection *pc)
{
if (!status)
return IOSTAT_READ_ERROR;
+ dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: read[%d] %d", (int)pc->sd, status);
pc->buf.len = status;
}
return IOSTAT_GOOD;
@@ -544,7 +609,7 @@ proxy_connection_io_send (struct proxy_connection *pc, int *bytes_sent)
}
else
{
- /*dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: wrote[%d] %d", (int)sd, status);*/
+ dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: wrote[%d] %d", (int)sd, status);
pc->buf.len = 0;
pc->buf.offset = 0;
}
@@ -627,6 +692,8 @@ proxy_connection_io_dispatch (struct proxy_connection *pc,
int rwflags_pc = pc->rwflags;
int rwflags_cp = cp->rwflags;
+ ASSERT(pc->defined && cp->defined && cp->counterpart == pc);
+
if (rwflags & EVENT_READ)
{
const int status = proxy_connection_io_xfer (pc, max_transfer_per_iteration);
@@ -653,7 +720,11 @@ proxy_connection_io_dispatch (struct proxy_connection *pc,
* This is the main function for the port share proxy background process.
*/
static void
-port_share_proxy (const in_addr_t hostaddr, const int port, const socket_descriptor_t sd_control)
+port_share_proxy (const in_addr_t hostaddr,
+ const int port,
+ const socket_descriptor_t sd_control,
+ const int max_initial_buf,
+ const char *journal_dir)
{
if (send_control (sd_control, RESPONSE_INIT_SUCCEEDED) >= 0)
{
@@ -687,7 +758,7 @@ port_share_proxy (const in_addr_t hostaddr, const int port, const socket_descrip
const struct event_set_return *e = &esr[i];
if (e->arg == sd_control_marker)
{
- if (!control_message_from_parent (sd_control, &list, es, hostaddr, port))
+ if (!control_message_from_parent (sd_control, &list, es, hostaddr, port, max_initial_buf, journal_dir))
goto done;
}
else
@@ -713,7 +784,7 @@ port_share_proxy (const in_addr_t hostaddr, const int port, const socket_descrip
proxy_list_close (&list);
event_free (es);
}
- msg (D_PS_PROXY, "PORT SHARE PROXY: proxy exiting");
+ msg (M_INFO, "PORT SHARE PROXY: proxy exiting");
}
/*
@@ -721,7 +792,10 @@ port_share_proxy (const in_addr_t hostaddr, const int port, const socket_descrip
* share proxy.
*/
struct port_share *
-port_share_open (const char *host, const int port)
+port_share_open (const char *host,
+ const int port,
+ const int max_initial_buf,
+ const char *journal_dir)
{
pid_t pid;
socket_descriptor_t fd[2];
@@ -766,6 +840,10 @@ port_share_open (const char *host, const int port)
/* don't let future subprocesses inherit child socket */
set_cloexec (fd[0]);
+ /* note that this will cause possible EAGAIN when writing to
+ control socket if proxy process is backlogged */
+ set_nonblock (fd[0]);
+
/* wait for background child process to initialize */
status = recv_control (fd[0]);
if (status == RESPONSE_INIT_SUCCEEDED)
@@ -796,7 +874,7 @@ port_share_open (const char *host, const int port)
prng_init (NULL, 0);
/* execute the event loop */
- port_share_proxy (hostaddr, port, fd[1]);
+ port_share_proxy (hostaddr, port, fd[1], max_initial_buf, journal_dir);
openvpn_close_socket (fd[1]);
diff --git a/ps.h b/ps.h
index d488a72..4280635 100644
--- a/ps.h
+++ b/ps.h
@@ -44,7 +44,9 @@ struct port_share {
extern struct port_share *port_share;
struct port_share *port_share_open (const char *host,
- const int port);
+ const int port,
+ const int max_initial_buf,
+ const char *journal_dir);
void port_share_close (struct port_share *ps);
void port_share_abort (struct port_share *ps);