Last week we released Arti 1.3.0, the latest version of our rewrite of Tor in Rust. One new feature in this release is memory quota tracking.
Tracking and restricting memory for queued data
The memory quota tracking feature allows you to restrict the amount of memory used by an Arti process. In particular, it allows you to limit the amount of memory that other people can cause your Arti to use.
This is particularly important when Arti is being used to provide an Onion Service (aka a Tor Hidden Service). Running an Onion Service means letting users from all over the network connect to your service (depending, to an extent, on your configuration settings). That means those users can cause your system to do work, and, generally, to store data in transit to and from your Onion Service. In 2014, Jansen et al discovered that this kind of data storage can even be used to help deanonymise your service.
We have now implemented the recommended countermeasure: Arti can track how much data is stored in its various queues. When the configured limit is reached, Arti starts shutting down connections, and discarding data, until the queued data is below the limit. We kill the connections with the oldest oustanding data. This minimises the impact on unrelated, innocent, traffic.
We'll also need this memory limit feature for Arti Relay, which is currently being developed.
Configuration
In Arti, the memory quota tracker is controlled by the
[system.memory]
configuration subsection in arti.toml
. You can enable it by writing something like this:
Code:
[system]
memory.max = "1 GiB"
The feature is compiled in by default. Setting the limit for the first time requires an Arti restart. After that, adjusting (or removing) the limit can be done at runtime.
There is also a
memory.low_water
setting: When Arti needs to free memory because max
is exceeded, it keeps tearing down connections until the usage is below low_water
. This hysteresis helps stop the system oscillating. The defaualt value of low_water
is 75% of max
.(Note that unlike C Tor's
MaxMemInQueues
setting, the current default in Arti is not to enable a memory limit. In Arti you must turn on the feature explicitly, by setting max
. We hope to get more experience of how it works for users in practice, before we consider whether to enable a limit by default.)Logging
After you've enabled memory quota tracking, you should see Arti print a log message like this:
Code:
2024-10-31T16:55:55Z INFO tor_memquota::mtracker: memory quota tracking initialised max=1.00 GiB low_water=768 MiB
You can tell if memory reclaim has been triggered:
Code:
2024-10-31T17:22:19Z INFO tor_memquota::mtracker::reclaim: memory tracking: 1.86 GiB > 1.00 GiB, reclamation started (target 768 MiB)
...
2024-10-31T17:22:20Z INFO tor_memquota::mtracker::reclaim: memory tracking reclamation reached: 44.3 KiB (target 768 MiB): complete
Caution: very new code!
This is a very new feature. There is a lot of complexity behind the scenes, and by its nature it is difficult to do a full-scale integration test. It is quite possible that there are bugs! We'd like to hear your feedback, when you enable this feature.
You can report issues you discover in our gitlab (also available via an anonymous ticket reporting system). You can also contact us informally by email, or on irc: we're in
#tor-dev
on OFTC.Thanks to our sponsors
Thanks to Zcash Community Grants for their funding, which enabled the development of this feature, and of course to our other sponsors for funding the development of Arti.
@Dark_Duck