commit 5419fd5d9f54bda86549b47e096d4f88e1b58655 Author: David Goulet dgoulet@torproject.org Date: Tue Jun 25 10:26:57 2019 -0400
hs-v3: Implement torrc DoS defenses options
Signed-off-by: David Goulet dgoulet@torproject.org --- src/app/config/config.c | 5 ++++ src/feature/hs/hs_config.c | 56 +++++++++++++++++++++++++++++++++++++++++++++ src/feature/hs/hs_config.h | 8 +++++++ src/feature/hs/hs_service.c | 3 +++ src/feature/hs/hs_service.h | 5 ++++ 5 files changed, 77 insertions(+)
diff --git a/src/app/config/config.c b/src/app/config/config.c index 8da1e2acd..f72aacd8a 100644 --- a/src/app/config/config.c +++ b/src/app/config/config.c @@ -507,6 +507,11 @@ static config_var_t option_vars_[] = { VAR("HiddenServiceMaxStreamsCloseCircuit",LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceNumIntroductionPoints", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceExportCircuitID", LINELIST_S, RendConfigLines, NULL), + VAR("HiddenServiceEnableIntroDoSDefense", LINELIST_S, RendConfigLines, NULL), + VAR("HiddenServiceEnableIntroDoSRatePerSec", + LINELIST_S, RendConfigLines, NULL), + VAR("HiddenServiceEnableIntroDoSBurstPerSec", + LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceStatistics", BOOL, HiddenServiceStatistics_option, "1"), V(HidServAuth, LINELIST, NULL), V(ClientOnionAuthDir, FILENAME, NULL), diff --git a/src/feature/hs/hs_config.c b/src/feature/hs/hs_config.c index 87f625759..51558f323 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 040e451f1..249e19309 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 8a4f1efb1..bbfade4d1 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 22aa00b2d..77f6527c2 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. */
tor-commits@lists.torproject.org