diff options
author | teor (Tim Wilson-Brown) <teor2345@gmail.com> | 2016-07-14 14:04:02 +1000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2016-09-13 10:10:54 -0400 |
commit | b560f852f220f5630f6bf5a300d15b40c9c235cf (patch) | |
tree | 8f245dab0172516b01f5617adb0c856ed991a0f2 /src/or/config.c | |
parent | b494ccc3c91423c4280c1fc003b5117d9aae54c0 (diff) | |
download | tor-b560f852f220f5630f6bf5a300d15b40c9c235cf.tar.gz tor-b560f852f220f5630f6bf5a300d15b40c9c235cf.zip |
Implement Prop #260: Single Onion Services
Add experimental OnionServiceSingleHopMode and
OnionServiceNonAnonymousMode options. When both are set to 1, every
hidden service on a tor instance becomes a non-anonymous Single Onion
Service. Single Onions make one-hop (direct) connections to their
introduction and renzedvous points. One-hop circuits make Single Onion
servers easily locatable, but clients remain location-anonymous.
This is compatible with the existing hidden service implementation, and
works on the current tor network without any changes to older relays or
clients.
Implements proposal #260, completes ticket #17178. Patch by teor & asn.
squash! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! Implement Prop #260: Single Onion Services
Redesign single onion service poisoning.
When in OnionServiceSingleHopMode, each hidden service key is poisoned
(marked as non-anonymous) on creation by creating a poison file in the
hidden service directory.
Existing keys are considered non-anonymous if this file exists, and
anonymous if it does not.
Tor refuses to launch in OnionServiceSingleHopMode if any existing keys
are anonymous. Similarly, it refuses to launch in anonymous client mode
if any existing keys are non-anonymous.
Rewrite the unit tests to match and be more comprehensive.
Adds a bonus unit test for rend_service_load_all_keys().
Diffstat (limited to 'src/or/config.c')
-rw-r--r-- | src/or/config.c | 160 |
1 files changed, 137 insertions, 23 deletions
diff --git a/src/or/config.c b/src/or/config.c index 136958c6aa..f7f1f571ce 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -18,6 +18,7 @@ #include "circuitlist.h" #include "circuitmux.h" #include "circuitmux_ewma.h" +#include "circuitstats.h" #include "config.h" #include "connection.h" #include "connection_edge.h" @@ -297,6 +298,8 @@ static config_var_t option_vars_[] = { V(HidServAuth, LINELIST, NULL), V(CloseHSClientCircuitsImmediatelyOnTimeout, BOOL, "0"), V(CloseHSServiceRendCircuitsImmediatelyOnTimeout, BOOL, "0"), + V(OnionServiceSingleHopMode, BOOL, "0"), + V(OnionServiceNonAnonymousMode,BOOL, "0"), V(HTTPProxy, STRING, NULL), V(HTTPProxyAuthenticator, STRING, NULL), V(HTTPSProxy, STRING, NULL), @@ -1558,10 +1561,10 @@ options_act(const or_options_t *old_options) if (consider_adding_dir_servers(options, old_options) < 0) return -1; -#ifdef NON_ANONYMOUS_MODE_ENABLED - log_warn(LD_GENERAL, "This copy of Tor was compiled to run in a " - "non-anonymous mode. It will provide NO ANONYMITY."); -#endif + if (rend_non_anonymous_mode_enabled(options)) { + log_warn(LD_GENERAL, "This copy of Tor was compiled or configured to run " + "in a non-anonymous mode. It will provide NO ANONYMITY."); + } #ifdef ENABLE_TOR2WEB_MODE /* LCOV_EXCL_START */ @@ -1723,8 +1726,27 @@ options_act(const or_options_t *old_options) monitor_owning_controller_process(options->OwningControllerProcess); + /* We must create new keys after we poison the directories, because our + * poisoning code checks for existing keys, and refuses to modify their + * directories. */ + + /* If we use the insecure OnionServiceSingleHopMode, make sure we poison any + new hidden service directories, so that we never accidentally launch the + non-anonymous hidden services thinking they are anonymous. */ + if (running_tor && rend_service_allow_non_anonymous_connection(options)) { + if (options->RendConfigLines && !num_rend_services()) { + log_warn(LD_BUG,"Error: hidden services configured, but not parsed."); + return -1; + } + if (rend_service_poison_new_single_onion_dirs(NULL) < 0) { + log_warn(LD_GENERAL,"Failed to mark new hidden services as Single " + "Onion."); + return -1; + } + } + /* reload keys as needed for rendezvous services. */ - if (rend_service_load_all_keys()<0) { + if (rend_service_load_all_keys(NULL)<0) { log_warn(LD_GENERAL,"Error loading rendezvous service keys"); return -1; } @@ -2796,6 +2818,88 @@ warn_about_relative_paths(or_options_t *options) } } +/* Validate options related to OnionServiceSingleHopMode. + * Modifies some options that are incompatible with OnionServiceSingleHopMode. + * On failure returns -1, and sets *msg to an error string. + * Returns 0 on success. */ +STATIC int +options_validate_single_onion(or_options_t *options, char **msg) +{ + /* You must set OnionServiceNonAnonymousMode to 1 to use + * OnionServiceSingleHopMode */ + if (options->OnionServiceSingleHopMode && + !rend_service_non_anonymous_mode_enabled(options)) { + REJECT("OnionServiceSingleHopMode does not provide any server anonymity. " + "It must be used with OnionServiceNonAnonymousMode set to 1."); + } + + /* If you have OnionServiceNonAnonymousMode set, you must use + * OnionServiceSingleHopMode. */ + if (rend_service_non_anonymous_mode_enabled(options) && + !options->OnionServiceSingleHopMode) { + REJECT("OnionServiceNonAnonymousMode does not provide any server " + "anonymity. It must be used with OnionServiceSingleHopMode set to " + "1."); + } + + /* If you run an anonymous client with an active Single Onion service, the + * client loses anonymity. */ + const int client_port_set = (options->SocksPort_set || + options->TransPort_set || + options->NATDPort_set || + options->DNSPort_set); + if (options->OnionServiceSingleHopMode && client_port_set && + !options->Tor2webMode) { + REJECT("OnionServiceSingleHopMode is incompatible with using Tor as an " + "anonymous client. Please set Socks/Trans/NATD/DNSPort to 0, or " + "OnionServiceSingleHopMode to 0, or use the non-anonymous " + "Tor2webMode."); + } + + /* If you run a hidden service in non-anonymous mode, the hidden service + * loses anonymity, even if SOCKSPort / Tor2web mode isn't used. */ + if (!options->OnionServiceSingleHopMode && options->RendConfigLines + && options->Tor2webMode) { + REJECT("Non-anonymous (Tor2web) mode is incompatible with using Tor as a " + "hidden service. Please remove all HiddenServiceDir lines, or use " + "a version of tor compiled without --enable-tor2web-mode, or use " + "the non-anonymous OnionServiceSingleHopMode."); + } + + if (options->OnionServiceSingleHopMode + && options->UseEntryGuards) { + /* Single Onion services do not (and should not) use entry guards + * in any meaningful way. Further, Single Onions causes the hidden + * service code to do things which break the path bias + * detector, and it's far easier to turn off entry guards (and + * thus the path bias detector with it) than to figure out how to + * make a piece of code which cannot possibly help Single Onions, + * compatible with OnionServiceSingleHopMode. + */ + log_notice(LD_CONFIG, + "OnionServiceSingleHopMode is enabled; disabling " + "UseEntryGuards."); + options->UseEntryGuards = 0; + } + + /* Check if existing hidden service keys were created with a different + * setting of OnionServiceNonAnonymousMode, and refuse to launch if they + * have. We'll poison new keys in options_act() just before we create them. + */ + if (rend_service_list_verify_single_onion_poison(NULL, options) < 0) { + log_warn(LD_GENERAL, "We are configured with OnionServiceSingleHopMode " + "%d, but one or more hidden service keys were created in %s " + "mode. This is not allowed.", + rend_service_non_anonymous_mode_enabled(options) ? 1 : 0, + rend_service_non_anonymous_mode_enabled(options) ? + "an anonymous" : "a non-anonymous" + ); + return -1; + } + + return 0; +} + /** Return 0 if every setting in <b>options</b> is reasonable, is a * permissible transition from <b>old_options</b>, and none of the * testing-only settings differ from <b>default_options</b> unless in @@ -3291,25 +3395,11 @@ options_validate(or_options_t *old_options, or_options_t *options, options->PredictedPortsRelevanceTime = MAX_PREDICTED_CIRCS_RELEVANCE; } -#ifdef ENABLE_TOR2WEB_MODE - if (options->Tor2webMode && options->LearnCircuitBuildTimeout) { - /* LearnCircuitBuildTimeout and Tor2webMode are incompatible in - * two ways: - * - * - LearnCircuitBuildTimeout results in a low CBT, which - * Tor2webMode's use of one-hop rendezvous circuits lowers - * much further, producing *far* too many timeouts. - * - * - The adaptive CBT code does not update its timeout estimate - * using build times for single-hop circuits. - * - * If we fix both of these issues someday, we should test - * Tor2webMode with LearnCircuitBuildTimeout on again. */ - log_notice(LD_CONFIG,"Tor2webMode is enabled; turning " - "LearnCircuitBuildTimeout off."); - options->LearnCircuitBuildTimeout = 0; - } + /* Check the Single Onion Service options */ + if (options_validate_single_onion(options, msg) < 0) + return -1; +#ifdef ENABLE_TOR2WEB_MODE if (options->Tor2webMode && options->UseEntryGuards) { /* tor2web mode clients do not (and should not) use entry guards * in any meaningful way. Further, tor2web mode causes the hidden @@ -3353,6 +3443,17 @@ options_validate(or_options_t *old_options, or_options_t *options, return -1; } + /* OnionServiceSingleHopMode: one hop between the onion service server and + * intro and rendezvous points */ + if (options->OnionServiceSingleHopMode) { + log_warn(LD_CONFIG, + "OnionServiceSingleHopMode is set. Every hidden service on this " + "tor instance is NON-ANONYMOUS. If OnionServiceSingleHopMode is " + "disabled, Tor will refuse to launch hidden services from the " + "same directories, to protect against config errors. This " + "setting is for experimental use only."); + } + if (!options->LearnCircuitBuildTimeout && options->CircuitBuildTimeout && options->CircuitBuildTimeout < RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT) { log_warn(LD_CONFIG, @@ -4295,6 +4396,19 @@ options_transition_allowed(const or_options_t *old, return -1; } + if (old->OnionServiceSingleHopMode != new_val->OnionServiceSingleHopMode) { + *msg = tor_strdup("While Tor is running, changing " + "OnionServiceSingleHopMode is not allowed."); + return -1; + } + + if (old->OnionServiceNonAnonymousMode != + new_val->OnionServiceNonAnonymousMode) { + *msg = tor_strdup("While Tor is running, changing " + "OnionServiceNonAnonymousMode is not allowed."); + return -1; + } + if (old->DisableDebuggerAttachment && !new_val->DisableDebuggerAttachment) { *msg = tor_strdup("While Tor is running, disabling " |