mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Add an option to limit the number of non-open client circuits.
This is mainly meant as a way to keep clients from accidentally DOSing themselves by (e.g.) enabling IsolateDestAddr or IsolateDestPort on a port that they use for HTTP.
This commit is contained in:
@@ -288,6 +288,27 @@ circuit_get_best(const edge_connection_t *conn,
|
||||
return best;
|
||||
}
|
||||
|
||||
/** Return the number of not-yet-open general-purpose origin circuits. */
|
||||
static int
|
||||
count_pending_general_client_circuits(void)
|
||||
{
|
||||
const circuit_t *circ;
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (circ = global_circuitlist; circ; circ = circ->next) {
|
||||
if (circ->marked_for_close ||
|
||||
circ->state == CIRCUIT_STATE_OPEN ||
|
||||
circ->purpose != CIRCUIT_PURPOSE_C_GENERAL ||
|
||||
!CIRCUIT_IS_ORIGIN(circ))
|
||||
continue;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/** Check whether, according to the policies in <b>options</b>, the
|
||||
* circuit <b>circ</b> makes sense. */
|
||||
@@ -1347,6 +1368,20 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
|
||||
if (!circ) {
|
||||
extend_info_t *extend_info=NULL;
|
||||
uint8_t new_circ_purpose;
|
||||
const int n_pending = count_pending_general_client_circuits();
|
||||
|
||||
if (n_pending >= options->MaxClientCircuitsPending) {
|
||||
static ratelim_t delay_limit = RATELIM_INIT(10*60);
|
||||
char *m;
|
||||
if ((m = rate_limit_log(&delay_limit, approx_time()))) {
|
||||
log_notice(LD_APP, "We'd like to launch a circuit to handle a "
|
||||
"connection, but we already have %d general-purpose client "
|
||||
"circuits pending. Waiting until some finish.",
|
||||
n_pending);
|
||||
tor_free(m);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
|
||||
/* need to pick an intro point */
|
||||
|
||||
@@ -315,6 +315,7 @@ static config_var_t _option_vars[] = {
|
||||
VAR("MapAddress", LINELIST, AddressMap, NULL),
|
||||
V(MaxAdvertisedBandwidth, MEMUNIT, "1 GB"),
|
||||
V(MaxCircuitDirtiness, INTERVAL, "10 minutes"),
|
||||
V(MaxClientCircuitsPending, UINT, "32"),
|
||||
V(MaxOnionsPending, UINT, "100"),
|
||||
OBSOLETE("MonthlyAccountingStart"),
|
||||
V(MyFamily, STRING, NULL),
|
||||
@@ -3215,6 +3216,15 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (options->MaxClientCircuitsPending <= 0 ||
|
||||
options->MaxClientCircuitsPending > MAX_MAX_CLIENT_CIRCUITS_PENDING) {
|
||||
tor_asprintf(msg,
|
||||
"MaxClientCircuitsPending must be between 1 and %d, but "
|
||||
"was set to %d", MAX_MAX_CLIENT_CIRCUITS_PENDING,
|
||||
options->MaxClientCircuitsPending);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (validate_ports_csv(options->FirewallPorts, "FirewallPorts", msg) < 0)
|
||||
return -1;
|
||||
|
||||
|
||||
@@ -3230,6 +3230,11 @@ typedef struct {
|
||||
/** Should that file be group-readable? */
|
||||
int ControlPortFileGroupReadable;
|
||||
|
||||
#define MAX_MAX_CLIENT_CIRCUITS_PENDING 1024
|
||||
/** Maximum number of non-open general-purpose origin circuits to allow at
|
||||
* once. */
|
||||
int MaxClientCircuitsPending;
|
||||
|
||||
} or_options_t;
|
||||
|
||||
/** Persistent state for an onion router, as saved to disk. */
|
||||
|
||||
Reference in New Issue
Block a user