|
@@ -147,6 +147,13 @@ typedef struct rend_service_t {
|
|
|
|
|
|
* ports. */
|
|
|
int allow_unknown_ports;
|
|
|
+
|
|
|
+ * to be established, or 0 if no limit is set.
|
|
|
+ */
|
|
|
+ int max_streams_per_circuit;
|
|
|
+
|
|
|
+ * limit. */
|
|
|
+ int max_streams_close_circuit;
|
|
|
} rend_service_t;
|
|
|
|
|
|
|
|
@@ -539,6 +546,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")) {
|
|
|
|
|
|
* rend_authorized_client_t for each client to the service's list
|
|
@@ -3795,6 +3829,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) {
|
|
|
+
|
|
|
+ * 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,
|
|
|
{
|