[tor-commits] [torsocks/master] Add support for localhost only UDP via `AllowOutboundLocalhost 2`.

dgoulet at torproject.org dgoulet at torproject.org
Mon Jun 13 21:14:03 UTC 2016


commit f1301e083ed67752ef89e07f1a961ac5b635d9f2
Author: Yawning Angel <yawning at 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 at progsoc.org> 
+ * Copyright (C) 2000-2008 - Shaun Clowes <delius at progsoc.org>
  * 				 2008-2011 - Robert Hogan <robert at roberthogan.net>
  * 				 	  2013 - David Goulet <dgoulet at 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);





More information about the tor-commits mailing list