Opened 6 years ago

Last modified 18 months ago

#9498 new enhancement

Allow bridge descriptors to contain no address if they are not being published

Reported by: nwf Owned by:
Priority: Very High Milestone: Tor: unspecified
Component: Core Tor/Tor Version: Tor: unspecified
Severity: Normal Keywords: tor-bridge, need-spec, bridgedb, needs-proposal censorship
Cc: isis, karsten, catalyst Actual Points:
Parent ID: Points: large
Reviewer: Sponsor:

Description

To strengthen an "isolating proxy"-style approach to client security, I'd like to allow a Tor bridge node to not reveal its external address(es) in its bridge descriptor. The following patch leaves the address as 0.0.0.0 when it's not going to be published:

diff --git a/src/or/router.c b/src/or/router.c
index 1063eda..30749b9 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -1772,7 +1772,7 @@ router_rebuild_descriptor(int force)
 {
   routerinfo_t *ri;
   extrainfo_t *ei;
-  uint32_t addr;
+  uint32_t addr = 0;
   char platform[256];
   int hibernating = we_are_hibernating();
   const or_options_t *options = get_options();
@@ -1780,11 +1780,16 @@ router_rebuild_descriptor(int force)
   if (desc_clean_since && !force)
     return 0;
 
-  if (router_pick_published_address(options, &addr) < 0 ||
-      router_get_advertised_or_port(options) == 0) {
+  /* If we're not trying to publish our descriptor, it's OK to use 0.0.0.0
+   * as the address therein.
+   */
+  if ((options->PublishServerDescriptor_ != NO_DIRINFO) &&
+      (router_pick_published_address(options, &addr) < 0 ||
+       router_get_advertised_or_port(options) == 0)) {
     /* Stop trying to rebuild our descriptor every second. We'll
      * learn that it's time to try again when ip_address_changed()
      * marks it dirty. */

Child Tickets

Change History (19)

comment:1 Changed 6 years ago by nickm

Keywords: tor-bridge added
Milestone: Tor: 0.2.5.x-final
Priority: minornormal

Hm. Does this break anything client-side? We should test this with a lot of versions of tor.

This will also need a specification patch.

comment:2 Changed 6 years ago by nwf

I have been testing with 0.2.2.39 as my proxy and it seems to work fine, FWIW.

Bridge-side, tho', I note that unless I set AssumeReachable 1 and use ExcludeNodes and StrictNodes that the bridge continues to try to test its own reachability by building circuits to 0.0.0.0, which seems wrong. At least there's a workaround.

comment:3 Changed 6 years ago by isis

Cc: isis@… added
Keywords: need-spec bridgedb added

Adding keyword 'need-spec'.

This is a really neat idea. It could potentially (though not currently, with this patch) allow clients who use bridges which are not contained in BridgeDB to verify the onion-key, signing-key, and fingerprint of their bridge. Although to do that, there ought to be some sort of challenge-response between the client and the bridge, i.e. something like:

1) client connects to bridge and asks it to sign a nonce.
2) bridge signs and sends it back.
3) client checks that the signature was made with the key received from the bridge-server-descriptor, and that both sigs are valid.

I am worried also that private bridges creating falsified descriptors will break things, since BridgeDB, as well as anything else which parses descriptors looking for addresses -- such as (probably) metrics-tasks, stem, and arm, would need to be changed to understand this.

Also, there is much more identifying information in the bridge-server-descriptors than just the IP. I see the following problems:

  • Would such a bridge report its extrainfo descriptor? Because the @type bridge-extrainfo contains read-history and write-history lines, which, if a bridge has very few users, could possibly damage those user's anonymity. For example, if a bridge had only one user (which could be quite likely, since it is a private bridge), anyone who had this information could possibly determine some information about the browsing habits of the user (though likely no more than sitting outside the user's house in a black van and wiretapping everything).
  • The @type bridge-server-descriptor contains the contact line which is likely also problematic.
  • The @type bridge-extrainfo contains also the geoip-client-origins / bridge-ips, these might be problematic. Also, the transport line, if it has one.

Currently, a bridge descriptor (@type bridge-server-descriptor) looks like this:

@purpose bridge
router thisisafakebridge 11.11.11.11 9001 0 0
platform Tor 0.2.3.25 on Linux
opt protocols Link 1 2 Circuit 1
published 2013-08-21 12:00:00
opt fingerprint 26E5 B0C0 0C5D F12A 3C96 9D35 BA71 4527 8AEC 2B96
uptime 2171396
bandwidth 5243880 10585760 160875
opt extra-info-digest D34DB33FD1511CDDAF9486D8615CCBD48E1C07F8001
onion-key
-----BEGIN RSA PUBLIC KEY-----
MIGJ3oGBAJMrq17ZyIxZBAVwbQXUiY2ZpzNj/fLINjo4snw75wx+sex6iwM+kYsr
JMyGOU1oFDUpz6dHXmk/tZw0F46B7TV4Ae+f6iEkRLWNuxah2Jvr8wci55ZAJWV9
rVR1sHndj4y3CJeCqYjPxmWUJSxO9evPKjjOZbmbyeJox7alRUkTAgMBAAE=
-----END RSA PUBLIC KEY-----
signing-key
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBALhRvLOjvM2pUSA6Njq29rq23rawYIsk6fvWo9mwucSCQrw75whCMzj8
VVWbrpvxkT1bxxEpwuxeawef98u323rqg4ffpsL7riUcKlL4GAG7QhOKVdqCx6FJ
svvHOUKCAHTxsqjit2/LzPhQ/DuUxFn9awef8mEUgBs0tIdnaowe24LMBAAE=
-----END RSA PUBLIC KEY-----
opt hidden-service-dir
contact SoAndSo <soandso@example.com>
ntor-onion-key AYZTRGjUdo+VuurT3VkgNzPWuUf/LT4VCq78wMwlWio=
reject *:*
router-signature
-----BEGIN SIGNATURE-----
PAUsG3Pcz7X39bE8NlCmBBoCOEPQwNhNO52IebNUqnh7gfyoq3dqGqHMIC0PJ5WJ
SW6P6LAqpi0MopIl8D8YxcD69xWO/0mTBZDaZT3EOEBW2PcYinNg4vwOCj/kxpaM
Zbl3BpbnudVGzASc7UgxQcjWBtXVOiI44FdX3RtG7tM=
-----END SIGNATURE-----

comment:4 Changed 6 years ago by atagar

I am worried also that private bridges creating falsified descriptors will break things, since BridgeDB, as well as anything else which parses descriptors looking for addresses -- such as (probably) metrics-tasks, stem, and arm, would need to be changed to understand this.

  • Arm does not presently use bridge descriptors (it only uses general descriptor information available through the controller interface).
  • Wiping the address would prevent metrics from producing the sanaitized addresses in the bridge format it publishes. I suspect for Karsten's purposes he would like the address to be something unique (not blanked to 0.0.0.0), though it probably fine for it to be inaccurate. You should double check with him.

If you do write a spec for this please be clearer about the reason for it. When I first read the ticket I thought "Huh? Clients already need the address to get unpublished bridges so what's the purpose of scrubbing the address we respond with?" but then I remembered flash proxies and the other fancy schemes you folks have been coming up with. :)

comment:5 in reply to:  4 Changed 6 years ago by isis

Replying to atagar:

  • Arm does not presently use bridge descriptors (it only uses general descriptor information available through the controller interface).

Derp. Misremembered. I think I had a dream once where arm showed me all kinds of magical statistics about bridges, perhaps some of that interface accidentally melded.

  • Wiping the address would prevent metrics from producing the sanaitized addresses in the bridge format it publishes. I suspect for Karsten's purposes he would like the address to be something unique (not blanked to 0.0.0.0), though it probably fine for it to be inaccurate. You should double check with him.

Although, keeping them all the same might be neat, because it would allow aggregate statistics on private bridge usage. That might be safer, or more privacy-preserving, Karsten would probably know.

The other thing that could be neat is if some range were set aside, like using 127.255.0.0/16 (though this might raise other problems), but then we run into problems if we ever expect to have more than 216 IPv4 bridges. Using entirely random addresses would definitely be a bad idea, because BridgeDB would think these were real bridges at these addresses, and start handing them out to users, who wouldn't be able to connect to them. Not to mention the birthday problem would apply to collisions, but this seems negligible because the total ipv4 address space is 224. Still, I'm not sure what tor does if two ORs claim to have the same address with different keys. Or what the DirAuths do.

comment:6 Changed 6 years ago by atagar

Derp. Misremembered. I think I had a dream once where arm showed me all kinds of magical statistics about bridges, perhaps some of that interface accidentally melded.

Maybe it will in the future. I plan on returning to arm development soon so feature requests welcome. :)

Still, I'm not sure what tor does if two ORs claim to have the same address with different keys. Or what the DirAuths do.

Good question. Same address is fine, but duplicate address/orport combination of course would be problematic. My hunch is that they'd reject the descriptors for the newcomer until the old relay disappeared but haven't checked the code.

comment:7 Changed 6 years ago by nwf

Responding to various points raised:

If you do write a spec for this please be clearer about the reason for it.

The intention here is to allow someone (i.e. me) who might otherwise run a Tor proxy and an "isolating proxy"-style setup to instead run an unpublished Tor bridge and expose its bridge port to the isolated node, which in turn runs a Tor proxy set to use that bridge. The advantages here are

  • Bridging Tor rather than bringing the SOCKS proxy across the link allows running self-contained hidservs and gives the isolated node full control over its behavior within Tor.
  • The mechanism of exposure for the bridge port need not be an IP network -- a serial stream will do just fine. This reduces the attack surface available to a would-be de-anonymizing adversary who has compromised the VM, but this reduction is only meaningful if the bridge doesn't announce its address to the isolated node, which is why I had it scrub the address information. (Concretely, consider, for example, that by default Linux responds to ARP requests arriving on any interface for any address configured on any interface; a compromised user node in a typical "isolating proxy" setup would therefore be able to probe the network link between the end node and the Tor proxy, and, if the machine hosting the proxy has a public IP address, thereby de-anonymize the proxy's user. This is just one example; UNIX IP stacks tend to be large and complex and I am doubtful that they could be made believably free of such information exposures. The advantage of using something like a high-speed serial link is that the only attack surface available is the inside of the bridge port, the socat-like tool for bridging serial to TCP on the bridge, and the bridge's kernel's serial layer. Unfortunately, this is currently immaterial due to #7144; a compromised proxy host in this setup easily reveals its bridges by making circuits through adversary-controlled 2nd hops.)

I recognize that this is something of an abuse of the intended functionality of bridges -- I'm trying to control the proxy's choice of first hops so that I can get a machine which can be said to be reasonably well connected to the Internet but that cannot discover any IP address information for said first hops (and has no non-127/8 address for itself). (Though again see #7144.)

It could potentially (though not currently, with this patch) allow clients who use bridges which are not contained in BridgeDB to verify the onion-key, signing-key, and fingerprint of their bridge.

I am confused. When I ran this experimentally, the Tor proxy had

Bridge 127.0.0.1:12345 0123456789ABCDEF0123456789ABCDEF01234567

in its config file; I thought the wad of hex there was the bridge's fingerprint and that the proxy's connection to the bridge and the bridge's proffered self-descriptor would be verified against it?

I am worried also that private bridges creating falsified descriptors will break things, since BridgeDB, [...]

I'm not sure why BridgeDB is relevant here -- the descriptors are not intended to be published at all?

Thanks!

comment:8 Changed 6 years ago by karsten

Cc: karsten added

I'm not entirely clear where this discussion is heading, but once there's a spec or proposal I'm happy to comment on anything related to bridge descriptor sanitizing.

comment:9 Changed 6 years ago by atagar

The intention here is to allow someone (i.e. me) who might otherwise run a Tor proxy and an "isolating proxy"-style setup to instead run an unpublished Tor bridge and expose its bridge port to the isolated node, which in turn runs a Tor proxy set to use that bridge.

I suspect there's some context that I'm missing (I'm not quite sure what an '"isolating proxy"-style setup' is, how it relates to bridges, and the explanation left me more confused than illuminated). That said, I'm happy to leave this to isis and nickm if they know what's up. Just let me know if there's any questions regarding descriptor parsing in particular.

comment:10 Changed 6 years ago by nwf

"isolating proxy" is the term used at doc/TorifyHOWTO/IsolatingProxy; sorry for any and all induced confusion.

comment:11 Changed 5 years ago by nickm

Milestone: Tor: 0.2.5.x-finalTor: 0.2.6.x-final

comment:12 Changed 5 years ago by nickm

Keywords: needs-proposal 026-triaged-1 026-deferrable added

comment:13 Changed 4 years ago by nickm

Milestone: Tor: 0.2.6.x-finalTor: 0.2.???

Still needs proposal and analysis.

comment:14 Changed 3 years ago by isis

Cc: isis added; isis@… removed
Milestone: Tor: 0.2.???Tor: very long term
Points: large

comment:15 Changed 22 months ago by nickm

Milestone: Tor: very long termTor: unspecified

Batch modify: these tickets seem to be things that wouldn't actually be a big redesign or a big amount of work, so they belong "Unspecified", not "Very Long Term"

comment:16 Changed 22 months ago by nickm

Keywords: 026-triaged-1 removed

comment:17 Changed 22 months ago by nickm

Keywords: 026-deferrable removed

comment:18 Changed 22 months ago by nickm

Keywords: censorship added
Priority: MediumVery High
Severity: Normal

comment:19 Changed 18 months ago by catalyst

Cc: catalyst added
Note: See TracTickets for help on using tickets.