diff options
author | Roger Dingledine <arma@torproject.org> | 2005-02-22 00:53:08 +0000 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2005-02-22 00:53:08 +0000 |
commit | 8727acf2f1e3d385588fcd0a99661e6db15ba152 (patch) | |
tree | c5843496c7e509c344c6477662e07f5e5b804087 /src | |
parent | b5bddd8cfdeff71fcc04553bfd8a1049ee8e90e6 (diff) | |
download | tor-8727acf2f1e3d385588fcd0a99661e6db15ba152.tar.gz tor-8727acf2f1e3d385588fcd0a99661e6db15ba152.zip |
Add a new AddressMap directive to rewrite incoming socks addresses.
Add a new TrackHostExits directive to trigger addressmaps for
certain incoming socks addresses, for sites that break when your exit
keeps changing.
Redo the client-side dns cache so it's just an addressmap too.
svn:r3641
Diffstat (limited to 'src')
-rw-r--r-- | src/or/circuituse.c | 57 | ||||
-rw-r--r-- | src/or/config.c | 30 | ||||
-rw-r--r-- | src/or/connection_edge.c | 367 | ||||
-rw-r--r-- | src/or/main.c | 4 | ||||
-rw-r--r-- | src/or/or.h | 20 | ||||
-rw-r--r-- | src/or/relay.c | 4 |
6 files changed, 283 insertions, 199 deletions
diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 0cf3651d7e..2d69e97566 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -385,7 +385,7 @@ void circuit_build_needed_circs(time_t now) { circuit_reset_failure_count(1); time_to_new_circuit = now + get_options()->NewCircuitPeriod; if (proxy_mode(get_options())) - client_dns_clean(); + addressmap_clean(now); circuit_expire_old_circuits(); #if 0 /* disable for now, until predict-and-launch-new can cull leftovers */ @@ -768,7 +768,6 @@ circuit_get_open_circ_or_launch(connection_t *conn, uint8_t desired_circuit_purpose, circuit_t **circp) { circuit_t *circ; - uint32_t addr; int is_resolve; int need_uptime; @@ -801,7 +800,10 @@ circuit_get_open_circ_or_launch(connection_t *conn, /* Do we need to check exit policy? */ if (!is_resolve && !connection_edge_is_rendezvous_stream(conn)) { - addr = client_dns_lookup_entry(conn->socks_request->address); + struct in_addr in; + uint32_t addr = 0; + if (tor_inet_aton(conn->socks_request->address, &in)) + addr = ntohl(in.s_addr); if (router_exit_policy_all_routers_reject(addr, conn->socks_request->port, need_uptime)) { log_fn(LOG_NOTICE,"No Tor server exists that allows exit to %s:%d. Rejecting.", @@ -899,6 +901,53 @@ static void link_apconn_to_circ(connection_t *apconn, circuit_t *circ) { apconn->cpath_layer = circ->cpath->prev; } +/** If an exit wasn't specifically chosen, save the history for future + * use */ +static void +consider_recording_trackhost(connection_t *conn, circuit_t *circ) { + int found_needle = 0; + char *str; + or_options_t *options = get_options(); + size_t len; + char *new_address; + + /* Search the addressmap for this conn's destination. */ + /* If he's not in the address map.. */ + if (!options->TrackHostExits || + addressmap_already_mapped(conn->socks_request->address)) + return; /* nothing to track, or already mapped */ + + SMARTLIST_FOREACH(options->TrackHostExits, const char *, cp, { + if (cp[0] == '.') { /* match end */ + /* XXX strstr is probably really bad here */ + if ((str = strstr(conn->socks_request->address, &cp[1]))) { + if (str == conn->socks_request->address + || strcmp(str, &cp[1]) == 0) { + found_needle = 1; + } + } + } else if (strcmp(cp, conn->socks_request->address) == 0) { + found_needle = 1; + } + }); + + if (!found_needle) + return; + + /* Add this exit/hostname pair to the addressmap. */ + len = strlen(conn->socks_request->address) + 1 /* '.' */ + + strlen(circ->build_state->chosen_exit_name) + 1 /* '.' */ + + strlen("exit") + 1 /* '\0' */; + new_address = tor_malloc(len); + + tor_snprintf(new_address, len, "%s.%s.exit", + conn->socks_request->address, + circ->build_state->chosen_exit_name); + + addressmap_register(conn->socks_request->address, new_address, + time(NULL) + options->TrackHostExitsExpire); +} + /** Try to find a safe live circuit for CONN_TYPE_AP connection conn. If * we don't find one: if conn cannot be handled by any known nodes, * warn and return -1 (conn needs to die); @@ -957,7 +1006,7 @@ int connection_ap_handshake_attach_circuit(connection_t *conn) { link_apconn_to_circ(conn, circ); tor_assert(conn->socks_request); if (conn->socks_request->command == SOCKS_COMMAND_CONNECT) { -// consider_recording_trackhost(conn, circ); + consider_recording_trackhost(conn, circ); connection_ap_handshake_send_begin(conn, circ); } else { connection_ap_handshake_send_resolve(conn, circ); diff --git a/src/or/config.c b/src/or/config.c index e8142176d6..47b292e465 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -120,6 +120,9 @@ static config_var_t config_vars[] = { VAR("StrictEntryNodes", BOOL, StrictEntryNodes, "0"), VAR("ExitPolicy", LINELIST, ExitPolicy, NULL), VAR("ExcludeNodes", STRING, ExcludeNodes, NULL), + VAR("TrackHostExits", CSV, TrackHostExits, NULL), + VAR("TrackHostExitsExpire",INTERVAL, TrackHostExitsExpire, "30 minutes"), + VAR("AddressMap", LINELIST, AddressMap, NULL), VAR("FascistFirewall", BOOL, FascistFirewall, "0"), VAR("FirewallPorts", CSV, FirewallPorts, "80,443"), VAR("MyFamily", STRING, MyFamily, NULL), @@ -186,6 +189,7 @@ static or_options_t *options_dup(or_options_t *old); static int options_validate(or_options_t *options); static int options_transition_allowed(or_options_t *old, or_options_t *new); static int check_nickname_list(const char *lst, const char *name); +static void config_register_addressmaps(or_options_t *options); static int parse_dir_server_line(const char *line, int validate_only); static int parse_redirect_line(smartlist_t *result, @@ -333,6 +337,9 @@ options_act(void) { if (options->PidFile) write_pidfile(options->PidFile); + /* Register addressmap directives */ + config_register_addressmaps(options); + /* Update address policies. */ parse_socks_policy(); parse_dir_policy(); @@ -1797,6 +1804,29 @@ init_from_config(int argc, char **argv) return -1; } +static void +config_register_addressmaps(or_options_t *options) { + smartlist_t *elts; + struct config_line_t *opt; + char *from, *to; + + elts = smartlist_create(); + for (opt = options->AddressMap; opt; opt = opt->next) { + smartlist_split_string(elts, opt->value, NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2); + if (smartlist_len(elts) >= 2) { + from = smartlist_get(elts,0); + to = smartlist_get(elts,1); + addressmap_register(from, tor_strdup(to), 0); + } else { + log_fn(LOG_WARN,"AddressMap '%s' has too few arguments. Ignoring.", opt->value); + } + SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp)); + smartlist_clear(elts); + } + smartlist_free(elts); +} + /** If <b>range</b> is of the form MIN-MAX, for MIN and MAX both * recognized log severity levels, set *<b>min_out</b> to MIN and * *<b>max_out</b> to MAX and return 0. Else, if <b>range<b> is of diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index a541ab1c44..55343fee03 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -329,6 +329,169 @@ void connection_ap_attach_pending(void) } } +/** A client-side struct to remember requests to rewrite addresses + * to new addresses. These structs make up a tree, with addressmap + * below as its root. + * + * There are 5 ways to set an address mapping: + * - A MapAddress command from the controller [permanent] + * - An AddressMap directive in the torrc [permanent] + * - When a TrackHostExits torrc directive is triggered [temporary] + * - When a dns resolve succeeds [temporary] + * - When a dns resolve fails [temporary] + * + * When an addressmap request is made but one is already registered, + * the new one is replaced only if the currently registered one has + * no "new_address" (that is, it's in the process of dns resolve), + * or if the new one is permanent (expires==0). + */ +typedef struct { + char *new_address; + time_t expires; + int num_resolve_failures; +} addressmap_entry_t; + +/** The tree of client-side address rewrite instructions. */ +static strmap_t *addressmap; + +/** Initialize addressmap. */ +void addressmap_init(void) { + addressmap = strmap_new(); +} + +/** Free the memory associated with the addressmap entry <b>_ent</b>. */ +static void +addressmap_ent_free(void *_ent) { + addressmap_entry_t *ent = _ent; + tor_free(ent->new_address); + tor_free(ent); +} + +/** A helper function for addressmap_clean() below. If ent is too old, + * then remove it from the tree and return NULL, else return ent. + */ +static void * +_addressmap_remove_if_expired(const char *addr, + addressmap_entry_t *ent, + time_t *nowp) { + if (ent->expires && ent->expires < *nowp) { + log(LOG_NOTICE, "Addressmap: expiring remap (%s to %s)", + addr, ent->new_address); + addressmap_ent_free(ent); + return NULL; + } else { + return ent; + } +} + +/** Clean out entries from the addressmap cache that were + * added long enough ago that they are no longer valid. + */ +void addressmap_clean(time_t now) { + strmap_foreach(addressmap, + (strmap_foreach_fn)_addressmap_remove_if_expired, &now); +} + +/** Free all the elements in the addressmap, and free the addressmap + * itself. */ +void addressmap_free_all(void) { + strmap_free(addressmap, addressmap_ent_free); + addressmap = NULL; +} + +/** Look at address, and rewrite it until it doesn't want any + * more rewrites; but don't get into an infinite loop. + * Don't write more than maxlen chars into address. + */ +void addressmap_rewrite(char *address, size_t maxlen) { + addressmap_entry_t *ent; + int rewrites; + + for (rewrites = 0; rewrites < 16; rewrites++) { + ent = strmap_get(addressmap, address); + + if (!ent || !ent->new_address) + return; /* done, no rewrite needed */ + + log_fn(LOG_NOTICE, "Addressmap: rewriting '%s' to '%s'", + address, ent->new_address); + strlcpy(address, ent->new_address, maxlen); + } + log_fn(LOG_WARN,"Loop detected: we've rewritten '%s' 16 times! Using it as-is.", + address); + /* it's fine to rewrite a rewrite, but don't loop forever */ +} + +/** Return 1 if <b>address</b> is already registered, else return 0 */ +int addressmap_already_mapped(const char *address) { + return strmap_get(addressmap, address) ? 1 : 0; +} + +/** Register a request to map <b>address</b> to <b>new_address</b>, + * which will expire on <b>expires</b> (or 0 if never expires). + * + * new_address should be a newly dup'ed string, which we'll use or + * free as appropriate. We will leave address alone. + */ +void addressmap_register(const char *address, char *new_address, time_t expires) { + addressmap_entry_t *ent; + + ent = strmap_get(addressmap, address); + if (ent && ent->new_address && expires) { + log_fn(LOG_NOTICE,"Addressmap ('%s' to '%s') not performed, since it's already mapped to '%s'", address, new_address, ent->new_address); + tor_free(new_address); + return; + } + if (ent) { /* we'll replace it */ + tor_free(ent->new_address); + } else { /* make a new one and register it */ + ent = tor_malloc_zero(sizeof(addressmap_entry_t)); + strmap_set(addressmap, address, ent); + } + ent->new_address = new_address; + ent->expires = expires; + ent->num_resolve_failures = 0; + + log_fn(LOG_NOTICE, "Addressmap: (re)mapped '%s' to '%s'", + address, ent->new_address); +} + +/** An attempt to resolve <b>address</b> failed at some OR. + * Increment the number of resolve failures we have on record + * for it, and then return that number. + */ +int client_dns_incr_failures(const char *address) +{ + addressmap_entry_t *ent; + ent = strmap_get(addressmap,address); + if (!ent) { + ent = tor_malloc_zero(sizeof(addressmap_entry_t)); + ent->expires = time(NULL)+MAX_DNS_ENTRY_AGE; + strmap_set(addressmap,address,ent); + } + ++ent->num_resolve_failures; + log_fn(LOG_NOTICE,"Address %s now has %d resolve failures.", + address, ent->num_resolve_failures); + return ent->num_resolve_failures; +} + +/** Record the fact that <b>address</b> resolved to <b>val</b>. + * We can now use this in subsequent streams via addressmap_rewrite() + * so we can more correctly choose an exit that will allow <b>address</b>. + */ +void client_dns_set_addressmap(const char *address, uint32_t val) +{ + struct in_addr in; + + tor_assert(address); tor_assert(val); + + if (tor_inet_aton(address, &in)) + return; /* don't set an addressmap back to ourselves! */ + in.s_addr = htonl(val); + addressmap_register(address, strdup(inet_ntoa(in)), + time(NULL) + MAX_DNS_ENTRY_AGE); +} + /** Return 1 if <b>address</b> has funny characters in it like * colons. Return 0 if it's fine. */ @@ -383,6 +546,11 @@ static int connection_ap_handshake_process_socks(connection_t *conn) { return sockshere; } /* else socks handshake is done, continue processing */ + tor_strlower(socks->address); /* normalize it */ + + /* For address map controls, remap the address */ + addressmap_rewrite(socks->address, sizeof(socks->address)); + /* Parse the address provided by SOCKS. Modify it in-place if it * specifies a hidden-service (.onion) or particular exit node (.exit). */ @@ -408,7 +576,7 @@ static int connection_ap_handshake_process_socks(connection_t *conn) { } if (socks->command == SOCKS_COMMAND_RESOLVE) { - uint32_t answer = 0; + uint32_t answer; struct in_addr in; /* Reply to resolves immediately if we can. */ if (strlen(socks->address) > RELAY_PAYLOAD_SIZE) { @@ -416,11 +584,8 @@ static int connection_ap_handshake_process_socks(connection_t *conn) { connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,0,NULL); return -1; } - if (tor_inet_aton(socks->address, &in)) /* see if it's an IP already */ + if (tor_inet_aton(socks->address, &in)) { /* see if it's an IP already */ answer = in.s_addr; - if (!answer && !conn->chosen_exit_name) /* if it's not .exit, check cache */ - answer = htonl(client_dns_lookup_entry(socks->address)); - if (answer) { connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_IPV4,4, (char*)&answer); conn->has_sent_end = 1; @@ -514,8 +679,6 @@ int connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ) { char payload[CELL_PAYLOAD_SIZE]; int payload_len; - struct in_addr in; - const char *string_addr; tor_assert(ap_conn->type == CONN_TYPE_AP); tor_assert(ap_conn->state == AP_CONN_STATE_CIRCUIT_WAIT); @@ -530,18 +693,10 @@ int connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ) return -1; } - if (circ->purpose == CIRCUIT_PURPOSE_C_GENERAL) { - in.s_addr = htonl(client_dns_lookup_entry(ap_conn->socks_request->address)); - string_addr = in.s_addr ? inet_ntoa(in) : NULL; - - tor_snprintf(payload,RELAY_PAYLOAD_SIZE, - "%s:%d", - string_addr ? string_addr : ap_conn->socks_request->address, - ap_conn->socks_request->port); - } else { - tor_snprintf(payload,RELAY_PAYLOAD_SIZE, - ":%d", ap_conn->socks_request->port); - } + tor_snprintf(payload,RELAY_PAYLOAD_SIZE, "%s:%d", + (circ->purpose == CIRCUIT_PURPOSE_C_GENERAL) ? + ap_conn->socks_request->address : "", + ap_conn->socks_request->port); payload_len = strlen(payload)+1; log_fn(LOG_DEBUG,"Sending relay cell to begin stream %d.",ap_conn->stream_id); @@ -670,7 +825,7 @@ void connection_ap_handshake_socks_resolved(connection_t *conn, if (answer_type == RESOLVED_TYPE_IPV4) { uint32_t a = get_uint32(answer); if (a) - client_dns_set_entry(conn->socks_request->address, ntohl(a)); + client_dns_set_addressmap(conn->socks_request->address, ntohl(a)); } if (conn->socks_request->socks_version == 4) { @@ -844,6 +999,7 @@ int connection_exit_begin_conn(cell_t *cell, circuit_t *circ) { tor_free(address); return 0; } + tor_strlower(address); n_stream->address = address; n_stream->state = EXIT_CONN_STATE_RESOLVEFAILED; /* default to failed, change in dns_resolve if it turns out not to fail */ @@ -1018,8 +1174,6 @@ int connection_edge_is_rendezvous_stream(connection_t *conn) { */ int connection_ap_can_use_exit(connection_t *conn, routerinfo_t *exit) { - uint32_t addr; - tor_assert(conn); tor_assert(conn->type == CONN_TYPE_AP); tor_assert(conn->socks_request); @@ -1042,7 +1196,10 @@ int connection_ap_can_use_exit(connection_t *conn, routerinfo_t *exit) } if (conn->socks_request->command != SOCKS_COMMAND_RESOLVE) { - addr = client_dns_lookup_entry(conn->socks_request->address); + struct in_addr in; + uint32_t addr = 0; + if (tor_inet_aton(conn->socks_request->address, &in)) + addr = ntohl(in.s_addr); if (router_compare_addr_to_addr_policy(addr, conn->socks_request->port, exit->exit_policy) == ADDR_POLICY_REJECTED) return 0; @@ -1098,164 +1255,6 @@ int socks_policy_permits_address(uint32_t addr) return 0; } -/* ***** Client DNS code ***** */ - -/* XXX Perhaps this should get merged with the dns.c code somehow. */ -/* XXX But we can't just merge them, because then nodes that act as - * both OR and OP could be attacked: people could rig the dns cache - * by answering funny things to stream begin requests, and later - * other clients would reuse those funny addr's. Hm. - */ - -/** A client-side struct to remember the resolved IP (addr) for - * a given address. These structs make up a tree, with client_dns_map - * below as its root. - */ -struct client_dns_entry { - uint32_t addr; /**< The resolved IP of this entry. */ - time_t expires; /**< At what second does addr expire? */ - int n_failures; /**< How many times has this entry failed to resolve so far? */ -}; - -/** How many elements are in the client dns cache currently? */ -static int client_dns_size = 0; -/** The tree of client-side cached DNS resolves. */ -static strmap_t *client_dns_map = NULL; - -/** Initialize client_dns_map and client_dns_size. */ -void client_dns_init(void) { - client_dns_map = strmap_new(); - client_dns_size = 0; -} - -/** Return the client_dns_entry that corresponds to <b>address</b>. - * If it's not there, allocate and return a new entry for <b>address</b>. - */ -static struct client_dns_entry * -_get_or_create_ent(const char *address) -{ - struct client_dns_entry *ent; - ent = strmap_get_lc(client_dns_map,address); - if (!ent) { - ent = tor_malloc_zero(sizeof(struct client_dns_entry)); - ent->expires = time(NULL)+MAX_DNS_ENTRY_AGE; - strmap_set_lc(client_dns_map,address,ent); - ++client_dns_size; - } - return ent; -} - -/** Return the IP associated with <b>address</b>, if we know it - * and it's still fresh enough. Otherwise return 0. - */ -uint32_t client_dns_lookup_entry(const char *address) -{ - struct client_dns_entry *ent; - struct in_addr in; - time_t now; - - tor_assert(address); - - if (tor_inet_aton(address, &in)) { - log_fn(LOG_DEBUG, "Using static address %s (%08lX)", address, - (unsigned long)ntohl(in.s_addr)); - return ntohl(in.s_addr); - } - ent = strmap_get_lc(client_dns_map,address); - if (!ent || !ent->addr) { - log_fn(LOG_DEBUG, "No entry found for address %s", address); - return 0; - } else { - now = time(NULL); - if (ent->expires < now) { - log_fn(LOG_DEBUG, "Expired entry found for address %s", address); - strmap_remove_lc(client_dns_map,address); - tor_free(ent); - --client_dns_size; - return 0; - } - in.s_addr = htonl(ent->addr); - log_fn(LOG_DEBUG, "Found cached entry for address %s: %s", address, - inet_ntoa(in)); - return ent->addr; - } -} - -/** An attempt to resolve <b>address</b> failed at some OR. - * Increment the number of resolve failures we have on record - * for it, and then return that number. - */ -int client_dns_incr_failures(const char *address) -{ - struct client_dns_entry *ent; - ent = _get_or_create_ent(address); - ++ent->n_failures; - log_fn(LOG_DEBUG,"Address %s now has %d resolve failures.", - address, ent->n_failures); - return ent->n_failures; -} - -/** Record the fact that <b>address</b> resolved to <b>val</b>. - * We can now use this in subsequent streams in client_dns_lookup_entry(), - * so we can more correctly choose a router that will allow <b>address</b> - * to exit from him. - */ -void client_dns_set_entry(const char *address, uint32_t val) -{ - struct client_dns_entry *ent; - struct in_addr in; - time_t now; - - tor_assert(address); - tor_assert(val); - - if (tor_inet_aton(address, &in)) - return; - now = time(NULL); - ent = _get_or_create_ent(address); - in.s_addr = htonl(val); - log_fn(LOG_DEBUG, "Updating entry for address %s: %s", address, - inet_ntoa(in)); - ent->addr = val; - ent->expires = now+MAX_DNS_ENTRY_AGE; - ent->n_failures = 0; -} - -/** A helper function for client_dns_clean() below. If ent is too old, - * then remove it from the tree and return NULL, else return ent. - */ -static void* _remove_if_expired(const char *addr, - struct client_dns_entry *ent, - time_t *nowp) -{ - if (ent->expires < *nowp) { - --client_dns_size; - tor_free(ent); - return NULL; - } else { - return ent; - } -} - -/** Clean out entries from the client-side DNS cache that were - * resolved long enough ago that they are no longer valid. - */ -void client_dns_clean(void) -{ - time_t now; - - if (!client_dns_size) - return; - now = time(NULL); - strmap_foreach(client_dns_map, (strmap_foreach_fn)_remove_if_expired, &now); -} - -void client_dns_free_all(void) -{ - strmap_free(client_dns_map, free); - client_dns_map = NULL; -} - /** Make connection redirection follow the provided list of * exit_redirect_t */ void @@ -1284,20 +1283,18 @@ parse_extended_hostname(char *address) { s = strrchr(address,'.'); if (!s) return 0; /* no dot, thus normal */ - if (!strcasecmp(s+1,"exit")) { + if (!strcmp(s+1,"exit")) { *s = 0; /* null-terminate it */ return EXIT_HOSTNAME; /* .exit */ } - if (strcasecmp(s+1,"onion")) + if (strcmp(s+1,"onion")) return NORMAL_HOSTNAME; /* neither .exit nor .onion, thus normal */ /* so it is .onion */ *s = 0; /* null-terminate it */ if (strlcpy(query, address, REND_SERVICE_ID_LEN+1) >= REND_SERVICE_ID_LEN+1) goto failed; - tor_strlower(query); if (rend_valid_service_id(query)) { - tor_strlower(address); return ONION_HOSTNAME; /* success */ } failed: diff --git a/src/or/main.c b/src/or/main.c index 184bfa3308..dbc81c3a2a 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -1263,7 +1263,7 @@ static int tor_init(int argc, char *argv[]) { rep_hist_init(); /* Initialize the service cache. */ rend_cache_init(); - client_dns_init(); /* Init the client dns cache. Do it always, since it's cheap. */ + addressmap_init(); /* Init the client dns cache. Do it always, since it's cheap. */ /* give it somewhere to log to initially */ add_temp_log(); @@ -1308,7 +1308,7 @@ void tor_free_all(void) { routerlist_free_current(); free_trusted_dir_servers(); - client_dns_free_all(); + addressmap_free_all(); free_socks_policy(); free_dir_policy(); dirserv_free_all(); diff --git a/src/or/or.h b/src/or/or.h index 2403c65999..840ca4a6bb 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -950,6 +950,10 @@ typedef struct { smartlist_t *FirewallPorts; /**< Which ports our firewall allows (strings). */ /** Application ports that require all nodes in circ to have sufficient uptime. */ smartlist_t *LongLivedPorts; + /** Should we try to reuse the same exit node for a given host */ + smartlist_t *TrackHostExits; + int TrackHostExitsExpire; /**< Number of seconds until we expire an addressmap */ + struct config_line_t *AddressMap; /**< List of address map directives. */ int DirFetchPeriod; /**< How often do we fetch new directories? */ int DirPostPeriod; /**< How often do we post our server descriptor to the * authoritative directory servers? */ @@ -1212,6 +1216,7 @@ connection_t *connection_get_by_identity_digest(const char *digest, int type); connection_t *connection_get_by_type(int type); connection_t *connection_get_by_type_state(int type, int state); +connection_t *connection_get_by_type_purpose(int type, int purpose); connection_t *connection_get_by_type_state_lastwritten(int type, int state); connection_t *connection_get_by_type_state_rendquery(int type, int state, const char *rendquery); connection_t *connection_get_by_type_purpose(int type, int purpose); @@ -1258,16 +1263,19 @@ int connection_ap_can_use_exit(connection_t *conn, routerinfo_t *exit); void connection_ap_expire_beginning(void); void connection_ap_attach_pending(void); +void addressmap_init(void); +void addressmap_clean(time_t now); +void addressmap_free_all(void); +void addressmap_rewrite(char *address, size_t maxlen); +int addressmap_already_mapped(const char *address); +void addressmap_register(const char *address, char *new_address, time_t expires); +int client_dns_incr_failures(const char *address); +void client_dns_set_addressmap(const char *address, uint32_t val); + void parse_socks_policy(void); void free_socks_policy(void); int socks_policy_permits_address(uint32_t addr); -void client_dns_init(void); -uint32_t client_dns_lookup_entry(const char *address); -int client_dns_incr_failures(const char *address); -void client_dns_set_entry(const char *address, uint32_t val); -void client_dns_clean(void); -void client_dns_free_all(void); void set_exit_redirects(smartlist_t *lst); typedef enum hostname_type_t { NORMAL_HOSTNAME, ONION_HOSTNAME, EXIT_HOSTNAME diff --git a/src/or/relay.c b/src/or/relay.c index 13ae5cb02d..a403875f67 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -516,7 +516,7 @@ connection_edge_process_relay_cell_not_open( connection_mark_for_close(conn); return 0; } - client_dns_set_entry(conn->socks_request->address, addr); + client_dns_set_addressmap(conn->socks_request->address, addr); /* check if he *ought* to have allowed it */ exitrouter = router_get_by_digest(circ->build_state->chosen_exit_digest); @@ -589,7 +589,7 @@ connection_edge_process_relay_cell_not_open( connection_mark_for_close(conn); return 0; } - client_dns_set_entry(conn->socks_request->address, addr); + client_dns_set_addressmap(conn->socks_request->address, addr); } circuit_log_path(LOG_INFO,circ); connection_ap_handshake_socks_reply(conn, NULL, 0, 1); |