Commit Graph

38662 Commits

Author SHA1 Message Date
Micah Elizabeth Scott
903c6cf1ab hs_pow: client side effort adjustment
The goal of this patch is to add an additional mechanism for adjusting
PoW effort upwards, where clients rather than services can choose to
solve their puzzles at a higher effort than what was suggested in the
descriptor.

I wanted to use hs_cache's existing unreachability stats to drive this
effort bump, but this revealed some cases where a circuit (intro or
rend) closed early on can end up in hs_cache with an all zero intro
point key, where nobody will find it. This moves intro_auth_pk
initialization earlier in a couple places and adds nonfatal asserts to
catch the problem if it shows up elsewhere.

The actual effort adjustment method I chose is to multiply the suggested
effort by (1 + unresponsive_count), then ensure the result is at least
1. If a service has suggested effort of 0 but we fail to connect,
retries will all use an effort of 1. If the suggestion was 50, we'll try
50, 100, 150, 200, etc. This is bounded both by our client effort limit
and by the limit on unresponsive_count (currently 5).

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:40:46 -07:00
Micah Elizabeth Scott
ac466a2219 hs_pow: leak fix, free the contents of pqueue entries in hs_pow_free_service_state
Asan catches this pretty readily when ending a service gracefully while
a DoS is in progress and the queue is full of items that haven't yet
timed out.

The module boundaries in hs_circuit are quite fuzzy here, but I'm trying
to follow the vibe of the existing hs_pow code.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:29 -07:00
Micah Elizabeth Scott
ac29c7209d hs_pow: bump client-side effort limit from 500 to 10000
500 was quite low, but this limit was helpful when the suggested-effort
estimation algorithm was likely to give us large abrupt increases. Now
that this should be fixed, let's allow spending a bit more time on the
client puzzles if it's actually necessary.

Solving a puzzle with effort=10000 usually completes within a minute
on my old x86_64 machine. We may want to fine tune this further, and it
should probably be made into a config option.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:29 -07:00
Micah Elizabeth Scott
6a0809c4e3 hs_pow: stop having a "minimum effort", and let PoW effort start low
I don't think the concept of "minimum effort" is really useful to us,
so this patch removes it entirely and consequentially changes the way
that "total" effort is calculated so that we don't rely on any minimum
and we instead ramp up effort no faster than necessary.

If at least some portion of the attack is conducted by clients that
avoid PoW or provide incorrect solutions, those (potentially very
cheap) attacks will end up keeping the pqueue full. Prior to this patch,
that would cause suggested efforts to be unnecessarily high, because
rounding these very cheap requests up to even a minimum of 1 will
overestimate how much actual attack effort is being spent.

The result is that this patch is a simplification and it also allows a
slower start, where PoW effort jumps up either by a single unit or by an
amount calculated from actual effort in the queue.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:29 -07:00
Micah Elizabeth Scott
d15bbf32da changes: Ticket 40634 (hs_pow)
Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:29 -07:00
Micah Elizabeth Scott
18a2191a13 gitlab-ci: Try enabling GPL mode so we test hs_pow
Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:29 -07:00
Micah Elizabeth Scott
2de98a7f4e hs_pow: Represent equix_solution as a byte array
This patch is intended to clarify the points at which we convert
between the internal representation of an equix_solution and a portable
but opaque byte array representation.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
287c78c5a8 sandbox: allow stack mmap with prot_none
This fixes a failure that was showing up on i386 Debian hosts
with sandboxing enabled, now that cpuworker is enabled on clients.
We already had allowances for creating threads and creating stacks
in the sandbox, but prot_none (probably used for a stack guard)
was not allowed so thread creation failed.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
700814a3a1 hs_pow: Fix nonce cache entry leak
This leak was showing up in address sanitizer runs of test_hs_pow,
but it will also happen during normal operation as seeds are rotated.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
00d9e0d252 hs_pow: Define seed_head as uint8_t[4] instead of uint32_t
This is more consistent with the specification, and it's much
less confusing with endianness. This resolves the underlying
cause of the earlier byte-swap. This patch itself does not
change the wire protocol at all, it's just tidying up the
types we use at the trunnel layer.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
209a59face hs_pow: Don't require uint128_t
We were using a native uint128_t to represent the hs_pow nonce,
but as the comments note it's more portable and more flexible to
use a byte array. Indeed the uint128_t was a problem for 32-bit
platforms. This swaps in a new implementation that uses multiple
machine words to implement the nonce incrementation.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
1a3afeb387 hs_pow: unswap byte order of seed_head field
In proposal 327, "POW_SEED is the first 4 bytes of the seed used".

The proposal doesn't specifically mention the data type of this field,
and the code in hs_pow so far treats it as an integer but semantically
it's more like the first four bytes of an already-encoded little endian
blob. This leads to a byte swap, since the type confusion takes place
in a little-endian subsystem but the wire encoding of seed_head uses
tor's default of big endian.

This patch does not address the underlying type confusion, it's a
minimal change that only swaps the byte order and updates unit tests
accordingly. Further changes will clean up the data types.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
037dea2252 hs_pow: fix assert in services that receive unsolicited proof of work
Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
3129910b11 hs_pow: use the compiled HashX implementation
Much faster per-hash, affects both verify and solve.
Only implemented on x86_64 and aarch64, other platforms
always use the interpreted version of hashx.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
c6b168e141 test_hs_pow: add test vectors for our hs_pow client puzzle
This adds test vectors for the overall client puzzle at the
hs_pow and hs_cell layers.

These are similar to the crypto/equix tests, but they also cover
particulars of our hs_pow format like the conversion to byte arrays,
the replay cache, the effort test, and the formatting of the equix
challenge string.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
0c11411f35 hashx: trim trailing whitespace
Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
ae86d98815 equix: Portability fixes for big endian platforms
Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
daa08557ad equix: Build cleanly with -Wall -Werror
Fixes some type nitpicks that show up in Tor development builds,
which usually run with -Wall -Werror. Tested on x86_64 and aarch64
for clean build and passing equix-tests + hashx-tests.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
246ced3a8c ext: build equix and hashx using automake
This replaces the sketchy cmake invocation we had inside configure

The libs are always built and always used in unit tests, but only
included in libtor and tor when --enable-gpl is set.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
bfa2102c95 hs_pow: Replace libb2 dependency with hashx's internal blake2
This forgoes another external library dependency, and instead
introduces a compatibility header so that interested parties
(who already depend on equix, like hs_pow and unit tests) can
use the implementation of blake2b included in hashx.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
ffa8531fe0 test_crypto: add equix and hashx tests
This adds test vectors for the Equi-X proof of work algorithm and the
Hash-X function it's based on. The overall Equi-X test takes about
10 seconds to run on my machine, so it's in test_crypto_slow. The hashx
test still covers both the compiled and interpreted versions of the
hash function.

There aren't any official test vectors for Equi-X or for its particular
configuration of Hash-X, so I made some up based on the current
implementation.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
92f83347f7 test_crypto: add blake2b test vectors
I'm planning on swapping blake2b implementations, and this test
is intended to prevent regressions. Right now blake2b is only used by
hs_pow.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
dcb9c4df67 hs_pow: Make proof-of-work support optional in configure
This adds a new "pow" module for the user-visible proof
of work support in ./configure, and this disables
src/feature/hs/hs_pow at compile-time.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
9d1a573977 configure: Add --enable-gpl option
This change on its own doesn't use the option for anything, but
it includes support for configure and a message in 'tor --version'

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
557eb81486 hs_pow_solve: use equix_solve more efficiently
This was apparently misinterpreting "zero solutions" as an error
instead of just moving on to the next nonce. Additionally, equix
could have been returning up to 8 solutions and we would only
give one of those a chance to succeed.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
0e271dda77 hs_pow: reduce min_effort default to 1
We may want to choose something larger eventually, but 20 seemed
much too large. Very low nonzero efforts are still useful against
a script kiddie level DoS attack.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
f3b98116b6 hs_pow: Rate limited dequeue
This adds a token bucket ratelimiter on the dequeue side
of hs_pow's priority queue. It adds config options and docs
for those options. (HiddenServicePoWQueueRate/Burst)

I'm testing this as a way to limit the overhead of circuit
creation when we're experiencing a flood of rendezvous requests.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
20d7c8ce14 fix typo in HiddenServiceExportCircuitID
Really inconsequential, since the string was only used for logging a
warning.
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
98299e0f8b manpage: document HiddenServicePoWDefensesEnabled option
Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
a0b9f3546e hs_pow: check for expired params in can_client_refetch_desc
Without this check, we never actually refetch the hs descriptor
when PoW parameters expire, because can_client_refetch_desc
deems the descriptor to be still good.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
48c67263d9 hs_metrics: Proof of Work pqueue depth, suggested effort
Adds two new metrics for hs_pow, and an internal parameter within
hs_metrics for implementing gauge parameters that reset before
every update.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
2023-05-10 07:38:28 -07:00
Micah Elizabeth Scott
09afc5eacf update_suggested_effort: avoid assert if the pqueue has emptied
top_of_rend_pqueue_is_worthwhile requires a nonempty queue.
2023-05-10 07:37:11 -07:00
Roger Dingledine
eba9190933 compute the client-side pow in a cpuworker thread
We mark the intro circuit with a new flag saying that the pow is
in the cpuworker queue. When the cpuworker comes back, it either
has a solution, in which case we proceed with sending the intro1
cell, or it has no solution, in which case we unmark the intro
circuit and let the whole process restart on the next iteration of
connection_ap_handshake_attach_circuit().
2023-05-10 07:37:11 -07:00
Roger Dingledine
aa41d4b939 refactor send_introduce1()
into two parts:

* a "consider whether to send an intro2 cell" part (now called
consider_sending_introduce1()), and

* an "actually send it" (now called send_introduce1()).
2023-05-10 07:37:11 -07:00
Roger Dingledine
a5b0c7b404 start the cpuworkers always, even for clients
prepares the way for client-side pow cpuworkers

also happens to resolve bug https://bugs.torproject.org/tpo/core/tor/40617
(which went into 0.4.7.4-alpha) because now we survive initing the
cpuworker subsystem when we're not a relay.
2023-05-10 07:37:11 -07:00
Roger Dingledine
0716cd7cb2 allow suggested effort to be 0
First (both client and service), make descriptor parsing not fail when
suggested_effort is 0.

Second (client side), if we get a descriptor with a pow_params section
but with suggested_effort of 0, treat it as not requiring a pow.

Third (service side), when deciding whether the suggested effort has
changed, don't treat "previous suggested effort 0, new suggested effort 0"
as a change.

An alternative design to resolve 'first' and 'second' above would be
to omit the pow_params from the descriptor when suggested_effort is 0,
so clients never see the pow_params so they don't compute a pow. But
I decided to include a pow_params with an explicit suggested_effort
of 0, since this way the client knows the seed etc so they can solve
a higher-effort pow if they want. The tradeoff is that the descriptor
reveals whether HiddenServicePoWDefensesEnabled is set to 1 for this onion
service, even if the AIMD calculation is currently requiring effort 0.
2023-05-10 07:37:11 -07:00
Mike Perry
d36144ba31 Initialize startup effort at 0.
If it works correctly, auto-tuning should set a non-zero effort once
an attack begins.
2023-05-10 07:37:11 -07:00
Mike Perry
ec9e95cf1e Implement AIMD effort estimation.
Now, pow should auto-enable and auto-disable itself.
2023-05-10 07:37:11 -07:00
Mike Perry
5b3a067fe3 Replace the constant bottom-half rate with handled count.
This allows us to more accurately estimate effort, based on real bottom-half
throughput over the duration of a descriptor update.
2023-05-10 07:37:11 -07:00
Mike Perry
121766e6b8 Make the thing compile. 2023-05-10 07:37:11 -07:00
Roger Dingledine
e605620744 clients defend themselves from absurd pow requests
if asked for higher than a cap, we just solve it at the cap

i picked 500 for now but maybe we'll pick a better number in the future.
2023-05-10 07:37:11 -07:00
Roger Dingledine
ec7495d35a log_err is reserved for fatal failures 2023-05-10 07:37:11 -07:00
Roger Dingledine
e436ce2a3c drop the default min effort to 20
effort 100 is really quite expensive
2023-05-10 07:37:11 -07:00
Roger Dingledine
a575e35c17 sort pqueue ties by time-added
our pqueue implementation does bizarre unspecified things with
ordering of elements that are equal. it certainly doesn't do any
sort of "first in first out" property that i was expecting.

now make it explicit by saying that "equal-effort, added-earlier" is
higher priority.
2023-05-10 07:37:11 -07:00
Roger Dingledine
13f6258245 rate-limit low-effort rendezvous responses
specifically, if we have 16 in-flight rend circs, and the next
one at the top of the pqueue is lower than our suggested effort,
then don't launch it yet.

this way we always launch adequate-effort requests immediately, and
we always handle *some* low-effort requests, but we are ready at any
moment to handle a few new adequate-effort requests.
2023-05-10 07:37:11 -07:00
Roger Dingledine
dec3a0af7a make the rend_pqueue_cb event be postloop
this change makes us reach the callback *after* each mainloop
run, rather than as the next event to run immediately after
activation.

with the old behavior, we were starving everything else to drain the
pqueue entirely, each time we got a new intro2 cell.

now we at least will get to other activities as well.
2023-05-10 07:37:11 -07:00
Roger Dingledine
b95bd5017f track how many in-flight hs-side rend circs
not used in decision-making yet, but it's all ready to use in a
"don't dequeue any more if we have too many in-flight" kind of way
2023-05-10 07:37:11 -07:00
Roger Dingledine
5e768d5cb9 we were sorting our pqueue the wrong way
i.e. we were putting higher effort intro2 cells at the *end*
2023-05-10 07:37:11 -07:00
Roger Dingledine
d0c2d4cb43 add a log line for when client succeeds 2023-05-10 07:37:11 -07:00
Roger Dingledine
4e55f28220 bump up some log messages for easier debugging 2023-05-10 07:37:11 -07:00