From: dzwdz Date: Sun, 24 Aug 2025 18:25:08 +0000 (+0200) Subject: save PT bridge lines to disk X-Git-Tag: tor-0.4.9.3-alpha~20^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=892dc508dbbbcacf583eb879325c97f36d468c99;p=thirdparty%2Ftor.git save PT bridge lines to disk Solves https://gitlab.torproject.org/tpo/core/tor/-/issues/29128. pt_update_bridge_lines() was based on pt_get_extra_info_descriptor_string(). In particular, I copied the behaviour of not printing IPv6 addresses if IPv4 is present. I'll make both functions use IPv6 in another MR. That function is called when the IP or key changes. Sadly, I don't remember how I decided from where exactly to call it (I wrote this ages ago), but it seems fine? --- diff --git a/changes/ticket29128 b/changes/ticket29128 new file mode 100644 index 0000000000..7831038e6e --- /dev/null +++ b/changes/ticket29128 @@ -0,0 +1,2 @@ + o Minor features (bridges): + - Save complete bridge lines to 'datadir/bridgelines'. Closes ticket 29128. diff --git a/doc/man/tor.1.txt b/doc/man/tor.1.txt index 89df857f58..c1a3e5fe42 100644 --- a/doc/man/tor.1.txt +++ b/doc/man/tor.1.txt @@ -4103,6 +4103,10 @@ __DataDirectory__/**`hashed-fingerprint`**:: Only used by bridges. Contains the hashed fingerprint of the bridge's identity key. (That is, the hash of the hash of the identity key.) +__DataDirectory__/**`bridgelines`**:: + Only used by bridges. Contains the bridge lines that clients can use to + connect using pluggable transports. + __DataDirectory__/**`approved-routers`**:: Only used by authoritative directory servers. Each line lists a status and an identity, separated by whitespace. Identities can be hex-encoded RSA diff --git a/src/app/config/resolve_addr.c b/src/app/config/resolve_addr.c index 130998b7c8..90c99d423d 100644 --- a/src/app/config/resolve_addr.c +++ b/src/app/config/resolve_addr.c @@ -13,6 +13,7 @@ #include "core/mainloop/mainloop.h" +#include "feature/client/transports.h" #include "feature/control/control_events.h" #include "feature/dirauth/authmode.h" @@ -132,14 +133,18 @@ resolved_addr_set_suggested(const tor_addr_t *addr) } /* In case we don't have a configured address, log that we will be using the - * one discovered from the dirauth. */ + * one discovered from the dirauth, and, if running a bridge, use the new IP + * for the bridge lines. */ const int idx = af_to_idx(tor_addr_family(addr)); if (tor_addr_is_null(&last_resolved_addrs[idx]) && !tor_addr_eq(&last_suggested_addrs[idx], addr)) { log_notice(LD_CONFIG, "External address seen and suggested by a " "directory authority: %s", fmt_addr(addr)); + tor_addr_copy(&last_suggested_addrs[idx], addr); + pt_update_bridge_lines(); + } else { + tor_addr_copy(&last_suggested_addrs[idx], addr); } - tor_addr_copy(&last_suggested_addrs[idx], addr); } /** Copy the last resolved address of family into addr_out. diff --git a/src/core/mainloop/mainloop.c b/src/core/mainloop/mainloop.c index 658b4b47ee..963cb00128 100644 --- a/src/core/mainloop/mainloop.c +++ b/src/core/mainloop/mainloop.c @@ -2332,6 +2332,7 @@ ip_address_changed(int on_client_conn) reset_bandwidth_test(); reset_uptime(); router_reset_reachability(); + pt_update_bridge_lines(); /* All relays include their IP addresses as their ORPort addresses in * their descriptor. * Exit relays also incorporate interface addresses in their exit diff --git a/src/feature/client/transports.c b/src/feature/client/transports.c index 878675ac4d..c5d56697b9 100644 --- a/src/feature/client/transports.c +++ b/src/feature/client/transports.c @@ -676,6 +676,7 @@ register_server_proxy(const managed_proxy_t *mp) t->name, fmt_addrport(&t->addr, t->port)); control_event_transport_launched("server", t->name, &t->addr, t->port); } SMARTLIST_FOREACH_END(t); + pt_update_bridge_lines(); } /** Register all the transports supported by client managed proxy @@ -1830,6 +1831,92 @@ pt_get_extra_info_descriptor_string(void) return the_string; } +/** Log the bridge lines that clients can use to connect. */ +void +pt_update_bridge_lines(void) +{ + char fingerprint[FINGERPRINT_LEN+1]; + smartlist_t *string_chunks = NULL; + + if (!server_identity_key_is_set() || !managed_proxy_list) + return; + + if (crypto_pk_get_fingerprint(get_server_identity_key(), fingerprint, 0)<0) { + log_err(LD_BUG, "Error computing fingerprint"); + return; + } + + string_chunks = smartlist_new(); + + SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) { + if (!mp->is_server) + continue; + + tor_assert(mp->transports); + + SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) { + char *transport_args = NULL; + const char *saddr = NULL; + + /* If the transport proxy returned "0.0.0.0" as its address, display + * our external address if we know it, or a placeholder if we don't */ + if (tor_addr_is_null(&t->addr)) { + tor_addr_t addr; + /* Attempt to find the IPv4 and then attempt to find the IPv6 if we + * can't find it. */ + bool found = relay_find_addr_to_publish(get_options(), AF_INET, + RELAY_FIND_ADDR_NO_FLAG, + &addr); + if (!found) { + found = relay_find_addr_to_publish(get_options(), AF_INET6, + RELAY_FIND_ADDR_NO_FLAG, &addr); + } + if (found && !tor_addr_is_null(&addr)) { + saddr = fmt_and_decorate_addr(&addr); + } else { + saddr = ""; + } + } else { + saddr = fmt_and_decorate_addr(&t->addr); + } + + /* If this transport has any arguments with it, prepend a space + * to them so that we can add them to the transport line, and replace + * commas with spaces to make it a valid bridge line. */ + if (t->extra_info_args) { + tor_asprintf(&transport_args, " %s", t->extra_info_args); + for (int i = 0; transport_args[i]; i++) { + if (transport_args[i] == ',') { + transport_args[i] = ' '; + } + } + } + + smartlist_add_asprintf(string_chunks, "Bridge %s %s:%d %s%s", + t->name, saddr, t->port, fingerprint, + transport_args ? transport_args : ""); + tor_free(transport_args); + } SMARTLIST_FOREACH_END(t); + } SMARTLIST_FOREACH_END(mp); + + /* If we have any valid bridgelines, join them into a single string, and + * save them to disk. Don't create an empty file. */ + if (smartlist_len(string_chunks) != 0) { + char *str = smartlist_join_strings(string_chunks, "\n", 1, NULL); + char *fname = get_datadir_fname("bridgelines"); + if (write_str_to_file_if_not_equal(fname, str)) { + log_warn(LD_FS, "Couldn't save bridge lines to disk"); + } else { + log_info(LD_FS, "Saved bridge lines to disk"); + } + tor_free(fname); + tor_free(str); + } + + SMARTLIST_FOREACH(string_chunks, char *, s, tor_free(s)); + smartlist_free(string_chunks); +} + /** Stringify the SOCKS arguments in socks_args according to * 180_pluggable_transport.txt. The string is allocated on the heap * and it's the responsibility of the caller to free it after use. */ diff --git a/src/feature/client/transports.h b/src/feature/client/transports.h index 71e7feea37..14a1284697 100644 --- a/src/feature/client/transports.h +++ b/src/feature/client/transports.h @@ -57,6 +57,7 @@ void pt_configure_remaining_proxies(void); int pt_proxies_configuration_pending(void); char *pt_get_extra_info_descriptor_string(void); +void pt_update_bridge_lines(void); void pt_free_all(void); diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c index d9adc638c4..257eb790de 100644 --- a/src/feature/relay/router.c +++ b/src/feature/relay/router.c @@ -382,6 +382,7 @@ set_server_identity_key(crypto_pk_t *k) log_err(LD_BUG, "Couldn't compute our own identity key digest."); tor_assert(0); } + pt_update_bridge_lines(); } #ifdef TOR_UNIT_TESTS