Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions changes/anyone-hosts-autoupdate
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
o New features (anyone-hosts auto-update):
- The client now automatically fetches a fresh copy of the anyone_hosts
DNS mapping file from the .anyone DNS service nodes when new directory
information arrives and/or on a periodic schedule. New configuration
options AnyoneHostsUpdate, AnyoneHostsURL, AnyoneHostsUpdateInterval,
AnyoneHostsFetchPath, AnyoneHostsUpdateTrigger, and
AnyoneHostsSignatureRequirement control the behaviour.

o Minor features (documentation):
- DNSMappingFileMaxSize now documents bit-based units (KBits, MBits,
GBits, TBits) in the man page, consistent with other MEMUNIT options.
- Clarified that DNSMappingFileMaxSize only limits loading an existing
file; a missing file is always recreated with the default mapping.
42 changes: 40 additions & 2 deletions doc/man/anon.1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1222,10 +1222,48 @@ The following options are useful only for clients (that is, if
addresses/ports. See <<SocksPort,SocksPort>> for an explanation of isolation
flags. (Default: 0)

[[DNSMappingFileMaxSize]] **DNSMappingFileMaxSize** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**::
[[DNSMappingFileMaxSize]] **DNSMappingFileMaxSize** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**TBytes**|**KBits**|**MBits**|**GBits**|**TBits**::
The maximum size allowed for the `anyone_hosts` DNS mapping file in the
data directory. If the file exceeds this size, it is rejected. Set this
option to 0 to disable the size limit. (Default: 10 MB)
option to 0 to disable the size limit. This limit applies only when
reading or accepting an existing file; if the file is absent, a new
default file is created regardless of this setting. (Default: 10 MB)

[[AnyoneHostsUpdate]] **AnyoneHostsUpdate** **0**|**1**::
If 1, the client will automatically attempt to fetch a fresh copy of
the `anyone_hosts` DNS mapping file from the .anyone DNS service nodes
when new directory information arrives and/or on a periodic schedule
(see <<AnyoneHostsUpdateTrigger,AnyoneHostsUpdateTrigger>>).
(Default: 1)

[[AnyoneHostsURL]] **AnyoneHostsURL** __address__::
A .anyone onion address of a DNS service node to try when fetching the
`anyone_hosts` file. This option may be specified multiple times; the
addresses are tried in order before the built-in defaults extracted from
the current `anyone_hosts` file and `DEFAULT_ANON_DNS_MAPPING`.
(Default: none)

[[AnyoneHostsUpdateInterval]] **AnyoneHostsUpdateInterval** __N__ **seconds**|**minutes**|**hours**|**days**|**weeks**::
How often to attempt fetching a fresh `anyone_hosts` file.
(Default: 12 hours)

[[AnyoneHostsFetchPath]] **AnyoneHostsFetchPath** __path__::
The HTTP resource path to request from the DNS service node.
(Default: /tld/anyone)

[[AnyoneHostsUpdateTrigger]] **AnyoneHostsUpdateTrigger** **consensus**|**periodic**|**both**::
Controls what events trigger an `anyone_hosts` fetch attempt. **consensus**
triggers a fetch only when a new network consensus is successfully loaded.
**periodic** triggers only via the periodic scheduler. **both** uses
either trigger. (Default: both)

[[AnyoneHostsSignatureRequirement]] **AnyoneHostsSignatureRequirement** **strict**|**verify**|**any**::
Controls how strictly the signature on a fetched `anyone_hosts` file is
checked. **strict** requires a valid signature from a trusted DNS signer;
unsigned or untrusted files are discarded. **verify** accepts unsigned
files but rejects files whose signature fails verification. **any** accepts
all files that parse without error, regardless of signature status.
(Default: strict)

[[DownloadExtraInfo]] **DownloadExtraInfo** **0**|**1**::
If true, Tor downloads and caches "extra-info" documents. These documents
Expand Down
30 changes: 30 additions & 0 deletions src/app/config/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,12 @@ static const config_var_t option_vars_[] = {
V(AlternateBridgeAuthority, LINELIST, NULL),
V(AlternateDirAuthority, LINELIST, NULL),
OBSOLETE("AlternateHSAuthority"),
V(AnyoneHostsFetchPath, STRING, "/tld/anyone"),
V(AnyoneHostsSignatureRequirement, STRING, "strict"),
V(AnyoneHostsUpdate, BOOL, "1"),
V(AnyoneHostsUpdateInterval, INTERVAL, "12 hours"),
V(AnyoneHostsUpdateTrigger, STRING, "both"),
V(AnyoneHostsURL, LINELIST, NULL),
V(AssumeReachable, BOOL, "0"),
V(AssumeReachableIPv6, AUTOBOOL, "auto"),
OBSOLETE("AuthDirBadDir"),
Expand Down Expand Up @@ -4062,6 +4068,30 @@ options_validate_cb(const void *old_options_, void *options_, char **msg)
return -1;
}

if (options->AnyoneHostsUpdateTrigger) {
const char *t = options->AnyoneHostsUpdateTrigger;
if (strcmp(t, "consensus") && strcmp(t, "periodic") && strcmp(t, "both")) {
REJECT("AnyoneHostsUpdateTrigger must be \"consensus\", "
"\"periodic\", or \"both\".");
}
}
if (options->AnyoneHostsSignatureRequirement) {
const char *s = options->AnyoneHostsSignatureRequirement;
if (strcmp(s, "strict") && strcmp(s, "verify") && strcmp(s, "any")) {
REJECT("AnyoneHostsSignatureRequirement must be \"strict\", "
"\"verify\", or \"any\".");
}
}
Comment thread
jim-toth marked this conversation as resolved.
if (options->AnyoneHostsUpdateInterval < 1) {
REJECT("AnyoneHostsUpdateInterval must be positive.");
}
if (!options->AnyoneHostsFetchPath ||
!strlen(options->AnyoneHostsFetchPath) ||
options->AnyoneHostsFetchPath[0] != '/') {
REJECT("AnyoneHostsFetchPath must be a non-empty absolute path "
"beginning with '/'.");
}
Comment thread
Copilot marked this conversation as resolved.
Comment on lines +4101 to +4106

return 0;
}

Expand Down
15 changes: 15 additions & 0 deletions src/app/config/or_options_st.h
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,21 @@ struct or_options_t {
/** Maximum size in bytes allowed for the anyone_hosts DNS mapping file.
* A value of 0 disables the size limit. */
uint64_t DNSMappingFileMaxSize;
/** If true, automatically update the anyone_hosts DNS mapping file when
* new directory information arrives or on a periodic schedule. */
int AnyoneHostsUpdate;
/** List of .anyone service addresses to try when fetching the
* anyone_hosts file. Tried in order before built-in defaults. */
struct config_line_t *AnyoneHostsURL;
/** How often (in seconds) to check for a new anyone_hosts file. */
int AnyoneHostsUpdateInterval;
/** HTTP resource path on the DNS service to fetch. */
char *AnyoneHostsFetchPath;
/** When to trigger an update: "consensus", "periodic", or "both". */
char *AnyoneHostsUpdateTrigger;
/** Signature acceptance policy: "strict" (valid sig only), "verify"
* (valid sig or unsigned), or "any" (accept unless parse error). */
char *AnyoneHostsSignatureRequirement;

/** If true, do not accept any requests to connect to internal addresses
* over randomly chosen exits. */
Expand Down
17 changes: 17 additions & 0 deletions src/core/mainloop/mainloop.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
#include "core/or/connection_or.h"
#include "core/or/dos.h"
#include "core/or/status.h"
#include "feature/anyone/anyone_hosts_update.h"
#include "feature/client/addressmap.h"
#include "feature/client/bridges.h"
#include "feature/client/dnsserv.h"
Expand Down Expand Up @@ -1381,6 +1382,7 @@ CALLBACK(write_stats_file);
CALLBACK(control_per_second_events);
CALLBACK(second_elapsed);
CALLBACK(manage_vglite);
CALLBACK(update_anyone_hosts);

#undef CALLBACK

Expand All @@ -1406,6 +1408,9 @@ STATIC periodic_event_item_t mainloop_periodic_events[] = {
/* Update vanguards-lite once per hour, if we have networking */
CALLBACK(manage_vglite, NET_PARTICIPANT, FL(NEED_NET)),

/* Periodically update the anyone_hosts DNS mapping file. */
CALLBACK(update_anyone_hosts, NET_PARTICIPANT, FL(NEED_NET)),

Comment thread
jim-toth marked this conversation as resolved.
/* XXXX Do we have a reason to do this on a callback? Does it do any good at
* all? For now, if we're dormant, we can let our listeners decay. */
CALLBACK(retry_listeners, NET_PARTICIPANT, FL(NEED_NET)),
Expand Down Expand Up @@ -1553,6 +1558,8 @@ initialize_periodic_events(void)
NAMED_CALLBACK(launch_descriptor_fetches);
NAMED_CALLBACK(check_dns_honesty);
NAMED_CALLBACK(save_state);

anyone_hosts_update_init();
}

STATIC void
Expand Down Expand Up @@ -1691,6 +1698,16 @@ manage_vglite_callback(time_t now, const or_options_t *options)
return VANGUARDS_LITE_INTERVAL;
}

/** Periodic-event callback: attempt to update the anyone_hosts DNS mapping
* file, and return the number of seconds until the next run
* (AnyoneHostsUpdateInterval).
*/
static int
update_anyone_hosts_callback(time_t now, const or_options_t *options)
{
return anyone_hosts_update_callback(now, options);
Comment thread
jim-toth marked this conversation as resolved.
}
Comment thread
Copilot marked this conversation as resolved.

/** Perform regular maintenance tasks. This function gets run once per
* second.
*/
Expand Down
Loading