2019-05-02 15:52:03 +02:00
|
|
|
/* Copyright (c) 2001 Matej Pfajfar.
|
|
|
|
* Copyright (c) 2001-2004, Roger Dingledine.
|
|
|
|
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
|
|
|
* Copyright (c) 2007-2019, The Tor Project, Inc. */
|
|
|
|
/* See LICENSE for licensing information */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @file relay_periodic.c
|
|
|
|
* @brief Periodic functions for the relay subsytem
|
|
|
|
**/
|
|
|
|
|
|
|
|
#include "orconfig.h"
|
|
|
|
#include "core/or/or.h"
|
|
|
|
|
|
|
|
#include "core/mainloop/periodic.h"
|
|
|
|
#include "core/mainloop/cpuworker.h" // XXXX use a pubsub event.
|
|
|
|
#include "core/mainloop/mainloop.h"
|
|
|
|
#include "core/mainloop/netstatus.h"
|
|
|
|
#include "core/or/circuituse.h" // XXXX move have_performed_bandwidth_test
|
|
|
|
|
|
|
|
#include "feature/relay/dns.h"
|
|
|
|
#include "feature/relay/relay_periodic.h"
|
|
|
|
#include "feature/relay/router.h"
|
|
|
|
#include "feature/relay/routerkeys.h"
|
|
|
|
#include "feature/relay/routermode.h"
|
|
|
|
#include "feature/relay/selftest.h"
|
2019-06-05 15:33:35 +02:00
|
|
|
#include "feature/stats/predict_ports.h"
|
2019-05-02 15:52:03 +02:00
|
|
|
|
|
|
|
#include "lib/crypt_ops/crypto_rand.h"
|
|
|
|
|
|
|
|
#include "feature/nodelist/routerinfo_st.h"
|
|
|
|
#include "feature/control/control_events.h"
|
|
|
|
|
2019-10-09 16:34:43 +02:00
|
|
|
#ifndef COCCI
|
2019-05-02 15:52:03 +02:00
|
|
|
#define DECLARE_EVENT(name, roles, flags) \
|
|
|
|
static periodic_event_item_t name ## _event = \
|
|
|
|
PERIODIC_EVENT(name, \
|
|
|
|
PERIODIC_EVENT_ROLE_##roles, \
|
|
|
|
flags)
|
2019-10-22 15:40:31 +02:00
|
|
|
#endif /* !defined(COCCI) */
|
2019-05-02 15:52:03 +02:00
|
|
|
|
|
|
|
#define FL(name) (PERIODIC_EVENT_FLAG_##name)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Periodic callback: If we're a server and initializing dns failed, retry.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
retry_dns_callback(time_t now, const or_options_t *options)
|
|
|
|
{
|
|
|
|
(void)now;
|
|
|
|
#define RETRY_DNS_INTERVAL (10*60)
|
|
|
|
if (server_mode(options) && has_dns_init_failed())
|
|
|
|
dns_init();
|
|
|
|
return RETRY_DNS_INTERVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
DECLARE_EVENT(retry_dns, ROUTER, 0);
|
|
|
|
|
|
|
|
static int dns_honesty_first_time = 1;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Periodic event: if we're an exit, see if our DNS server is telling us
|
|
|
|
* obvious lies.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
check_dns_honesty_callback(time_t now, const or_options_t *options)
|
|
|
|
{
|
|
|
|
(void)now;
|
|
|
|
/* 9. and if we're an exit node, check whether our DNS is telling stories
|
|
|
|
* to us. */
|
|
|
|
if (net_is_disabled() ||
|
|
|
|
! public_server_mode(options) ||
|
|
|
|
router_my_exit_policy_is_reject_star())
|
|
|
|
return PERIODIC_EVENT_NO_UPDATE;
|
|
|
|
|
|
|
|
if (dns_honesty_first_time) {
|
|
|
|
/* Don't launch right when we start */
|
|
|
|
dns_honesty_first_time = 0;
|
|
|
|
return crypto_rand_int_range(60, 180);
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_launch_correctness_checks();
|
|
|
|
return 12*3600 + crypto_rand_int(12*3600);
|
|
|
|
}
|
|
|
|
|
|
|
|
DECLARE_EVENT(check_dns_honesty, RELAY, FL(NEED_NET));
|
|
|
|
|
|
|
|
/* Periodic callback: rotate the onion keys after the period defined by the
|
|
|
|
* "onion-key-rotation-days" consensus parameter, shut down and restart all
|
|
|
|
* cpuworkers, and update our descriptor if necessary.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
rotate_onion_key_callback(time_t now, const or_options_t *options)
|
|
|
|
{
|
|
|
|
if (server_mode(options)) {
|
|
|
|
int onion_key_lifetime = get_onion_key_lifetime();
|
|
|
|
time_t rotation_time = get_onion_key_set_at()+onion_key_lifetime;
|
|
|
|
if (rotation_time > now) {
|
|
|
|
return ONION_KEY_CONSENSUS_CHECK_INTERVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
log_info(LD_GENERAL,"Rotating onion key.");
|
|
|
|
rotate_onion_key();
|
|
|
|
cpuworkers_rotate_keyinfo();
|
|
|
|
if (router_rebuild_descriptor(1)<0) {
|
|
|
|
log_info(LD_CONFIG, "Couldn't rebuild router descriptor");
|
|
|
|
}
|
|
|
|
if (advertised_server_mode() && !net_is_disabled())
|
|
|
|
router_upload_dir_desc_to_dirservers(0);
|
|
|
|
return ONION_KEY_CONSENSUS_CHECK_INTERVAL;
|
|
|
|
}
|
|
|
|
return PERIODIC_EVENT_NO_UPDATE;
|
|
|
|
}
|
|
|
|
|
|
|
|
DECLARE_EVENT(rotate_onion_key, ROUTER, 0);
|
|
|
|
|
|
|
|
/** Periodic callback: consider rebuilding or and re-uploading our descriptor
|
|
|
|
* (if we've passed our internal checks). */
|
|
|
|
static int
|
|
|
|
check_descriptor_callback(time_t now, const or_options_t *options)
|
|
|
|
{
|
|
|
|
/** How often do we check whether part of our router info has changed in a
|
|
|
|
* way that would require an upload? That includes checking whether our IP
|
|
|
|
* address has changed. */
|
|
|
|
#define CHECK_DESCRIPTOR_INTERVAL (60)
|
|
|
|
|
|
|
|
(void)options;
|
|
|
|
|
|
|
|
/* 2b. Once per minute, regenerate and upload the descriptor if the old
|
|
|
|
* one is inaccurate. */
|
|
|
|
if (!net_is_disabled()) {
|
|
|
|
check_descriptor_bandwidth_changed(now);
|
|
|
|
check_descriptor_ipaddress_changed(now);
|
|
|
|
mark_my_descriptor_dirty_if_too_old(now);
|
|
|
|
consider_publishable_server(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return CHECK_DESCRIPTOR_INTERVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
DECLARE_EVENT(check_descriptor, ROUTER, FL(NEED_NET));
|
|
|
|
|
|
|
|
static int dirport_reachability_count = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Periodic callback: check whether we're reachable (as a relay), and
|
|
|
|
* whether our bandwidth has changed enough that we need to
|
|
|
|
* publish a new descriptor.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
check_for_reachability_bw_callback(time_t now, const or_options_t *options)
|
|
|
|
{
|
|
|
|
/* XXXX This whole thing was stuck in the middle of what is now
|
|
|
|
* XXXX check_descriptor_callback. I'm not sure it's right. */
|
|
|
|
|
|
|
|
/* also, check religiously for reachability, if it's within the first
|
|
|
|
* 20 minutes of our uptime. */
|
|
|
|
if (server_mode(options) &&
|
|
|
|
(have_completed_a_circuit() || !any_predicted_circuits(now)) &&
|
|
|
|
!net_is_disabled()) {
|
|
|
|
if (get_uptime() < TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) {
|
|
|
|
router_do_reachability_checks(1, dirport_reachability_count==0);
|
|
|
|
if (++dirport_reachability_count > 5)
|
|
|
|
dirport_reachability_count = 0;
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
/* If we haven't checked for 12 hours and our bandwidth estimate is
|
|
|
|
* low, do another bandwidth test. This is especially important for
|
|
|
|
* bridges, since they might go long periods without much use. */
|
|
|
|
const routerinfo_t *me = router_get_my_routerinfo();
|
|
|
|
static int first_time = 1;
|
|
|
|
if (!first_time && me &&
|
|
|
|
me->bandwidthcapacity < me->bandwidthrate &&
|
|
|
|
me->bandwidthcapacity < 51200) {
|
|
|
|
reset_bandwidth_test();
|
|
|
|
}
|
|
|
|
first_time = 0;
|
|
|
|
#define BANDWIDTH_RECHECK_INTERVAL (12*60*60)
|
|
|
|
return BANDWIDTH_RECHECK_INTERVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return CHECK_DESCRIPTOR_INTERVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
DECLARE_EVENT(check_for_reachability_bw, ROUTER, FL(NEED_NET));
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Callback: Send warnings if Tor doesn't find its ports reachable.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
reachability_warnings_callback(time_t now, const or_options_t *options)
|
|
|
|
{
|
|
|
|
(void) now;
|
|
|
|
|
|
|
|
if (get_uptime() < TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) {
|
|
|
|
return (int)(TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT - get_uptime());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (server_mode(options) &&
|
|
|
|
!net_is_disabled() &&
|
|
|
|
have_completed_a_circuit()) {
|
|
|
|
/* every 20 minutes, check and complain if necessary */
|
|
|
|
const routerinfo_t *me = router_get_my_routerinfo();
|
|
|
|
if (me && !check_whether_orport_reachable(options)) {
|
|
|
|
char *address = tor_dup_ip(me->addr);
|
|
|
|
log_warn(LD_CONFIG,"Your server (%s:%d) has not managed to confirm that "
|
|
|
|
"its ORPort is reachable. Relays do not publish descriptors "
|
|
|
|
"until their ORPort and DirPort are reachable. Please check "
|
|
|
|
"your firewalls, ports, address, /etc/hosts file, etc.",
|
|
|
|
address, me->or_port);
|
|
|
|
control_event_server_status(LOG_WARN,
|
|
|
|
"REACHABILITY_FAILED ORADDRESS=%s:%d",
|
|
|
|
address, me->or_port);
|
|
|
|
tor_free(address);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (me && !check_whether_dirport_reachable(options)) {
|
|
|
|
char *address = tor_dup_ip(me->addr);
|
|
|
|
log_warn(LD_CONFIG,
|
|
|
|
"Your server (%s:%d) has not managed to confirm that its "
|
|
|
|
"DirPort is reachable. Relays do not publish descriptors "
|
|
|
|
"until their ORPort and DirPort are reachable. Please check "
|
|
|
|
"your firewalls, ports, address, /etc/hosts file, etc.",
|
|
|
|
address, me->dir_port);
|
|
|
|
control_event_server_status(LOG_WARN,
|
|
|
|
"REACHABILITY_FAILED DIRADDRESS=%s:%d",
|
|
|
|
address, me->dir_port);
|
|
|
|
tor_free(address);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT;
|
|
|
|
}
|
|
|
|
|
|
|
|
DECLARE_EVENT(reachability_warnings, ROUTER, FL(NEED_NET));
|
|
|
|
|
|
|
|
/* Periodic callback: Every 30 seconds, check whether it's time to make new
|
|
|
|
* Ed25519 subkeys.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
check_ed_keys_callback(time_t now, const or_options_t *options)
|
|
|
|
{
|
|
|
|
if (server_mode(options)) {
|
|
|
|
if (should_make_new_ed_keys(options, now)) {
|
|
|
|
int new_signing_key = load_ed_keys(options, now);
|
|
|
|
if (new_signing_key < 0 ||
|
|
|
|
generate_ed_link_cert(options, now, new_signing_key > 0)) {
|
|
|
|
log_err(LD_OR, "Unable to update Ed25519 keys! Exiting.");
|
|
|
|
tor_shutdown_event_loop_and_exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 30;
|
|
|
|
}
|
|
|
|
return PERIODIC_EVENT_NO_UPDATE;
|
|
|
|
}
|
|
|
|
|
|
|
|
DECLARE_EVENT(check_ed_keys, ROUTER, 0);
|
|
|
|
|
|
|
|
/* Period callback: Check if our old onion keys are still valid after the
|
|
|
|
* period of time defined by the consensus parameter
|
|
|
|
* "onion-key-grace-period-days", otherwise expire them by setting them to
|
|
|
|
* NULL.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
check_onion_keys_expiry_time_callback(time_t now, const or_options_t *options)
|
|
|
|
{
|
|
|
|
if (server_mode(options)) {
|
|
|
|
int onion_key_grace_period = get_onion_key_grace_period();
|
|
|
|
time_t expiry_time = get_onion_key_set_at()+onion_key_grace_period;
|
|
|
|
if (expiry_time > now) {
|
|
|
|
return ONION_KEY_CONSENSUS_CHECK_INTERVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
log_info(LD_GENERAL, "Expiring old onion keys.");
|
|
|
|
expire_old_onion_keys();
|
|
|
|
cpuworkers_rotate_keyinfo();
|
|
|
|
return ONION_KEY_CONSENSUS_CHECK_INTERVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return PERIODIC_EVENT_NO_UPDATE;
|
|
|
|
}
|
|
|
|
|
|
|
|
DECLARE_EVENT(check_onion_keys_expiry_time, ROUTER, 0);
|
|
|
|
|
|
|
|
void
|
|
|
|
relay_register_periodic_events(void)
|
|
|
|
{
|
|
|
|
periodic_events_register(&retry_dns_event);
|
|
|
|
periodic_events_register(&check_dns_honesty_event);
|
|
|
|
periodic_events_register(&rotate_onion_key_event);
|
|
|
|
periodic_events_register(&check_descriptor_event);
|
|
|
|
periodic_events_register(&check_for_reachability_bw_event);
|
|
|
|
periodic_events_register(&reachability_warnings_event);
|
|
|
|
periodic_events_register(&check_ed_keys_event);
|
|
|
|
periodic_events_register(&check_onion_keys_expiry_time_event);
|
|
|
|
|
|
|
|
dns_honesty_first_time = 1;
|
|
|
|
dirport_reachability_count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Update our schedule so that we'll check whether we need to update our
|
|
|
|
* descriptor immediately, rather than after up to CHECK_DESCRIPTOR_INTERVAL
|
|
|
|
* seconds.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
reschedule_descriptor_update_check(void)
|
|
|
|
{
|
|
|
|
periodic_event_reschedule(&check_descriptor_event);
|
|
|
|
}
|