summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changes/bug140846
-rw-r--r--doc/tor.1.txt6
-rw-r--r--src/or/config.c1
-rw-r--r--src/or/connection_edge.c9
-rw-r--r--src/or/rendservice.c26
5 files changed, 43 insertions, 5 deletions
diff --git a/changes/bug14084 b/changes/bug14084
new file mode 100644
index 0000000000..c7f053e16e
--- /dev/null
+++ b/changes/bug14084
@@ -0,0 +1,6 @@
+ o Minor features:
+ - New option "HiddenServiceAllowUnknownPorts" to allow hidden
+ services to disable the anti-scanning feature introduced in
+ 0.2.6.2-alpha. With this option not set, a connection to an
+ unlisted port closes the circuit. With this option set, only a
+ RELAY_DONE cell is sent. Closes ticket #14084. \ No newline at end of file
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index a38b7dccca..5302b33bd1 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -2093,6 +2093,12 @@ The following options are used to configure a hidden service.
found in the hostname file. Clients need to put this authorization data in
their configuration file using **HidServAuth**.
+[[HiddenServiceAllowUnknownPorts]] **HiddenServiceAllowUnknownPorts** **0**|**1**::
+ If set to 1, then connections to unrecognized ports do not cause the
+ current hidden service to close rendezvous circuits. (Setting this to 0 is
+ not an authorization mechanism; it is instead meant to be a mild
+ inconvenience to port-scanners.) (Default: 0)
+
[[RendPostPeriod]] **RendPostPeriod** __N__ **seconds**|**minutes**|**hours**|**days**|**weeks**::
Every time the specified period elapses, Tor uploads any rendezvous
service descriptors to the directory servers. This information is also
diff --git a/src/or/config.c b/src/or/config.c
index e747adde6b..baff4198ee 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -281,6 +281,7 @@ static config_var_t option_vars_[] = {
VAR("HiddenServicePort", LINELIST_S, RendConfigLines, NULL),
VAR("HiddenServiceVersion",LINELIST_S, RendConfigLines, NULL),
VAR("HiddenServiceAuthorizeClient",LINELIST_S,RendConfigLines, NULL),
+ VAR("HiddenServiceAllowUnknownPorts",LINELIST_S, RendConfigLines, NULL),
V(HiddenServiceStatistics, BOOL, "0"),
V(HidServAuth, LINELIST, NULL),
V(CloseHSClientCircuitsImmediatelyOnTimeout, BOOL, "0"),
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index d1ad56d553..f541249992 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -2788,7 +2788,9 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
n_stream->rend_data = rend_data_dup(origin_circ->rend_data);
tor_assert(connection_edge_is_rendezvous_stream(n_stream));
assert_circuit_ok(circ);
- if (rend_service_set_connection_addr_port(n_stream, origin_circ) < 0) {
+
+ const int r = rend_service_set_connection_addr_port(n_stream, origin_circ);
+ if (r < 0) {
log_info(LD_REND,"Didn't find rendezvous service (port %d)",
n_stream->base_.port);
/* Send back reason DONE because we want to make hidden service port
@@ -2807,7 +2809,10 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
* scanning the hidden service ports. Note that this mitigates port
* scanning by adding more work on the attacker side to successfully
* scan but does not fully solve it. */
- return END_CIRC_AT_ORIGIN;
+ if (r < -1)
+ return END_CIRC_AT_ORIGIN;
+ else
+ return 0;
}
assert_circuit_ok(circ);
log_debug(LD_REND,"Finished assigning addr/port");
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index ca9b380d7d..5a12d074ac 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -129,6 +129,9 @@ typedef struct rend_service_t {
* when they do, this keeps us from launching multiple simultaneous attempts
* to connect to the same rend point. */
replaycache_t *accepted_intro_dh_parts;
+ /** If true, we don't close circuits for making requests to unsupported
+ * ports. */
+ int allow_unknown_ports;
} rend_service_t;
/** A list of rend_service_t's for services run on this OP.
@@ -397,6 +400,19 @@ rend_config_services(const or_options_t *options, int validate_only)
return -1;
}
smartlist_add(service->ports, portcfg);
+ } else if (!strcasecmp(line->key, "HiddenServiceAllowUnknownPorts")) {
+ service->allow_unknown_ports = (int)tor_parse_long(line->value,
+ 10, 0, 1, &ok, NULL);
+ if (!ok) {
+ log_warn(LD_CONFIG,
+ "HiddenServiceAllowUnknownPorts should be 0 or 1, not %s",
+ line->value);
+ rend_service_free(service);
+ return -1;
+ }
+ log_info(LD_CONFIG,
+ "HiddenServiceAllowUnknownPorts=%d for %s",
+ (int)service->allow_unknown_ports, service->directory);
} else if (!strcasecmp(line->key,
"HiddenServiceDirGroupReadable")) {
service->dir_group_readable = (int)tor_parse_long(line->value,
@@ -3388,7 +3404,8 @@ rend_service_dump_stats(int severity)
/** Given <b>conn</b>, a rendezvous exit stream, look up the hidden service for
* 'circ', and look up the port and address based on conn-\>port.
- * Assign the actual conn-\>addr and conn-\>port. Return -1 if failure,
+ * Assign the actual conn-\>addr and conn-\>port. Return -2 on failure
+ * for which the circuit should be closed, -1 on other failure,
* or 0 for success.
*/
int
@@ -3411,7 +3428,7 @@ rend_service_set_connection_addr_port(edge_connection_t *conn,
log_warn(LD_REND, "Couldn't find any service associated with pk %s on "
"rendezvous circuit %u; closing.",
serviceid, (unsigned)circ->base_.n_circ_id);
- return -1;
+ return -2;
}
matching_ports = smartlist_new();
SMARTLIST_FOREACH(service->ports, rend_service_port_config_t *, p,
@@ -3429,6 +3446,9 @@ rend_service_set_connection_addr_port(edge_connection_t *conn,
}
log_info(LD_REND, "No virtual port mapping exists for port %d on service %s",
conn->base_.port,serviceid);
- return -1;
+ if (service->allow_unknown_ports)
+ return -1;
+ else
+ return -2;
}