mirror of
https://github.com/torproject/torspec.git
synced 2025-03-03 22:27:06 +00:00
186 lines
8.0 KiB
Plaintext
186 lines
8.0 KiB
Plaintext
Filename: 307-onionbalance-v3.txt
|
|
Title: Onion Balance Support for Onion Service v3
|
|
Author: Nick Mathewson
|
|
Created: 03-April-2019
|
|
Status: Reserve
|
|
|
|
[This proposal is currently in reserve status because bug tor#29583 makes
|
|
it unnecessary. (2020 July 31)]
|
|
|
|
0. Draft Notes
|
|
|
|
2019-07-25:
|
|
|
|
At this point in time, the cross-certification is not implemented
|
|
correctly in >= tor-0.3.2.1-alpha. See https://trac.torproject.org/29583
|
|
for more details.
|
|
|
|
This proposal assumes that this bug is fixed.
|
|
|
|
1. Introduction
|
|
|
|
The OnionBalance tool allows several independent Tor instances to host an
|
|
onion service, while clients can access that onion service without having
|
|
to take its distributed status into account. OnionBalance works by having
|
|
each instance run a separate onion service. Then, a management server
|
|
periodically downloads the descriptors from those onion services, and
|
|
generates a new descriptor containing the introduction points from each
|
|
instance's onion service.
|
|
|
|
OnionBalance is used by several high-profile onion services, including
|
|
Facebook and The Tor Project.
|
|
|
|
Unfortunately, because of the cross-certification features in v3 onion
|
|
services, OnionBalance no longer works for them. To a certain extent, this
|
|
breakage is because of a security improvement: It's probably a good thing
|
|
that random third parties can no longer grab a onion service's introduction
|
|
points and claim that they are introduction points for a different service.
|
|
But nonetheless, a lack of a working OnionBalance remains an obstacle for
|
|
v3 onion service migration.
|
|
|
|
This proposal describes extensions to v3 onion service design to
|
|
accommodate OnionBalance.
|
|
|
|
2. Background and Solution
|
|
|
|
If an OnionBalance management server wants to provide an aggregate
|
|
descriptor for a v3 onion service, it faces several obstacles that it
|
|
didn't have in v2.
|
|
|
|
When the management server goes to construct an aggregated descriptor, it
|
|
will have a mismatch on the "auth-key", "enc-key-cert", and
|
|
"legacy-key-cert" fields: these fields are supposed to certify the onion
|
|
service's current descriptor-signing key, but each of these keys will be
|
|
generated independently by each instance. Because they won't match each
|
|
other, there is no possible key that the aggregated descriptor could use
|
|
for its descriptor signing key.
|
|
|
|
In this design, we require that each instance should know in advance about
|
|
a descriptor-signing public key that the aggregate descriptor will use for
|
|
each time period. (I'll explain how they can do this later, in section 3
|
|
below.) They don't have to know the corresponding private key.
|
|
|
|
When generating their own onion service descriptors for a given time
|
|
period, the instances generate these additional fields to be used for the
|
|
aggregate descriptor:
|
|
|
|
"meta-auth-key"
|
|
"meta-enc-key-cert"
|
|
"meta-legacy-key-cert"
|
|
|
|
These fields correspond to "auth-key", "enc-key-cert", and
|
|
"legacy-key-cert" respectively, but differ in one regard: the
|
|
descriptor-signing public key that they certify is _not_ the instance's own
|
|
descriptor-signing key, but rather the aggregate public key for the time
|
|
period.
|
|
|
|
Ordinary clients ignore these new fields.
|
|
|
|
When the management server creates the aggregate descriptor, it checks that
|
|
the signing key for each of these "meta" fields matches the signing key for
|
|
its corresponding non-"meta" field, and that they certify the correct
|
|
descriptor-signing key-- and then uses these fields in place of their
|
|
corresponding non-"meta" variants.
|
|
|
|
2.1. A quick note on synchronization
|
|
|
|
In the design above, and in the section below, I frequently refer to "the
|
|
current time period". By this, I mean the time period for which the
|
|
descriptor is encoded, not the time period in which it is generated.
|
|
|
|
Instances and management servers should generate descriptors for the two
|
|
closest time periods, as they do today: no additional synchronization
|
|
should needed here.
|
|
|
|
3. How to distribute descriptor-signing keys
|
|
|
|
The design requires that every instance of the onion service knows about
|
|
the public descriptor-signing key that will be used for the aggregate onion
|
|
service. Here I'll discuss how this can be achieved.
|
|
|
|
3.1. If the instances are trusted.
|
|
|
|
If the management server trusts each of the instances, it can distribute a
|
|
shared secret to each one of them, and use this shared secret to derive
|
|
each time period's private key.
|
|
|
|
For example, if the shared secret is SK, then the private descriptor-
|
|
signing key for each time period could be derived as:
|
|
|
|
H("meta-descriptor-signing-key-deriv" |
|
|
onion_service_identity
|
|
INT_8(period_num) |
|
|
INT_8(period_length) |
|
|
SK )
|
|
|
|
(Remember that in the terminology of rend-spec-v3, INT_8() denotes a 64-bit
|
|
integer, see section 0.2 in rend-spec-v3.txt.)
|
|
|
|
If shared secret is ever compromised, then an attacker can impersonate the
|
|
onion service until the shared secret is changed, and can correlate all
|
|
past descriptors for the onion service.
|
|
|
|
3.2. If the instances are not trusted: Option One
|
|
|
|
If the management server does not trust the instances with
|
|
descriptor-signing public keys, another option for it is to simply
|
|
distribute a load of public keys in advance, and use them according to a
|
|
schedule.
|
|
|
|
In this design, the management server would pre-generate the
|
|
"descriptor-signing-key-cert" fields for a long time in advance, and
|
|
distribute them to the instances offline. Each one would be
|
|
associated with its corresponding time period.
|
|
|
|
If these certificates were revealed to an attacker, the attacker
|
|
could correlate descriptors for the onion service with one another,
|
|
but could not impersonate the service.
|
|
|
|
3.3. If the instances are not trusted: Option Two
|
|
|
|
Another option for the trust model of 3.2 above is to use the same
|
|
key-blinding method as used for v3 onion services. The management server
|
|
would hold a private descriptor-signing key, and use it to derive a
|
|
different private descriptor-signing key for each time period. The instance
|
|
servers would hold the corresponding public key, and use it to derive a
|
|
different public descriptor-signing key for each time period.
|
|
|
|
(For security, the key-blinding function in this case should use a
|
|
different nonce than used in the)
|
|
|
|
This design would allow the instances to only be configured once, which
|
|
would be simpler than 3.2 above-- but at a cost. The management server's
|
|
use of a long-term private descriptor-signing key would require it to keep
|
|
that key online. (It could keep the derived private descriptor-signing keys
|
|
online, but the parent key could be derived from them.)
|
|
|
|
Here, if the instance's knowledge were revealed to an attack, the attacker
|
|
could correlate descriptors for the onion service with one another, but
|
|
could not impersonate the service.
|
|
|
|
4. Some features of this proposal
|
|
|
|
We retain the property that each instance service remains accessible as a
|
|
working onion service. However, anyone who can access it can identify it as
|
|
an instance of an OnionBalance service, and correlate its descriptor to the
|
|
aggregate descriptor.
|
|
|
|
Instances could use client authorization to ensure that only the management
|
|
server can decrypt their introduction points. However, because of the
|
|
key-blinding features of v3 onion services, nobody who doesn't know the
|
|
onion addresses for the instances can access them anyway: It would be
|
|
sufficient to keep these addresses secret.
|
|
|
|
Although anybody who successfully accesses an instance can correlate its
|
|
descriptor to the meta-descriptor, this only works for two descriptors
|
|
within a single time period: You can't match an instance descriptor from
|
|
one time period to a meta-descriptor from another.
|
|
|
|
A. Acknowledgments
|
|
|
|
Thanks to the network team for helping me clarify my ideas here, explore
|
|
options, and better understand some of the implementations and challenges
|
|
in this problem space.
|
|
|
|
This research was supported by NSF grants CNS-1526306 and CNS-1619454.
|