aboutsummaryrefslogtreecommitdiff
path: root/src/feature/hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/feature/hs')
-rw-r--r--src/feature/hs/hs_config.c56
-rw-r--r--src/feature/hs/hs_config.h8
-rw-r--r--src/feature/hs/hs_service.c3
-rw-r--r--src/feature/hs/hs_service.h5
4 files changed, 72 insertions, 0 deletions
diff --git a/src/feature/hs/hs_config.c b/src/feature/hs/hs_config.c
index 87f6257591..51558f323c 100644
--- a/src/feature/hs/hs_config.c
+++ b/src/feature/hs/hs_config.c
@@ -218,6 +218,9 @@ config_has_invalid_options(const config_line_t *line_,
const char *opts_exclude_v2[] = {
"HiddenServiceExportCircuitID",
+ "HiddenServiceEnableIntroDoSDefense",
+ "HiddenServiceEnableIntroDoSRatePerSec",
+ "HiddenServiceEnableIntroDoSBurstPerSec",
NULL /* End marker. */
};
@@ -276,6 +279,15 @@ config_validate_service(const hs_service_config_t *config)
goto invalid;
}
+ /* DoS validation values. */
+ if (config->has_dos_defense_enabled &&
+ (config->intro_dos_burst_per_sec < config->intro_dos_rate_per_sec)) {
+ log_warn(LD_CONFIG, "Hidden service DoS defenses burst (%" PRIu32 ") can "
+ "not be smaller than the rate value (%" PRIu32 ").",
+ config->intro_dos_burst_per_sec, config->intro_dos_rate_per_sec);
+ goto invalid;
+ }
+
/* Valid. */
return 0;
invalid:
@@ -296,6 +308,8 @@ config_service_v3(const config_line_t *line_,
{
int have_num_ip = 0;
bool export_circuit_id = false; /* just to detect duplicate options */
+ bool dos_enabled = false, dos_rate_per_sec = false;
+ bool dos_burst_per_sec = false;
const char *dup_opt_seen = NULL;
const config_line_t *line;
@@ -334,6 +348,48 @@ config_service_v3(const config_line_t *line_,
export_circuit_id = true;
continue;
}
+ if (!strcasecmp(line->key, "HiddenServiceEnableIntroDoSDefense")) {
+ config->has_dos_defense_enabled =
+ (unsigned int) helper_parse_uint64(line->key, line->value,
+ HS_CONFIG_V3_DOS_DEFENSE_DEFAULT,
+ 1, &ok);
+ if (!ok || dos_enabled) {
+ if (dos_enabled) {
+ dup_opt_seen = line->key;
+ }
+ goto err;
+ }
+ dos_enabled = true;
+ continue;
+ }
+ if (!strcasecmp(line->key, "HiddenServiceEnableIntroDoSRatePerSec")) {
+ config->intro_dos_rate_per_sec =
+ (unsigned int) helper_parse_uint64(line->key, line->value,
+ HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_MIN,
+ HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_MAX, &ok);
+ if (!ok || dos_rate_per_sec) {
+ if (dos_rate_per_sec) {
+ dup_opt_seen = line->key;
+ }
+ goto err;
+ }
+ dos_rate_per_sec = true;
+ continue;
+ }
+ if (!strcasecmp(line->key, "HiddenServiceEnableIntroDoSBurstPerSec")) {
+ config->intro_dos_burst_per_sec =
+ (unsigned int) helper_parse_uint64(line->key, line->value,
+ HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_MIN,
+ HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_MAX, &ok);
+ if (!ok || dos_burst_per_sec) {
+ if (dos_burst_per_sec) {
+ dup_opt_seen = line->key;
+ }
+ goto err;
+ }
+ dos_burst_per_sec = true;
+ continue;
+ }
}
/* We do not load the key material for the service at this stage. This is
diff --git a/src/feature/hs/hs_config.h b/src/feature/hs/hs_config.h
index 040e451f13..249e19309e 100644
--- a/src/feature/hs/hs_config.h
+++ b/src/feature/hs/hs_config.h
@@ -15,6 +15,14 @@
#define HS_CONFIG_MAX_STREAMS_PER_RDV_CIRCUIT 65535
/* Maximum number of intro points per version 3 services. */
#define HS_CONFIG_V3_MAX_INTRO_POINTS 20
+/* Default value for the introduction DoS defenses. */
+#define HS_CONFIG_V3_DOS_DEFENSE_DEFAULT 0
+#define HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_DEFAULT 25
+#define HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_MIN 0
+#define HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_MAX INT32_MAX
+#define HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_DEFAULT 200
+#define HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_MIN 0
+#define HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_MAX INT32_MAX
/* API */
diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c
index 8a4f1efb16..bbfade4d14 100644
--- a/src/feature/hs/hs_service.c
+++ b/src/feature/hs/hs_service.c
@@ -242,6 +242,9 @@ set_service_default_config(hs_service_config_t *c,
c->is_single_onion = 0;
c->dir_group_readable = 0;
c->is_ephemeral = 0;
+ c->has_dos_defense_enabled = HS_CONFIG_V3_DOS_DEFENSE_DEFAULT;
+ c->intro_dos_rate_per_sec = HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_DEFAULT;
+ c->intro_dos_burst_per_sec = HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_DEFAULT;
}
/* From a service configuration object config, clear everything from it
diff --git a/src/feature/hs/hs_service.h b/src/feature/hs/hs_service.h
index 22aa00b2d7..77f6527c20 100644
--- a/src/feature/hs/hs_service.h
+++ b/src/feature/hs/hs_service.h
@@ -241,6 +241,11 @@ typedef struct hs_service_config_t {
/* Does this service export the circuit ID of its clients? */
hs_circuit_id_protocol_t circuit_id_protocol;
+
+ /* DoS defenses. For the ESTABLISH_INTRO cell extension. */
+ unsigned int has_dos_defense_enabled : 1;
+ uint32_t intro_dos_rate_per_sec;
+ uint32_t intro_dos_burst_per_sec;
} hs_service_config_t;
/* Service state. */