mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-04-06 13:47:56 +02:00
tor: enable PoW defenses for automatically created hidden services
Enable PoW defenses [1] for hidden services that we create via
Tor Control using the `ADD_ONION` command [2].
The ability to do that has been added in tor-0.4.9.2-alpha [3]. Previous
versions return a syntax error to the `ADD_ONION` command with
`PoWDefensesEnabled=1`, so the approach here is to try with PoW and if
we get syntax error, then retry without PoW.
[1] https://tpo.pages.torproject.net/onion-services/ecosystem/technology/security/pow/
[2] https://spec.torproject.org/control-spec/commands.html#add_onion
[3] 02c1804446
This commit is contained in:
@@ -54,6 +54,9 @@ FUZZ_TARGET(torcontrol, .init = initialize_torcontrol)
|
||||
[&] {
|
||||
tor_control_reply.code = TOR_REPLY_UNRECOGNIZED;
|
||||
},
|
||||
[&] {
|
||||
tor_control_reply.code = TOR_REPLY_SYNTAX_ERROR;
|
||||
},
|
||||
[&] {
|
||||
tor_control_reply.code = fuzzed_data_provider.ConsumeIntegral<int>();
|
||||
});
|
||||
@@ -65,7 +68,10 @@ FUZZ_TARGET(torcontrol, .init = initialize_torcontrol)
|
||||
CallOneOf(
|
||||
fuzzed_data_provider,
|
||||
[&] {
|
||||
tor_controller.add_onion_cb(dummy_tor_control_connection, tor_control_reply);
|
||||
tor_controller.add_onion_cb(dummy_tor_control_connection, tor_control_reply, /*pow_was_enabled=*/true);
|
||||
},
|
||||
[&] {
|
||||
tor_controller.add_onion_cb(dummy_tor_control_connection, tor_control_reply, /*pow_was_enabled=*/false);
|
||||
},
|
||||
[&] {
|
||||
tor_controller.auth_cb(dummy_tor_control_connection, tor_control_reply);
|
||||
|
||||
@@ -423,10 +423,20 @@ void TorController::get_socks_cb(TorControlConnection& _conn, const TorControlRe
|
||||
}
|
||||
}
|
||||
|
||||
void TorController::add_onion_cb(TorControlConnection& _conn, const TorControlReply& reply)
|
||||
static std::string MakeAddOnionCmd(const std::string& private_key, const std::string& target, bool enable_pow)
|
||||
{
|
||||
// Note that the 'virtual' port is always the default port to avoid decloaking nodes using other ports.
|
||||
return strprintf("ADD_ONION %s%s Port=%i,%s",
|
||||
private_key,
|
||||
enable_pow ? " PoWDefensesEnabled=1" : "",
|
||||
Params().GetDefaultPort(),
|
||||
target);
|
||||
}
|
||||
|
||||
void TorController::add_onion_cb(TorControlConnection& _conn, const TorControlReply& reply, bool pow_was_enabled)
|
||||
{
|
||||
if (reply.code == TOR_REPLY_OK) {
|
||||
LogDebug(BCLog::TOR, "ADD_ONION successful\n");
|
||||
LogDebug(BCLog::TOR, "ADD_ONION successful (PoW defenses %s)", pow_was_enabled ? "enabled" : "disabled");
|
||||
for (const std::string &s : reply.lines) {
|
||||
std::map<std::string,std::string> m = ParseTorReplyMapping(s);
|
||||
std::map<std::string,std::string>::iterator i;
|
||||
@@ -453,6 +463,12 @@ void TorController::add_onion_cb(TorControlConnection& _conn, const TorControlRe
|
||||
// ... onion requested - keep connection open
|
||||
} else if (reply.code == TOR_REPLY_UNRECOGNIZED) {
|
||||
LogWarning("tor: Add onion failed with unrecognized command (You probably need to upgrade Tor)");
|
||||
} else if (pow_was_enabled && reply.code == TOR_REPLY_SYNTAX_ERROR) {
|
||||
LogDebug(BCLog::TOR, "ADD_ONION failed with PoW defenses, retrying without");
|
||||
_conn.Command(MakeAddOnionCmd(private_key, m_target.ToStringAddrPort(), /*enable_pow=*/false),
|
||||
[this](TorControlConnection& conn, const TorControlReply& reply) {
|
||||
add_onion_cb(conn, reply, /*pow_was_enabled=*/false);
|
||||
});
|
||||
} else {
|
||||
LogWarning("tor: Add onion failed; error code %d", reply.code);
|
||||
}
|
||||
@@ -474,9 +490,10 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply&
|
||||
private_key = "NEW:ED25519-V3"; // Explicitly request key type - see issue #9214
|
||||
}
|
||||
// Request onion service, redirect port.
|
||||
// Note that the 'virtual' port is always the default port to avoid decloaking nodes using other ports.
|
||||
_conn.Command(strprintf("ADD_ONION %s Port=%i,%s", private_key, Params().GetDefaultPort(), m_target.ToStringAddrPort()),
|
||||
std::bind_front(&TorController::add_onion_cb, this));
|
||||
_conn.Command(MakeAddOnionCmd(private_key, m_target.ToStringAddrPort(), /*enable_pow=*/true),
|
||||
[this](TorControlConnection& conn, const TorControlReply& reply) {
|
||||
add_onion_cb(conn, reply, /*pow_was_enabled=*/true);
|
||||
});
|
||||
} else {
|
||||
LogWarning("tor: Authentication failed");
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ static const bool DEFAULT_LISTEN_ONION = true;
|
||||
/** Tor control reply code. Ref: https://spec.torproject.org/control-spec/replies.html */
|
||||
constexpr int TOR_REPLY_OK{250};
|
||||
constexpr int TOR_REPLY_UNRECOGNIZED{510};
|
||||
constexpr int TOR_REPLY_SYNTAX_ERROR{512}; //!< Syntax error in command argument
|
||||
|
||||
void StartTorControl(CService onion_service_target);
|
||||
void InterruptTorControl();
|
||||
@@ -142,7 +143,7 @@ public:
|
||||
/** Callback for GETINFO net/listeners/socks result */
|
||||
void get_socks_cb(TorControlConnection& conn, const TorControlReply& reply);
|
||||
/** Callback for ADD_ONION result */
|
||||
void add_onion_cb(TorControlConnection& conn, const TorControlReply& reply);
|
||||
void add_onion_cb(TorControlConnection& conn, const TorControlReply& reply, bool pow_was_enabled);
|
||||
/** Callback for AUTHENTICATE result */
|
||||
void auth_cb(TorControlConnection& conn, const TorControlReply& reply);
|
||||
/** Callback for AUTHCHALLENGE result */
|
||||
|
||||
Reference in New Issue
Block a user