aboutsummaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2011-01-25 20:39:44 -0500
committerNick Mathewson <nickm@torproject.org>2011-01-25 20:39:44 -0500
commit411ec3c0f8cd4786233a3bc274cb2b766d4bfe7c (patch)
treef48f77c8f33b73f9d386c87026c87b0d1a2055d1 /src/or
parent85da676108f0de765301f961bc58aebd139a5564 (diff)
downloadtor-411ec3c0f8cd4786233a3bc274cb2b766d4bfe7c.tar.gz
tor-411ec3c0f8cd4786233a3bc274cb2b766d4bfe7c.zip
Add client code to detect attempts to connect to 127.0.0.1 etc
We detect and reject said attempts if there is no chosen exit node or circuit: connecting to a private addr via a randomly chosen exit node will usually fail (if all exits reject private addresses), is always ill-defined (you're not asking for any particular host or service), and usually an error (you've configured all requests to go over Tor when you really wanted to configure all _remote_ requests to go over Tor). This can also help detect forwarding loop requests. Found as part of bug2279.
Diffstat (limited to 'src/or')
-rw-r--r--src/or/connection.c2
-rw-r--r--src/or/connection_edge.c21
-rw-r--r--src/or/or.h7
-rw-r--r--src/or/reasons.c5
4 files changed, 35 insertions, 0 deletions
diff --git a/src/or/connection.c b/src/or/connection.c
index 55a9557ef6..fd30ac8cb6 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -1205,9 +1205,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 73ed9fb5c3..a85943f69f 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -1659,6 +1659,27 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
return -1;
}
+ if (!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 22c8498b66..a3ec71a927 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -583,6 +583,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
@@ -1170,6 +1173,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;
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; "