aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changes/bug227915
-rw-r--r--doc/spec/control-spec.txt6
-rw-r--r--doc/tor.1.txt12
-rw-r--r--src/or/config.c2
-rw-r--r--src/or/connection.c5
-rw-r--r--src/or/connection_edge.c22
-rw-r--r--src/or/or.h11
-rw-r--r--src/or/reasons.c5
8 files changed, 74 insertions, 4 deletions
diff --git a/changes/bug2279 b/changes/bug2279
new file mode 100644
index 0000000000..d31300978e
--- /dev/null
+++ b/changes/bug2279
@@ -0,0 +1,15 @@
+ o Minor bugfixes
+ - Avoid a double mark-for-free warning when failing to attach a
+ transparent proxy connection. Fixes bug 2279. Bugfix on
+ Tor 0.1.2.1 alpha.
+
+ o Minor features
+ - Detect attempts at the client side to open connections to private
+ IP addresses (like 127.0.0.1, 10.0.0.1, and so on) with a randomly
+ chosen exit node. Attempts to do so are always ill-defined, generally
+ prevented by exit policies, and usually in error. This will also
+ help to detect loops in transparent proxy configurations. You can
+ disable this feature by setting "ClientRejectInternalAddresses 0"
+ in your torrc.
+
+
diff --git a/doc/spec/control-spec.txt b/doc/spec/control-spec.txt
index bd327dba7f..f86f94ba6f 100644
--- a/doc/spec/control-spec.txt
+++ b/doc/spec/control-spec.txt
@@ -1083,7 +1083,8 @@
Reason = "MISC" / "RESOLVEFAILED" / "CONNECTREFUSED" /
"EXITPOLICY" / "DESTROY" / "DONE" / "TIMEOUT" /
"NOROUTE" / "HIBERNATING" / "INTERNAL"/ "RESOURCELIMIT" /
- "CONNRESET" / "TORPROTOCOL" / "NOTDIRECTORY" / "END"
+ "CONNRESET" / "TORPROTOCOL" / "NOTDIRECTORY" / "END" /
+ "PRIVATE_ADDR"
The "REASON" field is provided only for FAILED, CLOSED, and DETACHED
events, and only if extended events are enabled (see 3.19). Clients MUST
@@ -1092,7 +1093,10 @@
END (We received a RELAY_END cell from the other side of this
stream.)
+ PRIVATE_ADDR (The client tried to connect to a private address like
+ 127.0.0.1 or 10.0.0.1 over Tor.)
[XXXX document more. -NM]
+
The "REMOTE_REASON" field is provided only when we receive a RELAY_END
cell, and only if extended events are enabled. It contains the actual
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index 65dc76956c..98415e8b63 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -667,8 +667,9 @@ The following options are useful only for clients (that is, if
can leak your location to attackers. (Default: 1)
**VirtualAddrNetwork** __Address__/__bits__::
- When a controller asks for a virtual (unused) address with the MAPADDRESS
- command, Tor picks an unassigned address from this range. (Default:
+ When Tor needs to assign a virtual (unused) address because of a MAPADDRESS
+ command from the controller or the AutpmapHostsOnResolve feature, Tor
+ picks an unassigned address from this range. (Default:
127.192.0.0/10) +
+
When providing proxy server service to a network of computers using a tool
@@ -744,6 +745,12 @@ The following options are useful only for clients (that is, if
192.168.0.1). This option prevents certain browser-based attacks; don't
turn it off unless you know what you're doing. (Default: 1).
+**ClientRejectInternalAddresses** **0**|**1**::
+ If true, Tor does not try to fulfill requests to connect to an internal
+ address (like 127.0.0.1 or 192.168.0.1) __unless a exit node is
+ specifically requested__ (for example, via a .exit hostname, or a
+ controller request). (Default: 1).
+
**DownloadExtraInfo** **0**|**1**::
If true, Tor downloads and caches "extra-info" documents. These documents
contain information about servers other than the information in their
@@ -1300,6 +1307,7 @@ The following options are used for running a testing Tor network.
AuthDirMaxServersPerAddr 0
AuthDirMaxServersPerAuthAddr 0
ClientDNSRejectInternalAddresses 0
+ ClientRejectInternalAddresses 0
ExitPolicyRejectPrivate 0
V3AuthVotingInterval 5 minutes
V3AuthVoteDelay 20 seconds
diff --git a/src/or/config.c b/src/or/config.c
index 1fa8466945..087049cc7e 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -197,6 +197,7 @@ static config_var_t _option_vars[] = {
V(CircuitStreamTimeout, INTERVAL, "0"),
V(CircuitPriorityHalflife, DOUBLE, "-100.0"), /*negative:'Use default'*/
V(ClientDNSRejectInternalAddresses, BOOL,"1"),
+ V(ClientRejectInternalAddresses, BOOL, "1"),
V(ClientOnly, BOOL, "0"),
V(ConsensusParams, STRING, NULL),
V(ConnLimit, UINT, "1000"),
@@ -413,6 +414,7 @@ static config_var_t testing_tor_network_defaults[] = {
V(AuthDirMaxServersPerAddr, UINT, "0"),
V(AuthDirMaxServersPerAuthAddr,UINT, "0"),
V(ClientDNSRejectInternalAddresses, BOOL,"0"),
+ V(ClientRejectInternalAddresses, BOOL, "0"),
V(ExitPolicyRejectPrivate, BOOL, "0"),
V(V3AuthVotingInterval, INTERVAL, "5 minutes"),
V(V3AuthVoteDelay, INTERVAL, "20 seconds"),
diff --git a/src/or/connection.c b/src/or/connection.c
index 6f2eeb278f..874e724b7e 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -1221,7 +1221,8 @@ connection_handle_listener_read(connection_t *conn, int new_type)
}
if (connection_init_accepted_conn(newconn, conn->type) < 0) {
- connection_mark_for_close(newconn);
+ if (! conn->marked_for_close)
+ connection_mark_for_close(newconn);
return 0;
}
return 0;
@@ -1247,9 +1248,11 @@ connection_init_accepted_conn(connection_t *conn, uint8_t listener_type)
conn->state = AP_CONN_STATE_SOCKS_WAIT;
break;
case CONN_TYPE_AP_TRANS_LISTENER:
+ TO_EDGE_CONN(conn)->is_transparent_ap = 1;
conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
return connection_ap_process_transparent(TO_EDGE_CONN(conn));
case CONN_TYPE_AP_NATD_LISTENER:
+ TO_EDGE_CONN(conn)->is_transparent_ap = 1;
conn->state = AP_CONN_STATE_NATD_WAIT;
break;
}
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index c0b177d6e2..bb36f0832a 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -1659,6 +1659,28 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
return -1;
}
+ if (options->ClientRejectInternalAddresses &&
+ !conn->use_begindir && !conn->chosen_exit_name && !circ) {
+ tor_addr_t addr;
+ if (tor_addr_from_str(&addr, socks->address) >= 0 &&
+ tor_addr_is_internal(&addr, 0)) {
+ /* If this is an explicit private address with no chosen exit node,
+ * then we really don't want to try to connect to it. That's
+ * probably an error. */
+ if (conn->is_transparent_ap) {
+ log_warn(LD_NET,
+ "Rejecting request for anonymous connection to private "
+ "address %s on a TransPort or NATDPort. Possible loop "
+ "in your NAT rules?", safe_str_client(socks->address));
+ } else {
+ log_warn(LD_NET,
+ "Rejecting SOCKS request for anonymous connection to "
+ "private address %s", safe_str_client(socks->address));
+ }
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_PRIVATE_ADDR);
+ return -1;
+ }
+ }
if (!conn->use_begindir && !conn->chosen_exit_name && !circ) {
/* see if we can find a suitable enclave exit */
diff --git a/src/or/or.h b/src/or/or.h
index 9672b41584..9bf46e9793 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -592,6 +592,9 @@ typedef enum {
/** This is a connection on the NATD port, and the destination IP:Port was
* either ill-formed or out-of-range. */
#define END_STREAM_REASON_INVALID_NATD_DEST 261
+/** The target address is in a private network (like 127.0.0.1 or 10.0.0.1);
+ * you don't want to do that over a randomly chosen exit */
+#define END_STREAM_REASON_PRIVATE_ADDR 262
/** Bitwise-and this value with endreason to mask out all flags. */
#define END_STREAM_REASON_MASK 511
@@ -1194,6 +1197,10 @@ typedef struct edge_connection_t {
* zero, abandon the associated mapaddress. */
unsigned int chosen_exit_retries:3;
+ /** True iff this is an AP connection that came from a transparent or
+ * NATd connection */
+ unsigned int is_transparent_ap:1;
+
/** If this is a DNSPort connection, this field holds the pending DNS
* request that we're going to try to answer. */
struct evdns_server_request *dns_server_request;
@@ -2913,6 +2920,10 @@ typedef struct {
* Helps avoid some cross-site attacks. */
int ClientDNSRejectInternalAddresses;
+ /** If true, do not accept any requests to connect to internal addresses
+ * over randomly chosen exits. */
+ int ClientRejectInternalAddresses;
+
/** The length of time that we think a consensus should be fresh. */
int V3AuthVotingInterval;
/** The length of time we think it will take to distribute votes. */
diff --git a/src/or/reasons.c b/src/or/reasons.c
index 1401552223..304ea9fcfa 100644
--- a/src/or/reasons.c
+++ b/src/or/reasons.c
@@ -40,6 +40,8 @@ stream_end_reason_to_control_string(int reason)
case END_STREAM_REASON_NET_UNREACHABLE: return "NET_UNREACHABLE";
case END_STREAM_REASON_SOCKSPROTOCOL: return "SOCKS_PROTOCOL";
+ case END_STREAM_REASON_PRIVATE_ADDR: return "PRIVATE_ADDR";
+
default: return NULL;
}
}
@@ -125,6 +127,9 @@ stream_end_reason_to_socks5_response(int reason)
return SOCKS5_NET_UNREACHABLE;
case END_STREAM_REASON_SOCKSPROTOCOL:
return SOCKS5_GENERAL_ERROR;
+ case END_STREAM_REASON_PRIVATE_ADDR:
+ return SOCKS5_GENERAL_ERROR;
+
default:
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Reason for ending (%d) not recognized; "