|
Tor 0.5.0.0-alpha-dev
|
Implements a local cache for DNS results for Tor servers. This is implemented as a wrapper around Adam Langley's eventdns.c code. (We can't just use gethostbyname() and friends because we really need to be nonblocking.) More...
#include "core/or/or.h"#include "app/config/config.h"#include "core/mainloop/connection.h"#include "core/mainloop/mainloop.h"#include "core/mainloop/netstatus.h"#include "core/or/circuitlist.h"#include "core/or/circuituse.h"#include "core/or/connection_edge.h"#include "core/or/policies.h"#include "core/or/relay.h"#include "feature/control/control_events.h"#include "feature/relay/dns.h"#include "feature/nodelist/networkstatus.h"#include "feature/relay/router.h"#include "feature/relay/routermode.h"#include "feature/stats/rephist.h"#include "lib/crypt_ops/crypto_rand.h"#include "lib/evloop/compat_libevent.h"#include "lib/sandbox/sandbox.h"#include "core/or/edge_connection_st.h"#include "core/or/or_circuit_st.h"#include "core/or/conflux_util.h"#include "ht.h"#include <event2/event.h>#include <event2/dns.h>Go to the source code of this file.
Macros | |
| #define | DNS_PRIVATE |
| #define | RESOLVE_MAX_TIMEOUT 300 |
| #define | RESOLVED_CLIPPED_TTL (60) |
| #define | assert_cache_ok() STMT_NIL |
| #define | RESOLVED_TYPE_AUTO 0xff |
| #define | EXIT_DNS_TIMEOUT_DEFAULT (1000) |
| #define | EXIT_DNS_TIMEOUT_MIN (1) |
| #define | EXIT_DNS_TIMEOUT_MAX (120000) |
| #define | EXIT_DNS_NUM_ATTEMPTS_DEFAULT (2) |
| #define | EXIT_DNS_NUM_ATTEMPTS_MIN (0) |
| #define | EXIT_DNS_NUM_ATTEMPTS_MAX (255) |
| #define | SET(k, v) evdns_base_set_option(the_evdns_base, (k), (v)) |
| #define | N_WILDCARD_CHECKS 2 |
Functions | |
| static void | purge_expired_resolves (time_t now) |
| static void | dns_found_answer (const char *address, uint8_t query_type, int dns_answer, const tor_addr_t *addr, const char *hostname, uint32_t ttl) |
| static void | add_wildcarded_test_address (const char *address) |
| static int | configure_nameservers (int force) |
| static int | answer_is_wildcarded (const char *ip) |
| static int | evdns_err_is_transient (int err) |
| static void | inform_pending_connections (cached_resolve_t *resolve) |
| static void | make_pending_resolve_cached (cached_resolve_t *cached) |
| static void | configure_libevent_options (void) |
| static void | assert_resolve_ok (cached_resolve_t *resolve) |
| static | HT_HEAD (cache_map, cached_resolve_t) |
| static unsigned int | cached_resolve_hash (cached_resolve_t *a) |
| HT_PROTOTYPE (cache_map, cached_resolve_t, node, cached_resolve_hash, cached_resolves_eq) | |
| HT_GENERATE2 (cache_map, cached_resolve_t, node, cached_resolve_hash, cached_resolves_eq, 0.6, tor_reallocarray_, tor_free_) | |
| static void | init_cache_map (void) |
| static void | evdns_log_cb (int warn, const char *msg) |
| void | dns_new_consensus_params (const networkstatus_t *ns) |
| int | dns_init (void) |
| int | dns_reset (void) |
| int | has_dns_init_failed (void) |
| static void | free_cached_resolve_ (cached_resolve_t *r) |
| static int | compare_cached_resolves_by_expiry_ (const void *_a, const void *_b) |
| static void | cached_resolve_add_answer (cached_resolve_t *resolve, int query_type, int dns_result, const tor_addr_t *answer_addr, const char *answer_hostname, uint32_t ttl) |
| static int | cached_resolve_have_all_answers (const cached_resolve_t *resolve) |
| static void | set_expiry (cached_resolve_t *resolve, time_t expires) |
| void | dns_free_all (void) |
| STATIC void | send_resolved_cell (edge_connection_t *conn, uint8_t answer_type, const cached_resolve_t *resolved) |
| void | dns_send_resolved_error_cell (edge_connection_t *conn, uint8_t answer_type) |
| STATIC void | send_resolved_hostname_cell (edge_connection_t *conn, const char *hostname) |
| int | dns_resolve (edge_connection_t *exitconn) |
| STATIC int | dns_resolve_impl (edge_connection_t *exitconn, int is_resolve, or_circuit_t *oncirc, char **hostname_out, int *made_connection_pending_out, cached_resolve_t **resolve_out) |
| STATIC int | set_exitconn_info_from_resolve (edge_connection_t *exitconn, const cached_resolve_t *resolve, char **hostname_out) |
| void | assert_connection_edge_not_dns_pending (edge_connection_t *conn) |
| void | connection_dns_remove (edge_connection_t *conn) |
| STATIC void | dns_cancel_pending_resolve (const char *address) |
| static int | is_test_address (const char *address) |
| size_t | number_of_configured_nameservers (void) |
| static const char * | get_consensus_param_exit_dns_timeout (void) |
| static const char * | get_consensus_param_exit_dns_attempts (void) |
| static void | evdns_callback (int result, char type, int count, int ttl, void *addresses, void *arg) |
| static int | launch_one_resolve (const char *address, uint8_t query_type, const tor_addr_t *ptr_address) |
| STATIC int | launch_resolve (cached_resolve_t *resolve) |
| static void | wildcard_increment_answer (const char *id) |
| static void | evdns_wildcard_check_callback (int result, char type, int count, int ttl, void *addresses, void *arg) |
| static void | launch_wildcard_check (int min_len, int max_len, int is_ipv6, const char *suffix) |
| static void | launch_test_addresses (evutil_socket_t fd, short event, void *args) |
| static void | dns_launch_wildcard_checks (void) |
| void | dns_launch_correctness_checks (void) |
| int | dns_seems_to_be_broken (void) |
| int | dns_seems_to_be_broken_for_ipv6 (void) |
| void | dns_reset_correctness_checks (void) |
| static int | dns_cache_entry_count (void) |
| size_t | dns_cache_total_allocation (void) |
| void | dump_dns_mem_usage (int severity) |
| size_t | dns_cache_handle_oom (time_t now, size_t min_remove_bytes) |
| cached_resolve_t * | dns_get_cache_entry (cached_resolve_t *query) |
| void | dns_insert_cache_entry (cached_resolve_t *new_entry) |
Variables | |
| static struct evdns_base * | the_evdns_base = NULL |
| static int | nameservers_configured = 0 |
| static int | nameserver_config_failed = 0 |
| static char * | resolv_conf_fname = NULL |
| static time_t | resolv_conf_mtime = 0 |
| static smartlist_t * | cached_resolve_pqueue = NULL |
| static int | n_wildcard_requests = 0 |
| static strmap_t * | dns_wildcard_response_count = NULL |
| static smartlist_t * | dns_wildcard_list = NULL |
| static int | dns_wildcard_one_notice_given = 0 |
| static int | dns_wildcard_notice_given = 0 |
| static smartlist_t * | dns_wildcarded_test_address_list = NULL |
| static int | dns_wildcarded_test_address_notice_given = 0 |
| static int | dns_is_completely_invalid = 0 |
Implements a local cache for DNS results for Tor servers. This is implemented as a wrapper around Adam Langley's eventdns.c code. (We can't just use gethostbyname() and friends because we really need to be nonblocking.)
There are three main cases when a Tor relay uses dns.c to launch a DNS request:
Each of these gets handled a little differently.
To check for correctness, we look up some hostname we expect to exist and have real entries, some hostnames which we expect to definitely not exist, and some hostnames that we expect to probably not exist. If too many of the hostnames that shouldn't exist do exist, that's a DNS hijacking attempt. If too many of the hostnames that should exist have the same addresses as the ones that shouldn't exist, that's a very bad DNS hijacking attempt, or a very naughty captive portal. And if the hostnames that should exist simply don't exist, we probably have a broken nameserver.
To handle client requests, we first check our cache for answers. If there isn't something up-to-date, we've got to launch A or AAAA requests as appropriate. How we handle responses to those in particular is a bit complex; see dns_lookup() and set_exitconn_info_from_resolve().
When a lookup is finally complete, the inform_pending_connections() function will tell all of the streams that have been waiting for the resolve, by calling connection_exit_connect() if the client sent a RELAY_BEGIN cell, and by calling send_resolved_cell() or send_hostname_cell() if the client sent a RELAY_RESOLVE cell.
Definition in file dns.c.
| #define RESOLVE_MAX_TIMEOUT 300 |
| #define RESOLVED_CLIPPED_TTL (60) |
The clipped TTL sent back in the RESOLVED cell for every DNS queries.
See https://gitlab.torproject.org/tpo/core/tor/-/issues/40979 for a thorough explanation but this is first and foremost a security fix in order to avoid an exit DNS cache oracle.
|
static |
Note that a single test address (one believed to be good) seems to be getting redirected to the same IP as failures are.
Definition at line 1938 of file dns.c.
Referenced by evdns_callback().
|
static |
Return true iff we have noticed that the dotted-quad ip has been returned in response to requests for nonexistent hostnames.
Definition at line 2188 of file dns.c.
Referenced by evdns_callback().
| void assert_connection_edge_not_dns_pending | ( | edge_connection_t * | conn | ) |
|
static |
Exit with an assertion if resolve is corrupt.
Definition at line 2195 of file dns.c.
Referenced by dns_found_answer(), HT_HEAD(), and make_pending_resolve_cached().
|
static |
|
inlinestatic |
|
static |
Return true iff there are no in-flight requests for resolve.
Definition at line 375 of file dns.c.
Referenced by dns_found_answer().
|
static |
Compare two cached_resolve_t pointers by expiry time, and return less-than-zero, zero, or greater-than-zero as appropriate. Used for the priority queue implementation.
Definition at line 307 of file dns.c.
Referenced by purge_expired_resolves(), and set_expiry().
|
static |
Configure the libevent options. This can safely be called after initialization or even if the evdns base is not set.
Definition at line 1441 of file dns.c.
Referenced by configure_nameservers(), and dns_new_consensus_params().
|
static |
Configure eventdns nameservers if force is true, or if the configuration has changed since the last time we called this function, or if we failed on our last attempt. On Unix, this reads from /etc/resolv.conf or options->ServerDNSResolvConfFile; on Windows, this reads from options->ServerDNSResolvConfFile or the registry. Return 0 on success or -1 on failure.
Definition at line 1502 of file dns.c.
Referenced by dns_init(), dns_reset(), and launch_resolve().
| void connection_dns_remove | ( | edge_connection_t * | conn | ) |
|
static |
Return the number of DNS cache entries as an int
Definition at line 2219 of file dns.c.
Referenced by dump_dns_mem_usage().
| size_t dns_cache_handle_oom | ( | time_t | now, |
| size_t | min_remove_bytes | ||
| ) |
| STATIC void dns_cancel_pending_resolve | ( | const char * | address | ) |
Mark all connections waiting for address for close. Then cancel the resolve for address itself, and remove any cached results for address from the cache.
Definition at line 1057 of file dns.c.
Referenced by dns_resolve().
|
static |
Called on the OR side when the eventdns library tells us the outcome of a single DNS resolve: remember the answer, and tell all pending connections about the result of the lookup if the lookup is now done. (address is a NUL-terminated string containing the address to look up; query_type is one of DNS_{IPv4_A,IPv6_AAAA,PTR}; dns_answer is DNS_OK or one of DNS_ERR_*, addr is an IPv4 or IPv6 address if we got one; hostname is a hostname fora PTR request if we got one, and ttl is the time-to-live of this answer, in seconds.)
Definition at line 1147 of file dns.c.
Referenced by evdns_callback().
| void dns_free_all | ( | void | ) |
| cached_resolve_t * dns_get_cache_entry | ( | cached_resolve_t * | query | ) |
| int dns_init | ( | void | ) |
| void dns_insert_cache_entry | ( | cached_resolve_t * | new_entry | ) |
| void dns_launch_correctness_checks | ( | void | ) |
If appropriate, start testing whether our DNS servers tend to lie to us.
Definition at line 2126 of file dns.c.
Referenced by check_dns_honesty_callback().
|
static |
Launch DNS requests for a few nonexistent hostnames and a few well-known hostnames, and see if we can catch our nameserver trying to hijack them and map them to a stupid "I couldn't find ggoogle.com but maybe you'd like to buy these lovely encyclopedias" page.
Definition at line 2095 of file dns.c.
Referenced by dns_launch_correctness_checks().
| void dns_new_consensus_params | ( | const networkstatus_t * | ns | ) |
| int dns_reset | ( | void | ) |
Called when DNS-related options change (or may have changed). Returns -1 on failure, 0 on success.
Definition at line 253 of file dns.c.
Referenced by do_hup(), and options_act().
| void dns_reset_correctness_checks | ( | void | ) |
| int dns_resolve | ( | edge_connection_t * | exitconn | ) |
See if we have a cache entry for exitconn->address. If so, if resolve valid, put it into exitconn->addr and return 1. If resolve failed, free exitconn and return -1.
(For EXIT_PURPOSE_RESOLVE connections, send back a RESOLVED error cell on returning -1. For EXIT_PURPOSE_CONNECT connections, there's no need to send back an END cell, since connection_exit_begin_conn will do that for us.)
If we have a cached answer, send the answer back along exitconn's circuit.
Else, if seen before and pending, add conn to the pending list, and return 0.
Else, if not seen before, add conn to pending list, hand to dns farm, and return 0.
Exitconn's on_circuit field must be set, but exitconn should not yet be linked onto the n_streams/resolving_streams list of that circuit. On success, link the connection to n_streams if it's an exit connection. On "pending", link the connection to resolving streams. Otherwise, clear its on_circuit field.
Definition at line 641 of file dns.c.
Referenced by connection_exit_begin_conn(), and connection_exit_begin_resolve().
| STATIC int dns_resolve_impl | ( | edge_connection_t * | exitconn, |
| int | is_resolve, | ||
| or_circuit_t * | oncirc, | ||
| char ** | hostname_out, | ||
| int * | made_connection_pending_out, | ||
| cached_resolve_t ** | resolve_out | ||
| ) |
Helper function for dns_resolve: same functionality, but does not handle:
Return -2 on a transient error. If it's a reverse resolve and it's successful, sets *hostname_out to a newly allocated string holding the cached reverse DNS value.
Set *made_connection_pending_out to true if we have placed exitconn on the list of pending connections for some resolve; set it to false otherwise.
Set *resolve_out to a cached resolve, if we found one.
Definition at line 728 of file dns.c.
Referenced by dns_resolve().
| int dns_seems_to_be_broken | ( | void | ) |
| int dns_seems_to_be_broken_for_ipv6 | ( | void | ) |
| void dns_send_resolved_error_cell | ( | edge_connection_t * | conn, |
| uint8_t | answer_type | ||
| ) |
| void dump_dns_mem_usage | ( | int | severity | ) |
|
static |
For eventdns: Called when we get an answer for a request we launched. See eventdns.h for arguments; 'arg' holds the address we tried to resolve.
Definition at line 1636 of file dns.c.
Referenced by launch_one_resolve().
|
static |
Eventdns helper: return true iff the eventdns result err is a transient failure.
Definition at line 1341 of file dns.c.
Referenced by set_exitconn_info_from_resolve().
|
static |
Helper: called by eventdns when eventdns wants to log something.
Definition at line 173 of file dns.c.
Referenced by configure_nameservers().
|
static |
Callback function when we get an answer (possibly failing) for a request for a (hopefully) nonexistent domain.
Definition at line 1972 of file dns.c.
Referenced by launch_wildcard_check().
|
static |
Helper: free storage held by an entry in the DNS cache.
Definition at line 288 of file dns.c.
Referenced by dns_free_all().
|
static |
Return a pointer to a stack allocated buffer containing the string representation of the exit_dns_num_attempts consensus parameter.
Definition at line 1422 of file dns.c.
Referenced by configure_libevent_options().
|
static |
Return a pointer to a stack allocated buffer containing the string representation of the exit_dns_timeout consensus parameter.
Definition at line 1393 of file dns.c.
Referenced by configure_libevent_options().
| int has_dns_init_failed | ( | void | ) |
|
static |
|
static |
Given a pending cached_resolve_t that we just finished resolving, inform every connection that was waiting for the outcome of that resolution.
Do this by sending a RELAY_RESOLVED cell (if the pending stream had sent us a RELAY_RESOLVE cell), or by launching an exit connection (if the pending stream had sent us a RELAY_BEGIN cell).
Definition at line 1200 of file dns.c.
Referenced by dns_found_answer().
|
static |
|
inlinestatic |
Return true iff address is one of the addresses we use to verify that well-known sites aren't being hijacked by our DNS servers.
Definition at line 1130 of file dns.c.
Referenced by dns_found_answer(), and evdns_callback().
|
static |
Start a single DNS resolve for address (if query_type is DNS_IPv4_A or DNS_IPv6_AAAA) ptr_address (if query_type is DNS_PTR). Return 0 if we launched the request, -1 otherwise.
Definition at line 1760 of file dns.c.
Referenced by launch_resolve(), and launch_test_addresses().
| STATIC int launch_resolve | ( | cached_resolve_t * | resolve | ) |
For eventdns: start resolving as necessary to find the target for exitconn. Returns -1 on error, -2 on transient error, 0 on "resolve launched."
Definition at line 1815 of file dns.c.
Referenced by dns_resolve_impl().
|
static |
Launch attempts to resolve a bunch of known-good addresses (configured in ServerDNSTestAddresses). [Callback for a libevent timer]
Definition at line 2055 of file dns.c.
Referenced by dns_launch_correctness_checks().
|
static |
Launch a single request for a nonexistent hostname consisting of between min_len and max_len random (plausible) characters followed by suffix
Definition at line 2021 of file dns.c.
Referenced by dns_launch_wildcard_checks().
|
static |
Remove a pending cached_resolve_t from the hashtable, and add a corresponding cached cached_resolve_t.
This function is only necessary because of the perversity of our cache timeout code; see inline comment for ideas on eliminating it.
Definition at line 1285 of file dns.c.
Referenced by dns_found_answer().
| size_t number_of_configured_nameservers | ( | void | ) |
|
static |
Remove every cached_resolve whose expire time is before or equal to now from the cache.
Definition at line 424 of file dns.c.
Referenced by dns_resolve_impl().
| STATIC void send_resolved_cell | ( | edge_connection_t * | conn, |
| uint8_t | answer_type, | ||
| const cached_resolve_t * | resolved | ||
| ) |
Send a response to the RESOLVE request of a connection. answer_type must be one of RESOLVED_TYPE_(AUTO|ERROR|ERROR_TRANSIENT|).
If circ is provided, and we have a cached answer, send the answer back along circ; otherwise, send the answer back along conn's attached circuit.
Definition at line 516 of file dns.c.
Referenced by dns_resolve(), and inform_pending_connections().
| STATIC void send_resolved_hostname_cell | ( | edge_connection_t * | conn, |
| const char * | hostname | ||
| ) |
Send a response to the RESOLVE request of a connection for an in-addr.arpa address on connection conn which yielded the result hostname. The answer type will be RESOLVED_HOSTNAME.
If circ is provided, and we have a cached answer, send the answer back along circ; otherwise, send the answer back along conn's attached circuit.
Definition at line 590 of file dns.c.
Referenced by dns_resolve(), and inform_pending_connections().
| STATIC int set_exitconn_info_from_resolve | ( | edge_connection_t * | exitconn, |
| const cached_resolve_t * | resolve, | ||
| char ** | hostname_out | ||
| ) |
Given an exit connection exitconn, and a cached_resolve_t resolve whose DNS lookups have all either succeeded or failed, update the appropriate fields (address_ttl and addr) of exitconn.
The logic can be complicated here, since we might have launched both an A lookup and an AAAA lookup, and since either of those might have succeeded or failed, and since we want to answer a RESOLVE cell with a full answer but answer a BEGIN cell with whatever answer the client would accept and we could still connect to.
If this is a reverse lookup, set *hostname_out to a newly allocated copy of the name resulting hostname.
Return -2 on a transient error, -1 on a permenent error, and 1 on a successful lookup.
Definition at line 880 of file dns.c.
Referenced by dns_resolve_impl(), and inform_pending_connections().
|
static |
Set an expiry time for a cached_resolve_t, and add it to the expiry priority queue
Definition at line 385 of file dns.c.
Referenced by dns_resolve_impl(), and make_pending_resolve_cached().
|
static |
Called when we see id (a dotted quad or IPv6 address) in response to a request for a hopefully bogus address.
Definition at line 1906 of file dns.c.
Referenced by evdns_wildcard_check_callback().
|
static |
Priority queue of cached_resolve_t objects to let us know when they will expire.
Definition at line 320 of file dns.c.
Referenced by dns_free_all(), purge_expired_resolves(), and set_expiry().
|
static |
True iff all addresses seem to be getting wildcarded.
Definition at line 1901 of file dns.c.
Referenced by add_wildcarded_test_address(), dns_reset_correctness_checks(), and dns_seems_to_be_broken().
|
static |
If present, a list of dotted-quad IP addresses that we are pretty sure our nameserver wants to return in response to requests for nonexistent domains.
Definition at line 1887 of file dns.c.
Referenced by answer_is_wildcarded(), dns_reset_correctness_checks(), and wildcard_increment_answer().
|
static |
True iff we've warned that our DNS server is wildcarding too many failures.
Definition at line 1893 of file dns.c.
Referenced by dns_reset_correctness_checks(), and wildcard_increment_answer().
|
static |
True iff we've logged about a single address getting wildcarded. Subsequent warnings will be less severe.
Definition at line 1890 of file dns.c.
Referenced by dns_reset_correctness_checks(), and evdns_wildcard_check_callback().
|
static |
Map from dotted-quad IP address in response to an int holding how many times we've seen it for a randomly generated (hopefully bogus) address. It would be easier to use definitely-invalid addresses (as specified by RFC2606), but see comment in dns_launch_wildcard_checks().
Definition at line 1882 of file dns.c.
Referenced by dns_reset_correctness_checks(), evdns_wildcard_check_callback(), and wildcard_increment_answer().
|
static |
List of supposedly good addresses that are getting wildcarded to the same addresses as nonexistent addresses.
Definition at line 1897 of file dns.c.
Referenced by add_wildcarded_test_address(), and dns_reset_correctness_checks().
|
static |
True iff we've warned about a test address getting wildcarded
Definition at line 1899 of file dns.c.
Referenced by add_wildcarded_test_address(), and dns_reset_correctness_checks().
|
static |
How many requests for bogus addresses have we launched so far?
Definition at line 1876 of file dns.c.
Referenced by dns_reset_correctness_checks(), evdns_wildcard_check_callback(), and wildcard_increment_answer().
|
static |
Did our most recent attempt to configure nameservers with eventdns fail?
Definition at line 102 of file dns.c.
Referenced by configure_nameservers(), and has_dns_init_failed().
|
static |
Have we currently configured nameservers with eventdns?
Definition at line 100 of file dns.c.
Referenced by configure_nameservers(), dns_reset(), and launch_resolve().
|
static |
What was the resolv_conf fname we last used when configuring the nameservers? Used to check whether we need to reconfigure.
Definition at line 105 of file dns.c.
Referenced by configure_nameservers(), dns_free_all(), and dns_reset().
|
static |
What was the mtime on the resolv.conf file we last used when configuring the nameservers? Used to check whether we need to reconfigure.
Definition at line 108 of file dns.c.
Referenced by configure_nameservers(), and dns_reset().
|
static |
Our evdns_base; this structure handles all our name lookups.
Definition at line 97 of file dns.c.
Referenced by configure_libevent_options(), configure_nameservers(), dns_reset(), launch_one_resolve(), launch_resolve(), launch_test_addresses(), launch_wildcard_check(), and number_of_configured_nameservers().