Merge branch 'disable_network'

This commit is contained in:
Nick Mathewson
2011-11-29 17:52:23 -05:00
12 changed files with 138 additions and 32 deletions
+9
View File
@@ -0,0 +1,9 @@
o Minor features:
- New "DisableNetwork" option to prevent Tor from launching any
connections or accepting any connections except on a control
port. Some bundles and controllers want to use this so they can
configure Tor before letting Tor talk to the rest of the
network--for example, to prevent any connections from being made
to a non-bridge address.
+6
View File
@@ -125,6 +125,12 @@ Other options can be specified either on the command-line (--option
You probably don't need to adjust this. It has no effect on Windows
since that platform lacks getrlimit(). (Default: 1000)
**DisableNetwork** **0**|**1**::
When this option is set, we don't listen for or accept any connections
other than controller connections, and we don't make any outbound
connections. Controllers sometimes use this option to avoid using
the network until Tor is fully configured. (Default: 0)
**ConstrainedSockets** **0**|**1**::
If set, Tor will tell the kernel to attempt to shrink the buffers for all
sockets to the size specified in **ConstrainedSockSize**. This is useful for
+12 -1
View File
@@ -231,6 +231,7 @@ static config_var_t _option_vars[] = {
V(CountPrivateBandwidth, BOOL, "0"),
V(DataDirectory, FILENAME, NULL),
OBSOLETE("DebugLogFile"),
V(DisableNetwork, BOOL, "0"),
V(DirAllowPrivateAddresses, BOOL, NULL),
V(TestingAuthDirTimeToLearnReachability, INTERVAL, "30 minutes"),
V(DirListenAddress, LINELIST, NULL),
@@ -1100,13 +1101,22 @@ options_act_reversible(const or_options_t *old_options, char **msg)
consider_hibernation(time(NULL));
/* Launch the listeners. (We do this before we setuid, so we can bind to
* ports under 1024.) We don't want to rebind if we're hibernating. */
* ports under 1024.) We don't want to rebind if we're hibernating. If
* networking is disabled, this will close all but the control listeners,
* but disable those. */
if (!we_are_hibernating()) {
if (retry_all_listeners(replaced_listeners, new_listeners) < 0) {
*msg = tor_strdup("Failed to bind one of the listener ports.");
goto rollback;
}
}
if (options->DisableNetwork) {
/* Aggressively close non-controller stuff, NOW */
log_notice(LD_NET, "DisableNetwork is set. Tor will not make or accept "
"non-control network connections. Shutting down all existing "
"connections.");
connection_mark_all_noncontrol_connections();
}
}
#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
@@ -4187,6 +4197,7 @@ options_transition_affects_descriptor(const or_options_t *old_options,
old_options->ORPort != new_options->ORPort ||
old_options->DirPort != new_options->DirPort ||
old_options->ClientOnly != new_options->ClientOnly ||
old_options->DisableNetwork != new_options->DisableNetwork ||
old_options->_PublishServerDescriptor !=
new_options->_PublishServerDescriptor ||
get_effective_bwrate(old_options) != get_effective_bwrate(new_options) ||
+63 -5
View File
@@ -1318,6 +1318,24 @@ connection_connect(connection_t *conn, const char *address,
else
protocol_family = PF_INET;
if (get_options()->DisableNetwork) {
/* We should never even try to connect anyplace if DisableNetwork is set.
* Warn if we do, and refuse to make the connection. */
static ratelim_t disablenet_violated = RATELIM_INIT(30*60);
char *m;
#ifdef MS_WINDOWS
*socket_error = WSAENETUNREACH;
#else
*socket_error = ENETUNREACH;
#endif
if ((m = rate_limit_log(&disablenet_violated, approx_time()))) {
log_warn(LD_BUG, "Tried to open a socket with DisableNetwork set.%s", m);
tor_free(m);
}
tor_fragile_assert();
return -1;
}
s = tor_open_socket(protocol_family,SOCK_STREAM,IPPROTO_TCP);
if (s < 0) {
*socket_error = tor_socket_errno(-1);
@@ -1968,7 +1986,7 @@ retry_all_listeners(smartlist_t *replaced_conns,
smartlist_add(listeners, conn);
} SMARTLIST_FOREACH_END(conn);
if (! options->ClientOnly) {
if (! options->ClientOnly && ! options->DisableNetwork) {
if (retry_listeners(listeners,
CONN_TYPE_OR_LISTENER, options->ORListenAddress,
options->ORPort, "0.0.0.0",
@@ -1981,10 +1999,13 @@ retry_all_listeners(smartlist_t *replaced_conns,
retval = -1;
}
if (retry_listener_ports(listeners,
get_configured_client_ports(),
new_conns) < 0)
retval = -1;
if (!options->DisableNetwork) {
if (retry_listener_ports(listeners,
get_configured_client_ports(),
new_conns) < 0)
retval = -1;
}
if (retry_listeners(listeners,
CONN_TYPE_CONTROL_LISTENER,
options->ControlListenAddress,
@@ -2025,6 +2046,43 @@ retry_all_listeners(smartlist_t *replaced_conns,
return retval;
}
/** Mark every listener of type other than CONTROL_LISTENER to be closed. */
void
connection_mark_all_noncontrol_listeners(void)
{
SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
if (conn->marked_for_close)
continue;
if (conn->type == CONN_TYPE_CONTROL_LISTENER)
continue;
if (connection_is_listener(conn))
connection_mark_for_close(conn);
} SMARTLIST_FOREACH_END(conn);
}
/** Mark every external conection not used for controllers for close. */
void
connection_mark_all_noncontrol_connections(void)
{
SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
if (conn->marked_for_close)
continue;
switch (conn->type) {
case CONN_TYPE_CPUWORKER:
case CONN_TYPE_CONTROL_LISTENER:
case CONN_TYPE_CONTROL:
break;
case CONN_TYPE_AP:
connection_mark_unattached_ap(TO_ENTRY_CONN(conn),
END_STREAM_REASON_HIBERNATING);
break;
default:
connection_mark_for_close(conn);
break;
}
} SMARTLIST_FOREACH_END(conn);
}
/** Return 1 if we should apply rate limiting to <b>conn</b>, and 0
* otherwise.
* Right now this just checks if it's an internal IP address or an
+3
View File
@@ -66,6 +66,9 @@ int get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type,
int retry_all_listeners(smartlist_t *replaced_conns,
smartlist_t *new_conns);
void connection_mark_all_noncontrol_listeners(void);
void connection_mark_all_noncontrol_connections(void);
ssize_t connection_bucket_write_limit(connection_t *conn, time_t now);
int global_write_bucket_low(connection_t *conn, size_t attempt, int priority);
void connection_bucket_init(void);
+7
View File
@@ -1395,6 +1395,10 @@ launch_resolve(edge_connection_t *exitconn)
int r;
int options = get_options()->ServerDNSSearchDomains ? 0
: DNS_QUERY_NO_SEARCH;
if (get_options()->DisableNetwork)
return -1;
/* What? Nameservers not configured? Sounds like a bug. */
if (!nameservers_configured) {
log_warn(LD_EXIT, "(Harmless.) Nameservers not configured, but resolve "
@@ -1601,6 +1605,9 @@ launch_test_addresses(int fd, short event, void *args)
(void)event;
(void)args;
if (options->DisableNetwork)
return;
log_info(LD_EXIT, "Launching checks to see whether our nameservers like to "
"hijack *everything*.");
/* This situation is worse than the failure-hijacking situation. When this
+1 -10
View File
@@ -735,7 +735,6 @@ hibernate_soft_limit_reached(void)
static void
hibernate_begin(hibernate_state_t new_state, time_t now)
{
connection_t *conn;
const or_options_t *options = get_options();
if (new_state == HIBERNATE_STATE_EXITING &&
@@ -756,15 +755,7 @@ hibernate_begin(hibernate_state_t new_state, time_t now)
}
/* close listeners. leave control listener(s). */
while ((conn = connection_get_by_type(CONN_TYPE_OR_LISTENER)) ||
(conn = connection_get_by_type(CONN_TYPE_AP_LISTENER)) ||
(conn = connection_get_by_type(CONN_TYPE_AP_TRANS_LISTENER)) ||
(conn = connection_get_by_type(CONN_TYPE_AP_DNS_LISTENER)) ||
(conn = connection_get_by_type(CONN_TYPE_AP_NATD_LISTENER)) ||
(conn = connection_get_by_type(CONN_TYPE_DIR_LISTENER))) {
log_info(LD_NET,"Closing listener type %d", conn->type);
connection_mark_for_close(conn);
}
connection_mark_all_noncontrol_listeners();
/* XXX kill intro point circs */
/* XXX upload rendezvous service descriptors with no intro points */
+16 -13
View File
@@ -934,7 +934,7 @@ directory_info_has_arrived(time_t now, int from_cache)
update_extrainfo_downloads(now);
}
if (server_mode(options) && !we_are_hibernating() && !from_cache &&
if (server_mode(options) && !net_is_disabled() && !from_cache &&
(can_complete_circuit || !any_predicted_circuits(now)))
consider_testing_reachability(1, 1);
}
@@ -1161,11 +1161,11 @@ run_scheduled_events(time_t now)
if (router_rebuild_descriptor(1)<0) {
log_info(LD_CONFIG, "Couldn't rebuild router descriptor");
}
if (advertised_server_mode())
if (advertised_server_mode() & !options->DisableNetwork)
router_upload_dir_desc_to_dirservers(0);
}
if (time_to_try_getting_descriptors < now) {
if (!options->DisableNetwork && time_to_try_getting_descriptors < now) {
update_all_descriptor_downloads(now);
update_extrainfo_downloads(now);
if (router_have_minimum_dir_info())
@@ -1219,7 +1219,7 @@ run_scheduled_events(time_t now)
if (time_to_launch_reachability_tests < now &&
(authdir_mode_tests_reachability(options)) &&
!we_are_hibernating()) {
!net_is_disabled()) {
time_to_launch_reachability_tests = now + REACHABILITY_TEST_INTERVAL;
/* try to determine reachability of the other Tor relays */
dirserv_test_reachability(now);
@@ -1355,7 +1355,7 @@ run_scheduled_events(time_t now)
/* 2b. Once per minute, regenerate and upload the descriptor if the old
* one is inaccurate. */
if (time_to_check_descriptor < now) {
if (time_to_check_descriptor < now && !options->DisableNetwork) {
static int dirport_reachability_count = 0;
time_to_check_descriptor = now + CHECK_DESCRIPTOR_INTERVAL;
check_descriptor_bandwidth_changed(now);
@@ -1430,7 +1430,7 @@ run_scheduled_events(time_t now)
connection_expire_held_open();
/** 3d. And every 60 seconds, we relaunch listeners if any died. */
if (!we_are_hibernating() && time_to_check_listeners < now) {
if (!net_is_disabled() && time_to_check_listeners < now) {
retry_all_listeners(NULL, NULL);
time_to_check_listeners = now+60;
}
@@ -1441,7 +1441,7 @@ run_scheduled_events(time_t now)
* and we make a new circ if there are no clean circuits.
*/
have_dir_info = router_have_minimum_dir_info();
if (have_dir_info && !we_are_hibernating())
if (have_dir_info && !net_is_disabled())
circuit_build_needed_circs(now);
/* every 10 seconds, but not at the same second as other such events */
@@ -1472,7 +1472,7 @@ run_scheduled_events(time_t now)
circuit_close_all_marked();
/** 7. And upload service descriptors if necessary. */
if (can_complete_circuit && !we_are_hibernating()) {
if (can_complete_circuit && !net_is_disabled()) {
rend_consider_services_upload(now);
rend_consider_descriptor_republication();
}
@@ -1489,7 +1489,8 @@ run_scheduled_events(time_t now)
/** 9. and if we're a server, check whether our DNS is telling stories to
* us. */
if (public_server_mode(options) && time_to_check_for_correct_dns < now) {
if (!net_is_disabled() &&
public_server_mode(options) && time_to_check_for_correct_dns < now) {
if (!time_to_check_for_correct_dns) {
time_to_check_for_correct_dns = now + 60 + crypto_rand_int(120);
} else {
@@ -1508,7 +1509,8 @@ run_scheduled_events(time_t now)
}
/** 11. check the port forwarding app */
if (time_to_check_port_forwarding < now &&
if (!net_is_disabled() &&
time_to_check_port_forwarding < now &&
options->PortForwarding &&
is_server) {
#define PORT_FORWARDING_CHECK_INTERVAL 5
@@ -1520,7 +1522,7 @@ run_scheduled_events(time_t now)
}
/** 11b. check pending unconfigured managed proxies */
if (pt_proxies_configuration_pending())
if (!net_is_disabled() && pt_proxies_configuration_pending())
pt_configure_remaining_proxies();
/** 11c. validate pluggable transports configuration if we need to */
@@ -1592,7 +1594,7 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg)
control_event_stream_bandwidth_used();
if (server_mode(options) &&
!we_are_hibernating() &&
!net_is_disabled() &&
seconds_elapsed > 0 &&
can_complete_circuit &&
stats_n_seconds_working / TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT !=
@@ -1793,7 +1795,8 @@ do_hup(void)
/* retry appropriate downloads */
router_reset_status_download_failures();
router_reset_descriptor_download_failures();
update_networkstatus_downloads(time(NULL));
if (!options->DisableNetwork)
update_networkstatus_downloads(time(NULL));
/* We'll retry routerstatus downloads in about 10 seconds; no need to
* force a retry there. */
+4
View File
@@ -3455,6 +3455,10 @@ typedef struct {
* issue. */
int UserspaceIOCPBuffers;
/** If 1, we accept and launch no external network connections, except on
* control ports. */
int DisableNetwork;
} or_options_t;
/** Persistent state for an onion router, as saved to disk. */
+10 -2
View File
@@ -780,7 +780,7 @@ check_whether_dirport_reachable(void)
const or_options_t *options = get_options();
return !options->DirPort ||
options->AssumeReachable ||
we_are_hibernating() ||
net_is_disabled() ||
can_reach_dir_port;
}
@@ -806,7 +806,7 @@ decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port)
return 0;
if (authdir_mode(options)) /* always publish */
return dir_port;
if (we_are_hibernating())
if (net_is_disabled())
return 0;
if (!check_whether_dirport_reachable())
return 0;
@@ -974,6 +974,14 @@ router_perform_bandwidth_test(int num_circs, time_t now)
}
}
/** Return true iff our network is in some sense disabled: either we're
* hibernating, entering hibernation, or */
int
net_is_disabled(void)
{
return get_options()->DisableNetwork || we_are_hibernating();
}
/** Return true iff we believe ourselves to be an authoritative
* directory server.
*/
+2
View File
@@ -39,6 +39,8 @@ void router_orport_found_reachable(void);
void router_dirport_found_reachable(void);
void router_perform_bandwidth_test(int num_circs, time_t now);
int net_is_disabled(void);
int authdir_mode(const or_options_t *options);
int authdir_mode_v1(const or_options_t *options);
int authdir_mode_v2(const or_options_t *options);
+5 -1
View File
@@ -3244,7 +3244,7 @@ router_set_status(const char *digest, int up)
log_debug(LD_DIR,"Marking router %s as %s.",
node_describe(node), up ? "up" : "down");
#endif
if (!up && node_is_me(node) && !we_are_hibernating())
if (!up && node_is_me(node) && !net_is_disabled())
log_warn(LD_NET, "We just marked ourself as down. Are your external "
"addresses reachable?");
node->is_running = up;
@@ -4009,6 +4009,8 @@ signed_desc_digest_is_recognized(signed_descriptor_t *desc)
void
update_all_descriptor_downloads(time_t now)
{
if (get_options()->DisableNetwork)
return;
update_router_descriptor_downloads(now);
update_microdesc_downloads(now);
launch_dummy_descriptor_download_as_needed(now, get_options());
@@ -4021,6 +4023,8 @@ routerlist_retry_directory_downloads(time_t now)
{
router_reset_status_download_failures();
router_reset_descriptor_download_failures();
if (get_options()->DisableNetwork)
return;
update_networkstatus_downloads(now);
update_all_descriptor_downloads(now);
}