Merge branch 'reapply-exit-policy-on-reload' into 'main'

reapply exit policy on reload

Closes #40676

See merge request tpo/core/tor!735
This commit is contained in:
David Goulet 2023-08-25 16:55:40 +00:00
commit 4f21fc0fe4
8 changed files with 96 additions and 1 deletions

4
changes/ticket40676 Normal file
View File

@ -0,0 +1,4 @@
o Minor feature (exit policies):
- Implement reevaluating new exit policy against existing connections. This
is controlled by new config option ReevaluateExitPolicy, defaulting to 0.
Closes ticket 40676.

View File

@ -2385,6 +2385,16 @@ is non-zero):
policy options are set, Tor behaves as if ExitRelay were set to 0.
(Default: auto)
[[ReevaluateExitPolicy]] **ReevaluateExitPolicy** **0**|**1**::
If set, reevaluate the exit policy on existing connections when reloading
configuration. +
+
When the exit policy of an exit node change while reloading configuration,
connections made prior to this change could violate the new policy. By
setting this to 1, Tor will check if such connections exist, and mark them
for termination.
(Default: 0)
[[ExtendAllowPrivateAddresses]] **ExtendAllowPrivateAddresses** **0**|**1**::
When this option is enabled, Tor will connect to relays on localhost,
RFC1918 addresses, and so on. In particular, Tor will make direct OR

View File

@ -637,6 +637,7 @@ static const config_var_t option_vars_[] = {
V(RephistTrackTime, INTERVAL, "24 hours"),
V_IMMUTABLE(RunAsDaemon, BOOL, "0"),
V(ReducedExitPolicy, BOOL, "0"),
V(ReevaluateExitPolicy, BOOL, "0"),
OBSOLETE("RunTesting"), // currently unused
V_IMMUTABLE(Sandbox, BOOL, "0"),
V(SafeLogging, STRING, "1"),
@ -996,6 +997,7 @@ set_options(or_options_t *new_val, char **msg)
config_line_t *changes =
config_get_changes(get_options_mgr(), old_options, new_val);
control_event_conf_changed(changes);
connection_reapply_exit_policy(changes);
config_free_lines(changes);
}

View File

@ -141,6 +141,8 @@ struct or_options_t {
* Includes OutboundBindAddresses and
* configured ports. */
int ReducedExitPolicy; /**<Should we use the Reduced Exit Policy? */
int ReevaluateExitPolicy; /**<Should we re-evaluate Exit Policy on existing
* connections when it changes? */
struct config_line_t *SocksPolicy; /**< Lists of socks policy components */
struct config_line_t *DirPolicy; /**< Lists of dir policy components */
/** Local address to bind outbound sockets */

View File

@ -225,6 +225,10 @@
#ExitPolicy accept6 *6:119 # accept nntp ports on IPv6 only as well as default exit policy
#ExitPolicy reject *:* # no exits allowed
## Uncomment this if you want your exit relay to reevaluate its exit policy on
## existing connections when the exit policy is modified.
#ReevaluateExitPolicy 1
## Bridge relays (or "bridges") are Tor relays that aren't listed in the
## main directory. Since there is no complete public list of them, even an
## ISP that filters connections to all the known Tor relays probably

View File

@ -105,6 +105,7 @@
#include "lib/buf/buffers.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_util.h"
#include "lib/encoding/confline.h"
#include "core/or/cell_st.h"
#include "core/or/cpath_build_state_st.h"
@ -4237,6 +4238,76 @@ my_exit_policy_rejects(const tor_addr_t *addr,
return 0;
}
/* Reapply exit policy to existing connections, possibly terminating
* connections
* no longer allowed by the policy.
*/
void
connection_reapply_exit_policy(config_line_t *changes)
{
int marked_for_close = 0;
smartlist_t *conn_list = NULL;
smartlist_t *policy = NULL;
int config_change_relevant = 0;
if (get_options()->ReevaluateExitPolicy == 0) {
return;
}
for (const config_line_t *line = changes;
line && !config_change_relevant;
line = line->next) {
const char* exit_policy_options[] = {
"ExitRelay",
"ExitPolicy",
"ReducedExitPolicy",
"ReevaluateExitPolicy",
"IPv6Exit",
NULL
};
for (unsigned int i = 0; exit_policy_options[i] != NULL; ++i) {
if (strcmp(line->key, exit_policy_options[i]) == 0) {
config_change_relevant = 1;
break;
}
}
}
if (!config_change_relevant) {
/* Policy did not change: no need to iterate over connections */
return;
}
// we can't use router_compare_to_my_exit_policy as it depend on the
// descriptor, which is regenerated asynchronously, so we have to parse the
// policy ourselves.
// We don't verify for our own IP, it's not part of the configuration.
if (BUG(policies_parse_exit_policy_from_options(get_options(), NULL, NULL,
&policy) != 0)) {
return;
}
conn_list = connection_list_by_type_purpose(CONN_TYPE_EXIT,
EXIT_PURPOSE_CONNECT);
SMARTLIST_FOREACH_BEGIN(conn_list, connection_t *, conn) {
addr_policy_result_t verdict = compare_tor_addr_to_addr_policy(&conn->addr,
conn->port,
policy);
if (verdict != ADDR_POLICY_ACCEPTED) {
connection_edge_end(TO_EDGE_CONN(conn), END_STREAM_REASON_EXITPOLICY);
connection_mark_for_close(conn);
++marked_for_close;
}
} SMARTLIST_FOREACH_END(conn);
smartlist_free(conn_list);
smartlist_free(policy);
log_info(LD_GENERAL, "Marked %d connections to be closed as no longer "
"allowed per ExitPolicy", marked_for_close);
}
/** Return true iff the consensus allows network reentry. The default value is
* false if the parameter is not found. */
static bool

View File

@ -13,6 +13,7 @@
#define TOR_CONNECTION_EDGE_H
#include "lib/testsupport/testsupport.h"
#include "lib/encoding/confline.h"
#include "feature/hs/hs_service.h"
@ -101,6 +102,7 @@ void connection_entry_set_controller_wait(entry_connection_t *conn);
void connection_ap_about_to_close(entry_connection_t *edge_conn);
void connection_exit_about_to_close(edge_connection_t *edge_conn);
void connection_reapply_exit_policy(config_line_t *changes);
MOCK_DECL(int,
connection_ap_handshake_send_begin,(entry_connection_t *ap_conn));

View File

@ -1066,7 +1066,7 @@ socks_policy_permits_address(const tor_addr_t *addr)
}
/** Return 1 if <b>addr</b> is permitted to connect to our metrics port,
* based on <b>socks_policy</b>. Else return 0.
* based on <b>metrics_policy</b>. Else return 0.
*/
int
metrics_policy_permits_address(const tor_addr_t *addr)