Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also .

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also .
base repository: Yawning/tor
base: maint-0.2.6
head repository: Yawning/tor
compare: bug16052a_026
Checking mergeability… Don’t worry, you can still create the pull request.
  • 1 commit
  • 7 files changed
  • 0 comments
  • 1 contributor
Commits on May 20, 2015
When set, this limits the maximum number of simultaneous streams per
rendezvous circuit on the server side of a HS, with further RELAY_BEGIN
cells being silently ignored.

This can be modified via "HiddenServiceMaxStreamsCloseCircuit", which
if set will cause offending rendezvous circuits to be torn down instead.

Addresses part of #16052.
Showing with 94 additions and 8 deletions.
  1. +5 −0 changes/feature16052
  2. +10 −0 doc/tor.1.txt
  3. +19 −8 src/or/circuituse.c
  4. +2 −0 src/or/config.c
  5. +2 −0 src/or/connection_edge.c
  6. +3 −0 src/or/or.h
  7. +53 −0 src/or/rendservice.c
@@ -0,0 +1,5 @@
o Minor features (hidden service):
- Add the new options "HiddenServiceMaxStreams" and
"HiddenServiceMaxStreamsCloseCircuit" to allow hidden services to limit
the maximum number of simultaneous streams per circuit, and optionally
tear down the circuit when the limit is exceeded. Part of ticket 16052.
@@ -2129,6 +2129,16 @@ The following options are used to configure a hidden service.
not an authorization mechanism; it is instead meant to be a mild
inconvenience to port-scanners.) (Default: 0)

[[HiddenServiceMaxStreams]] **HiddenServiceMaxStreams** __N__::
The maximum number of simultaneous streams (connections) per rendezvous
circuit. (Setting this to 0 will allow an unlimited number of simultanous
streams.) (Default: 0)

[[HiddenServiceMaxStreamsCloseCircuit]] **HiddenServiceMaxStreamsCloseCircuit** **0**|**1**::
If set to 1, then exceeding **HiddenServiceMaxStreams** will cause the
offending rendezvous circuit to be torn down, as opposed to stream creation
requests that exceed the limit being silently ignored. (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
@@ -1189,17 +1189,28 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn)

if (CIRCUIT_IS_ORIGIN(circ)) {
origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
int removed = 0;
if (conn == origin_circ->p_streams) {
origin_circ->p_streams = conn->next_stream;
return;
removed = 1;
} else {
for (prevconn = origin_circ->p_streams;
prevconn && prevconn->next_stream && prevconn->next_stream != conn;
prevconn = prevconn->next_stream)
;
if (prevconn && prevconn->next_stream) {
prevconn->next_stream = conn->next_stream;
removed = 1;
}
}

for (prevconn = origin_circ->p_streams;
prevconn && prevconn->next_stream && prevconn->next_stream != conn;
prevconn = prevconn->next_stream)
;
if (prevconn && prevconn->next_stream) {
prevconn->next_stream = conn->next_stream;
if (removed) {
/* If the stream was removed, and it was a rend stream, decrement the
* number of streams on the circuit associated with the rend service.
*/
if (circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED) {
tor_assert(origin_circ->rend_data);
origin_circ->rend_data->nr_streams--;
}
return;
}
} else {
@@ -286,6 +286,8 @@ static config_var_t option_vars_[] = {
VAR("HiddenServiceVersion",LINELIST_S, RendConfigLines, NULL),
VAR("HiddenServiceAuthorizeClient",LINELIST_S,RendConfigLines, NULL),
VAR("HiddenServiceAllowUnknownPorts",LINELIST_S, RendConfigLines, NULL),
VAR("HiddenServiceMaxStreams",LINELIST_S, RendConfigLines, NULL),
VAR("HiddenServiceMaxStreamsCloseCircuit",LINELIST_S, RendConfigLines, NULL),
V(HiddenServiceStatistics, BOOL, "0"),
V(HidServAuth, LINELIST, NULL),
V(CloseHSClientCircuitsImmediatelyOnTimeout, BOOL, "0"),
@@ -2846,6 +2846,8 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
origin_circ->p_streams = n_stream;
assert_circuit_ok(circ);

origin_circ->rend_data->nr_streams++;

connection_exit_connect(n_stream);

/* For path bias: This circuit was used successfully */
@@ -804,6 +804,9 @@ typedef struct rend_data_t {

/** Rendezvous cookie used by both, client and service. */
char rend_cookie[REND_COOKIE_LEN];

/** Number of streams associated with this rendezvous circuit. */
int nr_streams;
} rend_data_t;

/** Time interval for tracking replays of DH public keys received in
@@ -139,6 +139,13 @@ typedef struct rend_service_t {
/** If true, we don't close circuits for making requests to unsupported
* ports. */
int allow_unknown_ports;
/** The maximum number of simultanious streams-per-circuit that are allowed
* to be established, or 0 if no limit is set.
*/
int max_streams_per_circuit;
/** If true, we close circuits that exceed the max_streams_per_circuit
* limit. */
int max_streams_close_circuit;
} rend_service_t;

/** A list of rend_service_t's for services run on this OP.
@@ -489,6 +496,33 @@ rend_config_services(const or_options_t *options, int validate_only)
log_info(LD_CONFIG,
"HiddenServiceDirGroupReadable=%d for %s",
service->dir_group_readable, service->directory);
} else if (!strcasecmp(line->key, "HiddenServiceMaxStreams")) {
service->max_streams_per_circuit = (int)tor_parse_long(line->value,
10, 0, 65535, &ok, NULL);
if (!ok) {
log_warn(LD_CONFIG,
"HiddenServiceMaxStreams should be between 0 and %d, not %s",
65535, line->value);
rend_service_free(service);
return -1;
}
log_info(LD_CONFIG,
"HiddenServiceMaxStreams=%d for %s",
service->max_streams_per_circuit, service->directory);
} else if (!strcasecmp(line->key, "HiddenServiceMaxStreamsCloseCircuit")) {
service->max_streams_close_circuit = (int)tor_parse_long(line->value,
10, 0, 1, &ok, NULL);
if (!ok) {
log_warn(LD_CONFIG,
"HiddenServiceMaxStreamsCloseCircuit should be 0 or 1, not %s",
line->value);
rend_service_free(service);
return -1;
}
log_info(LD_CONFIG,
"HiddenServiceMaxStreamsCloseCircuit=%d for %s",
(int)service->max_streams_close_circuit, service->directory);

} else if (!strcasecmp(line->key, "HiddenServiceAuthorizeClient")) {
/* Parse auth type and comma-separated list of client names and add a
* rend_authorized_client_t for each client to the service's list
@@ -3567,6 +3601,25 @@ rend_service_set_connection_addr_port(edge_connection_t *conn,
serviceid, (unsigned)circ->base_.n_circ_id);
return -2;
}
if (service->max_streams_per_circuit > 0) {
/* Enforce the streams-per-circuit limit, and refuse to provide a
* mapping if this circuit will exceed the limit. */
#define MAX_STREAM_WARN_INTERVAL 600
static struct ratelim_t stream_ratelim =
RATELIM_INIT(MAX_STREAM_WARN_INTERVAL);
if (circ->rend_data->nr_streams >= service->max_streams_per_circuit) {
log_fn_ratelim(&stream_ratelim, LOG_WARN, LD_REND,
"Maximum streams per circuit limit reached on rendezvous "
"circuit %u; %s. Circuit has %d out of %d streams.",
(unsigned)circ->base_.n_circ_id,
service->max_streams_close_circuit ?
"closing circuit" :
"ignoring open stream request",
circ->rend_data->nr_streams,
service->max_streams_per_circuit);
return service->max_streams_close_circuit ? -2 : -1;
}
}
matching_ports = smartlist_new();
SMARTLIST_FOREACH(service->ports, rend_service_port_config_t *, p,
{

No commit comments for this range