mirror of
https://github.com/OpenVPN/openvpn.git
synced 2024-11-27 11:43:51 +08:00
Added optional journal directory argument to "port-share" directive, for reporting client IP origins of proxied connections.
git-svn-id: http://svn.openvpn.net/projects/branches/BETA21@7031 e7ae566f-a301-0410-adde-c780ea21d3b5
This commit is contained in:
parent
6c34e74f13
commit
1c5ff7722d
29
error.c
29
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);
|
||||
}
|
||||
|
4
event.c
4
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
4
init.c
4
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");
|
||||
}
|
||||
|
12
openvpn.8
12
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
|
||||
|
@ -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"))
|
||||
|
@ -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
|
||||
|
||||
|
104
ps.c
104
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);
|
||||
}
|
||||
@ -308,6 +315,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.
|
||||
*/
|
||||
@ -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]);
|
||||
|
||||
|
4
ps.h
4
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);
|
||||
|
Loading…
Reference in New Issue
Block a user