commit f1301e083ed67752ef89e07f1a961ac5b635d9f2 Author: Yawning Angel yawning@schwanenlied.me Date: Sat Nov 7 11:14:30 2015 +0000
Add support for localhost only UDP via `AllowOutboundLocalhost 2`.
Exactly what it says on the tin, setting `AllowOutboundLocalhost 2` will:
* Allow all SOCK_DGRAM socket() calls. * Allow connect() to localhost, even for SOCK_DGRAM. * Allow SOCK_DGRAM sendto() calls, as long as the destination address is localhost.
Fixes bug #16765. --- doc/torsocks.conf | 4 +++- doc/torsocks.conf.5 | 7 ++++--- src/common/compat.h | 4 ++++ src/common/config-file.c | 3 +++ src/common/config-file.h | 2 +- src/lib/connect.c | 14 ++++++++++---- src/lib/sendto.c | 8 +++++++- src/lib/socket.c | 10 ++++++++++ src/lib/torsocks.h | 1 + 9 files changed, 43 insertions(+), 10 deletions(-)
diff --git a/doc/torsocks.conf b/doc/torsocks.conf index 5dd9df6..ec99766 100644 --- a/doc/torsocks.conf +++ b/doc/torsocks.conf @@ -31,7 +31,9 @@ OnionAddrRange 127.42.42.0/24
# Set Torsocks to allow outbound connections to the loopback interface. # If set to 1, connect() will be allowed to be used to the loopback interface -# bypassing Tor. This option should not be used by most users. (Default: 0) +# bypassing Tor. If set to 2, in addition to TCP connect(), UDP operations to +# the loopback interface will also be allowed, bypassing Tor. This option +# should not be used by most users. (Default: 0) #AllowOutboundLocalhost 1
# Set Torsocks to use an automatically generated SOCKS5 username/password based diff --git a/doc/torsocks.conf.5 b/doc/torsocks.conf.5 index 33fba3e..a6cc9b8 100644 --- a/doc/torsocks.conf.5 +++ b/doc/torsocks.conf.5 @@ -78,10 +78,11 @@ allowed for non localhost address so the applicaton can handle incoming connection. Note that Unix socket are allowed. (Default: 0)
.TP -.I AllowOutboundLocalhost 0|1 +.I AllowOutboundLocalhost 0|1|2 Allow outbound connections to the loopback interface meaning that connect() -will be allowed to connect to localhost addresses bypassing Tor. This option -should not be used by most users. (Default: 0) +will be allowed to connect to localhost addresses bypassing Tor. If set to 1, +TCP connections will be allowed. If set to 2, both TCP/IP and UDP connections +will be allowed. This option should not be used by most users. (Default: 0)
.TP .I IsolatePID 0|1 diff --git a/src/common/compat.h b/src/common/compat.h index 6c8ce32..38bf191 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -220,9 +220,13 @@ void tsocks_once(tsocks_once_t *o, void (*init_routine)(void)); #if defined(__NetBSD__) #define IS_SOCK_STREAM(type) \ ((type & ~(SOCK_NONBLOCK | SOCK_CLOEXEC | SOCK_NOSIGPIPE)) == SOCK_STREAM) +#define IS_SOCK_DGRAM(type) \ + ((type & ~(SOCK_NONBLOCK | SOCK_CLOEXEC | SOCK_NOSIGPIPE)) == SOCK_DGRAM) #else /* __NetBSD__ */ #define IS_SOCK_STREAM(type) \ ((type & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) == SOCK_STREAM) +#define IS_SOCK_DGRAM(type) \ + ((type & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) == SOCK_DGRAM) #endif /* __NetBSD__ */
#endif /* TORSOCKS_COMPAT_H */ diff --git a/src/common/config-file.c b/src/common/config-file.c index 2147068..da89ef7 100644 --- a/src/common/config-file.c +++ b/src/common/config-file.c @@ -406,6 +406,9 @@ int conf_file_set_allow_outbound_localhost(const char *val, } else if (ret == 1) { config->allow_outbound_localhost = 1; DBG("[config] Outbound localhost connections allowed."); + } else if (ret == 2) { + config->allow_outbound_localhost = 2; + DBG("[config] Outbound localhost connections + UDP allowed."); } else { ERR("[config] Invalid %s value for %s", val, conf_allow_outbound_localhost_str); diff --git a/src/common/config-file.h b/src/common/config-file.h index 23dd842..48be392 100644 --- a/src/common/config-file.h +++ b/src/common/config-file.h @@ -82,7 +82,7 @@ struct configuration { /* * Allow outbound connections to localhost that bypass Tor. */ - unsigned int allow_outbound_localhost:1; + unsigned int allow_outbound_localhost;
/* * Automatically set the SOCKS5 authentication to a unique per-process diff --git a/src/lib/connect.c b/src/lib/connect.c index 2480643..71c5886 100644 --- a/src/lib/connect.c +++ b/src/lib/connect.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2008 - Shaun Clowes delius@progsoc.org + * Copyright (C) 2000-2008 - Shaun Clowes delius@progsoc.org * 2008-2011 - Robert Hogan robert@roberthogan.net * 2013 - David Goulet dgoulet@ev0ke.net * @@ -45,7 +45,7 @@ TSOCKS_LIBC_DECL(connect, LIBC_CONNECT_RET_TYPE, LIBC_CONNECT_SIG) * On error or if validation fails, errno is set and -1 is returned. The caller * should *return* right away an error. */ -static int validate_socket(int sockfd, const struct sockaddr *addr) +int tsocks_validate_socket(int sockfd, const struct sockaddr *addr) { int ret, sock_type; socklen_t optlen; @@ -76,8 +76,14 @@ static int validate_socket(int sockfd, const struct sockaddr *addr) DBG("[connect] Socket family %s and type %d", addr->sa_family == AF_INET ? "AF_INET" : "AF_INET6", sock_type);
- /* Refuse non stream socket since Tor can't handle that. */ if (!IS_SOCK_STREAM(sock_type)) { + if ((tsocks_config.allow_outbound_localhost == 2) && + IS_SOCK_DGRAM(sock_type) && utils_sockaddr_is_localhost(addr)) { + DBG("[connect] Allowing localhost UDP socket."); + goto libc_call; + } + + /* Refuse non stream socket since Tor can't handle that. */ DBG("[connect] UDP or ICMP stream can't be handled. Rejecting."); errno = EPERM; goto error; @@ -115,7 +121,7 @@ LIBC_CONNECT_RET_TYPE tsocks_connect(LIBC_CONNECT_SIG) * Validate socket values in order to see if we can handle this connect * through Tor. */ - ret = validate_socket(sockfd, addr); + ret = tsocks_validate_socket(sockfd, addr); if (ret == 1) { /* Tor can't handle it so send it to the libc. */ goto libc_connect; diff --git a/src/lib/sendto.c b/src/lib/sendto.c index 6b1d3ff..75994f4 100644 --- a/src/lib/sendto.c +++ b/src/lib/sendto.c @@ -43,8 +43,8 @@ TSOCKS_LIBC_DECL(sendto, LIBC_SENDTO_RET_TYPE, LIBC_SENDTO_SIG) */ LIBC_SENDTO_RET_TYPE tsocks_sendto(LIBC_SENDTO_SIG) { -#ifdef MSG_FASTOPEN int ret; +#ifdef MSG_FASTOPEN
if ((flags & MSG_FASTOPEN) == 0) { /* No TFO, fallback to libc sendto() */ @@ -64,6 +64,12 @@ LIBC_SENDTO_RET_TYPE tsocks_sendto(LIBC_SENDTO_SIG) libc_sendto: #endif /* MSG_FASTOPEN */
+ /* Validate that the socket and address are ok to send traffic to. */ + ret = tsocks_validate_socket(sockfd, dest_addr); + if (ret == -1) { + return ret; + } + return tsocks_libc_sendto(LIBC_SENDTO_ARGS); }
diff --git a/src/lib/socket.c b/src/lib/socket.c index edc24ab..331de0b 100644 --- a/src/lib/socket.c +++ b/src/lib/socket.c @@ -48,6 +48,16 @@ LIBC_SOCKET_RET_TYPE tsocks_socket(LIBC_SOCKET_SIG) }
/* + * If outbound localhost UDP traffic is allowed, then allow all UDP + * socket creation. Validation on the destination addr is done at + * connect()/sendto() time. + */ + if ((tsocks_config.allow_outbound_localhost == 2) && + IS_SOCK_DGRAM(type)) { + goto end; + } + + /* * Print this message only in debug mode. Very often, applications uses * the libc to do DNS resolution which first tries with UDP and then * with TCP. It's not critical for the user to know that a non TCP diff --git a/src/lib/torsocks.h b/src/lib/torsocks.h index 9531db5..eddd0de 100644 --- a/src/lib/torsocks.h +++ b/src/lib/torsocks.h @@ -445,6 +445,7 @@ extern struct onion_pool tsocks_onion_pool;
extern unsigned int tsocks_cleaned_up;
+int tsocks_validate_socket(int sockfd, const struct sockaddr *addr); int tsocks_connect_to_tor(struct connection *conn); void *tsocks_find_libc_symbol(const char *symbol, enum tsocks_sym_action action);
tor-commits@lists.torproject.org