r12946@catbus: nickm | 2007-05-25 10:46:50 -0400

Add an AutomapHostsOnResolve option.  It seems to work.


svn:r10324
This commit is contained in:
Nick Mathewson 2007-05-25 14:48:16 +00:00
parent e9c294654d
commit 39fe91b9a2
5 changed files with 56 additions and 9 deletions

View File

@ -130,6 +130,12 @@ Changes in version 0.2.0.1-alpha - 2007-??-??
- More unit tests. - More unit tests.
- Warn when using a version of libevent before 1.3b to run a server on - Warn when using a version of libevent before 1.3b to run a server on
OSX or BSD: these versions interact badly with userspace threads. OSX or BSD: these versions interact badly with userspace threads.
- Add a new AutomapHostsOnResolve option: when it is enabled, any
resolve request for hosts matching a given pattern causes Tor to
generate an internal virtual address mapping for that host. This
allows DNSPort to work sensibly with hidden service users. By
default, .exit and .onion addresses are remapped; the list of
patterns can be reconfigured with AutomapHostsSuffixes.
o Removed features: o Removed features:
- Removed support for the old binary "version 0" controller protocol. - Removed support for the old binary "version 0" controller protocol.

View File

@ -199,8 +199,8 @@ Things we'd like to do in 0.2.0.x:
o Make a listener type. o Make a listener type.
o Hook into connection_edge logic. o Hook into connection_edge logic.
o Hook into evdns_server_* logic o Hook into evdns_server_* logic
- Actually send back a useful answer. o Actually send back a useful answer.
- Make i o Make it handle .onion and .exit correctly.
- Document. - Document.
- Add a way to request DNS resolves from the controller. - Add a way to request DNS resolves from the controller.
- A better UI for authority ops. - A better UI for authority ops.

View File

@ -67,6 +67,8 @@ static config_abbrev_t _option_abbrevs[] = {
PLURAL(StrictExitNode), PLURAL(StrictExitNode),
{ "l", "Log", 1, 0}, { "l", "Log", 1, 0},
{ "AllowUnverifiedNodes", "AllowInvalidNodes", 0, 0}, { "AllowUnverifiedNodes", "AllowInvalidNodes", 0, 0},
{ "AutomapHostSuffixes", "AutomapHostsSuffixes", 0, 0},
{ "AutomapHostOnResolve", "AutomapHostsOnResolve", 0, 0},
{ "BandwidthRateBytes", "BandwidthRate", 0, 0}, { "BandwidthRateBytes", "BandwidthRate", 0, 0},
{ "BandwidthBurstBytes", "BandwidthBurst", 0, 0}, { "BandwidthBurstBytes", "BandwidthBurst", 0, 0},
{ "DirFetchPostPeriod", "StatusFetchPeriod", 0, 0}, { "DirFetchPostPeriod", "StatusFetchPeriod", 0, 0},
@ -133,6 +135,8 @@ static config_var_t _option_vars[] = {
VAR("AuthDirRejectUnlisted",BOOL, AuthDirRejectUnlisted,"0"), VAR("AuthDirRejectUnlisted",BOOL, AuthDirRejectUnlisted,"0"),
VAR("AuthDirListBadExits", BOOL, AuthDirListBadExits, "0"), VAR("AuthDirListBadExits", BOOL, AuthDirListBadExits, "0"),
VAR("AuthoritativeDirectory",BOOL, AuthoritativeDir, "0"), VAR("AuthoritativeDirectory",BOOL, AuthoritativeDir, "0"),
VAR("AutomapHostsOnResolve",BOOL, AutomapHostsOnResolve,"0"),
VAR("AutomapHostsSuffixes",CSV, AutomapHostsSuffixes, ".onion,.exit"),
VAR("AvoidDiskWrites", BOOL, AvoidDiskWrites, "0"), VAR("AvoidDiskWrites", BOOL, AvoidDiskWrites, "0"),
VAR("BandwidthBurst", MEMUNIT, BandwidthBurst, "6 MB"), VAR("BandwidthBurst", MEMUNIT, BandwidthBurst, "6 MB"),
VAR("BandwidthRate", MEMUNIT, BandwidthRate, "3 MB"), VAR("BandwidthRate", MEMUNIT, BandwidthRate, "3 MB"),
@ -2909,6 +2913,15 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (options->PreferTunneledDirConns && !options->TunnelDirConns) if (options->PreferTunneledDirConns && !options->TunnelDirConns)
REJECT("Must set TunnelDirConns if PreferTunneledDirConns is set."); REJECT("Must set TunnelDirConns if PreferTunneledDirConns is set.");
if (options->AutomapHostsSuffixes) {
SMARTLIST_FOREACH(options->AutomapHostsSuffixes, char *, suf,
{
size_t len = strlen(suf);
if (len && suf[len-1] == '.')
suf[len-1] = '\0';
});
}
return 0; return 0;
#undef REJECT #undef REJECT
#undef COMPLAIN #undef COMPLAIN

View File

@ -669,7 +669,7 @@ addressmap_rewrite(char *address, size_t maxlen)
return (rewrites > 0); /* done, no rewrite needed */ return (rewrites > 0); /* done, no rewrite needed */
cp = tor_strdup(escaped_safe_str(ent->new_address)); cp = tor_strdup(escaped_safe_str(ent->new_address));
log_info(LD_APP, "Addressmap: rewriting %s to %s", log_notice(LD_APP, "Addressmap: rewriting %s to %s",
escaped_safe_str(address), cp); escaped_safe_str(address), cp);
tor_free(cp); tor_free(cp);
strlcpy(address, ent->new_address, maxlen); strlcpy(address, ent->new_address, maxlen);
@ -1009,7 +1009,7 @@ addressmap_get_virtual_address(int type)
++next_virtual_addr; ++next_virtual_addr;
--available; --available;
log_notice(LD_CONFIG, "%d addrs available", (int)available); log_info(LD_CONFIG, "%d addrs available", (int)available);
if (! --available) { if (! --available) {
log_warn(LD_CONFIG, "Ran out of virtual addresses!"); log_warn(LD_CONFIG, "Ran out of virtual addresses!");
return NULL; return NULL;
@ -1067,6 +1067,7 @@ addressmap_register_virtual_address(int type, char *new_address)
tor_free(*addrp); tor_free(*addrp);
*addrp = addressmap_get_virtual_address(type); *addrp = addressmap_get_virtual_address(type);
log_info(LD_APP, "Registering map from %s to %s", *addrp, new_address);
addressmap_register(*addrp, new_address, 2); addressmap_register(*addrp, new_address, 2);
#if 0 #if 0
@ -1081,7 +1082,7 @@ addressmap_register_virtual_address(int type, char *new_address)
tor_assert(!strcasecmp(*addrp, tor_assert(!strcasecmp(*addrp,
(type == RESOLVED_TYPE_IPV4) ? (type == RESOLVED_TYPE_IPV4) ?
vent->ipv4_address : vent->hostname_address)); vent->ipv4_address : vent->hostname_address));
log_fn(LOG_INFO, "Map from %s to %s okay.", log_info(LD_APP, "Map from %s to %s okay.",
safe_str(*addrp),safe_str(new_address)); safe_str(*addrp),safe_str(new_address));
} }
#endif #endif
@ -1176,12 +1177,34 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
{ {
socks_request_t *socks = conn->socks_request; socks_request_t *socks = conn->socks_request;
hostname_type_t addresstype; hostname_type_t addresstype;
or_options_t *options = get_options();
struct in_addr addr_tmp;
int automap = 0;
tor_strlower(socks->address); /* normalize it */ tor_strlower(socks->address); /* normalize it */
log_debug(LD_APP,"Client asked for %s:%d", log_debug(LD_APP,"Client asked for %s:%d",
safe_str(socks->address), safe_str(socks->address),
socks->port); socks->port);
if (socks->command == SOCKS_COMMAND_RESOLVE &&
!tor_inet_aton(socks->address, &addr_tmp) &&
options->AutomapHostsOnResolve && options->AutomapHostsSuffixes) {
SMARTLIST_FOREACH(options->AutomapHostsSuffixes, const char *, cp,
if (!strcasecmpend(socks->address, cp)) {
automap = 1;
break;
});
if (automap) {
const char *new_addr;
new_addr = addressmap_register_virtual_address(
RESOLVED_TYPE_IPV4, tor_strdup(socks->address));
tor_assert(new_addr);
log_info(LD_APP, "Automapping %s to %s",
escaped_safe_str(socks->address), safe_str(new_addr));
strlcpy(socks->address, new_addr, sizeof(socks->address));
}
}
if (socks->command == SOCKS_COMMAND_RESOLVE_PTR) { if (socks->command == SOCKS_COMMAND_RESOLVE_PTR) {
if (addressmap_rewrite_reverse(socks->address, sizeof(socks->address))) { if (addressmap_rewrite_reverse(socks->address, sizeof(socks->address))) {
connection_ap_handshake_socks_resolved(conn, RESOLVED_TYPE_HOSTNAME, connection_ap_handshake_socks_resolved(conn, RESOLVED_TYPE_HOSTNAME,
@ -1192,15 +1215,15 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
return 0; return 0;
} }
} else { } else if (!automap) {
/* For address map controls, remap the address */ /* For address map controls, remap the address. */
if (addressmap_rewrite(socks->address, sizeof(socks->address))) { if (addressmap_rewrite(socks->address, sizeof(socks->address))) {
control_event_stream_status(conn, STREAM_EVENT_REMAP, control_event_stream_status(conn, STREAM_EVENT_REMAP,
REMAP_STREAM_SOURCE_CACHE); REMAP_STREAM_SOURCE_CACHE);
} }
} }
if (address_is_in_virtual_range(socks->address)) { if (!automap && address_is_in_virtual_range(socks->address)) {
/* This address was probably handed out by client_dns_get_unmapped_address, /* This address was probably handed out by client_dns_get_unmapped_address,
* but the mapping was discarded for some reason. We *don't* want to send * but the mapping was discarded for some reason. We *don't* want to send
* the address through Tor; that's likely to fail, and may leak * the address through Tor; that's likely to fail, and may leak
@ -1229,6 +1252,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
/* foo.exit -- modify conn->chosen_exit_node to specify the exit /* foo.exit -- modify conn->chosen_exit_node to specify the exit
* node, and conn->address to hold only the address portion.*/ * node, and conn->address to hold only the address portion.*/
char *s = strrchr(socks->address,'.'); char *s = strrchr(socks->address,'.');
tor_assert(!automap);
if (s) { if (s) {
if (s[1] != '\0') { if (s[1] != '\0') {
conn->chosen_exit_name = tor_strdup(s+1); conn->chosen_exit_name = tor_strdup(s+1);
@ -1294,8 +1318,10 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
return 0; return 0;
} }
tor_assert(!automap);
rep_hist_note_used_resolve(time(NULL)); /* help predict this next time */ rep_hist_note_used_resolve(time(NULL)); /* help predict this next time */
} else if (socks->command == SOCKS_COMMAND_CONNECT) { } else if (socks->command == SOCKS_COMMAND_CONNECT) {
tor_assert(!automap);
if (socks->port == 0) { if (socks->port == 0) {
log_notice(LD_APP,"Application asked to connect to port 0. Refusing."); log_notice(LD_APP,"Application asked to connect to port 0. Refusing.");
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
@ -1340,7 +1366,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
/* it's a hidden-service request */ /* it's a hidden-service request */
rend_cache_entry_t *entry; rend_cache_entry_t *entry;
int r; int r;
tor_assert(!automap);
if (SOCKS_COMMAND_IS_RESOLVE(socks->command)) { if (SOCKS_COMMAND_IS_RESOLVE(socks->command)) {
/* if it's a resolve request, fail it right now, rather than /* if it's a resolve request, fail it right now, rather than
* building all the circuits and then realizing it won't work. */ * building all the circuits and then realizing it won't work. */

View File

@ -1822,6 +1822,8 @@ typedef struct {
int TrackHostExitsExpire; /**< Number of seconds until we expire an int TrackHostExitsExpire; /**< Number of seconds until we expire an
* addressmap */ * addressmap */
config_line_t *AddressMap; /**< List of address map directives. */ config_line_t *AddressMap; /**< List of address map directives. */
int AutomapHostsOnResolve; /**< DOCDOC */
smartlist_t *AutomapHostsSuffixes; /**< DOCDOC */
int RendPostPeriod; /**< How often do we post each rendezvous service int RendPostPeriod; /**< How often do we post each rendezvous service
* descriptor? Remember to publish them independently. */ * descriptor? Remember to publish them independently. */
int KeepalivePeriod; /**< How often do we send padding cells to keep int KeepalivePeriod; /**< How often do we send padding cells to keep