On Wed, Sep 11, 2024 at 7:02 AM Michael Rogers michael@briarproject.org wrote:
Hi Nick,
It would be useful to have a way of controlling access to the SOCKS port so that untrusted applications running on the same device as a Tor client can't use the Tor client's SOCKS proxy. This is something that people auditing Briar have raised as a security concern.
Unix sockets aren't a great solution here because HTTP libraries don't necessarily know how to connect to them. A TCP socket with username/password auth is what HTTP libraries are expecting to see, but because Tor uses the SOCKS username and password for other purposes, we can't currently use them for access control.
Before seeing this proposal I'd thought about asking if Tor could support some way of configuring username/password pairs, which would function as real SOCKS credentials as well as providing stream isolation. But it seems like this proposal would make that more difficult, and if it's going to be possible to support SOCKS credentials in future, it might make sense to plan for it now.
I'm not asking for username/password auth to be added to this proposal, just for the proposal to leave room for it to be added in the future.
Can you see how that might be done?
Good question, Michael!
So, I see several answers: two comparatively simple, one a bit trickier, one that's a bit philosophical, and two you probably can't use. (There are probably more I haven't thought of.)
In the order of descending usefulness:
## Simple answer 1: Extending this proposal to allow to using username/password as a username/password
So, with this proposal (351), we have the ability to add new semantics to the SOCKS5 username/password field: If the username begins with `<torS0X>`, then the next byte describes what format the rest of the username/password are in.
Now, the version of this proposal sent to the ML only defines semantics for `0`; there's a version on gitlab (see [torspec!280]) that defines both `0` and `1`.
[torspec!280]: https://gitlab.torproject.org/tpo/core/torspec/-/merge_requests/280
But we could also add a new format (call it `P`) that allows encoding an actual username and password. That would be backward compatible with this proposal, though we'd actually need to design and implement it.
To use such a format, you might configure the SOCKS library to say that the username is something like `<torS0X>Pmy_real_username`, and that the password is `cnffjbeq`.
(FWIW, I believe this proposal makes it _easier_ to put a username/password back into the SOCKS5 username password field, since it defines a forward-compatible way to define new implementations.)
## Simple answer 2: Define a new SocksPort where Username/Password means Username/Password
Both C Tor and Arti have the ability to define flags on a SocksPort. We could in principle define a flag that means, "On this particular SocksPort, Username/Password authentication is required, prop351 semantics are not available, and the username/password must be on some list of approved users."
(Again we'd need to actually design and implement this, but it's not impossible.)
## Trickier answer: How to do it if your application is using Arti RPC
With the Arti RPC subsystem (that's Arti's equivalent of C Tor's control port), when your app authenticates an Arti RPC connection, it gets an Object ID for an object called a Session. According to this proposal as amended at [tospec!280], you open a SOCKS connection within a session by setting your username to `<torS0X>1session_id_goes_here`. (Note that Session IDs are fairly long, and deliberately hard to guess.)
Taken together, this would make it possible to add a SocksPort flag that means "Don't allow any SOCKS connections unless they are on a session."
With this flag, if your application is already authenticating with Arti RPC and linking its sockets via the mechanism defined here, it would be allowed to connect, but Arti would shut out any application that wasn't configured to do so.
## Philosophical answer: what are we restricting here and why?
It's not immediately clear to me _why_ it's considered a risk for another application to be able to open connections through the same Tor proxy as yours. Naturally, you wouldn't want another app to use the same circuits as yours, but you can mostly[^1] solve that by setting your username/password to any hard-to-guess random values, and having stream isolation code take care of that for you.
I guess that we might worry about side-channel attacks, where a hostile application is sending traffic through the Tor proxy in order to introduce a timing signal into your traffic? But any application with network access could do that, whether it has Tor access or not.
[^1]: Actually, wait. There's a possible problem here when you're making lots of onion service connections, since IIRC in C Tor onion service circuits aren't affected by isolation. But in Arti, they are. So at least that problem will go away as Arti moves to the fore.
## An answer you probably can't use: embedding Arti
Right now, you can embed Arti in any Rust app. Some folks have already started to write wrappers for Java and other languages. With our RPC protocol, we intend to support embedding Arti in any application written in any language that can call C and link a library.
So with this solution, there is no SOCKS port at all, and nobody can use your Tor client but you.
## An answer you probably can't use: OS-specific restrictions
Because somebody will mention it if I don't: you could probably cobble something together using OS specific restrictions, like containers or selinux. Of course, this isn't really something you can ship in a convenient cross-platform way AFAIK, so it probably isn't going to be any portable application's first resort.
----- Sorry for all the text! But I do hope it's at least somewhat interesting.
best wishes,