From 09ccc4c4a3b67695295ad95f24b2f102d5f2fa1a Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 31 Jan 2014 12:59:35 -0500 Subject: [PATCH 1/3] Add support for TPROXY via new TransTPRoxy option Based on patch from "thomo" at #10582. --- changes/10582_tproxy | 7 +++++++ doc/tor.1.txt | 13 +++++++++++++ src/or/config.c | 26 ++++++++++++++++++++++---- src/or/connection.c | 11 +++++++++++ src/or/or.h | 2 ++ 5 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 changes/10582_tproxy diff --git a/changes/10582_tproxy b/changes/10582_tproxy new file mode 100644 index 0000000000..3609d568a8 --- /dev/null +++ b/changes/10582_tproxy @@ -0,0 +1,7 @@ + o Minor features: + + - Add support for the TPROXY transparent proxying facility on Linux. + See documentation for the new TransTRPOXY option for more details. + Implementation by "thomo". Closes ticket 10582. + + diff --git a/doc/tor.1.txt b/doc/tor.1.txt index 28e7c5d7d1..69452a02f9 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -1183,6 +1183,19 @@ The following options are useful only for clients (that is, if compatibility, TransListenAddress is only allowed when TransPort is just a port number.) +[[TransTPROXY]] **TransTPROXY** **0**|**1**:: + TransTPROXY may only be enabled when there is transparent proxy listener + enabled and only for Linux. + + + Set this 1 if you wish to be able to use the TPROXY linux module to + transparently proxy connections that are configured using the TransPort + option. This setting lets the listener on the TransPort accept connections + for all addresses, even when the TransListenAddress is configured for an + internal address. Detailed information on how to configure the TPROXY + feature can be found in the Linux kernel source tree in the file + Documentation/networking/tproxy.txt. + (Default: 0) + [[NATDPort]] **NATDPort** \['address':]__port__|**auto** [_isolation flags_]:: Open this port to listen for connections from old versions of ipfw (as included in old versions of FreeBSD, etc) using the NATD protocol. diff --git a/src/or/config.c b/src/or/config.c index d348f1036b..a2366c06fa 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -408,6 +408,7 @@ static config_var_t option_vars_[] = { OBSOLETE("TrafficShaping"), V(TransListenAddress, LINELIST, NULL), VPORT(TransPort, LINELIST, NULL), + V(TransTPROXY, BOOL, "0"), V(TunnelDirConns, BOOL, "1"), V(UpdateBridgesFromAuthority, BOOL, "0"), V(UseBridges, BOOL, "0"), @@ -2530,10 +2531,27 @@ options_validate(or_options_t *old_options, or_options_t *options, "undefined, and there aren't any hidden services configured. " "Tor will still run, but probably won't do anything."); -#ifndef USE_TRANSPARENT - /* XXXX024 I think we can remove this TransListenAddress */ - if (options->TransPort_set || options->TransListenAddress) - REJECT("TransPort and TransListenAddress are disabled in this build."); +#ifdef USE_TRANSPARENT + if (options->TransTPROXY) { +#ifndef __linux__ + REJECT("TransTPROXY is a Linux-specific feature.") +#endif + if (!options->TransPort_set) { + REJECT("Cannot use TransTPROXY without any valid TransPort or " + "TransListenAddress."); + } + /* Friendly suggestion about running as root initially. */ + if (!options->User) { + log_warn(LD_CONFIG, + "You have enabled TransTPROXY but have not specified the " + "\"User\" option. TransTPROXY will not function without " + "root privileges."); + } + } +#else + if (options->TransPort_set || options->TransTPROXY) + REJECT("TransPort, TransListenAddress, and TransTPROXY are disabled " + "in this build."); #endif if (options->TokenBucketRefillInterval <= 0 diff --git a/src/or/connection.c b/src/or/connection.c index 1f6e11fac1..7d8feeb95c 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -1035,6 +1035,17 @@ connection_listener_new(const struct sockaddr *listensockaddr, make_socket_reuseable(s); +#if defined USE_TRANSPARENT && defined(IP_TRANSPARENT) + if (options->TransTPROXY && type == CONN_TYPE_AP_TRANS_LISTENER) { + int one = 1; + if (setsockopt(s, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) < 0) { + int e = tor_socket_errno(s); + log_warn(LD_NET, "Error setting IP_TRANSPARENT flag: %s", + tor_socket_strerror(e)); + } + } +#endif + #ifdef IPV6_V6ONLY if (listensockaddr->sa_family == AF_INET6) { #ifdef _WIN32 diff --git a/src/or/or.h b/src/or/or.h index 7df6c37f7d..55f2862089 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3553,6 +3553,8 @@ typedef struct { config_line_t *SocksPort_lines; /** Ports to listen on for transparent pf/netfilter connections. */ config_line_t *TransPort_lines; + int TransTPROXY; /** < Boolean: are we going to listen for all destinations + * on the TransPort_lines are required for TPROXY? */ config_line_t *NATDPort_lines; /**< Ports to listen on for transparent natd * connections. */ config_line_t *ControlPort_lines; /**< Ports to listen on for control From fd8947afc2815cc3316513fe4461d8d8096eddea Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Sun, 2 Feb 2014 15:45:00 -0500 Subject: [PATCH 2/3] Move the friendly warning about TPROXY and root to EPERM time I'm doing this because: * User doesn't mean you're running as root, and running as root doesn't mean you've set User. * It's possible that the user has done some other capability-based hack to retain the necessary privileges. --- src/or/config.c | 7 ------- src/or/connection.c | 8 ++++++-- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/or/config.c b/src/or/config.c index a2366c06fa..c921bb7317 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -2540,13 +2540,6 @@ options_validate(or_options_t *old_options, or_options_t *options, REJECT("Cannot use TransTPROXY without any valid TransPort or " "TransListenAddress."); } - /* Friendly suggestion about running as root initially. */ - if (!options->User) { - log_warn(LD_CONFIG, - "You have enabled TransTPROXY but have not specified the " - "\"User\" option. TransTPROXY will not function without " - "root privileges."); - } } #else if (options->TransPort_set || options->TransTPROXY) diff --git a/src/or/connection.c b/src/or/connection.c index 7d8feeb95c..6dbba668c6 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -1039,9 +1039,13 @@ connection_listener_new(const struct sockaddr *listensockaddr, if (options->TransTPROXY && type == CONN_TYPE_AP_TRANS_LISTENER) { int one = 1; if (setsockopt(s, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) < 0) { + const char *extra = ""; int e = tor_socket_errno(s); - log_warn(LD_NET, "Error setting IP_TRANSPARENT flag: %s", - tor_socket_strerror(e)); + if (e == EPERM) + extra = "TransTPROXY requires root privileges or similar" + " capabilities."; + log_warn(LD_NET, "Error setting IP_TRANSPARENT flag: %s.%s", + tor_socket_strerror(e), extra); } } #endif From 25f0eb4512a57e305ed0bff00eb276812a7c8de6 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Sun, 2 Feb 2014 15:47:48 -0500 Subject: [PATCH 3/3] Add a sandbox rule to allow IP_TRANSPARENT --- src/common/sandbox.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index dec6bfeea5..6b78748834 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -475,6 +475,14 @@ sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) if (rc) return rc; +#ifdef IP_TRANSPARENT + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 2, + SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP), + SCMP_CMP(2, SCMP_CMP_EQ, IP_TRANSPARENT)); + if (rc) + return rc; +#endif + return 0; }