Trac: Status: new to accepted Owner: N/Ato dgoulet Summary: dos: Add an option to block tor2web requests at the HSDir to dos: Block single hop client at the HSDir Points: N/Ato 0.1 Milestone: Tor: unspecified to Tor: 0.4.2.x-final Sponsor: N/Ato Sponsor27-must
This one... I have honestly no idea how to pull this off with our current tor code.
Problem is that when the GET requests comes in for the descriptor, we only learn what it is in the directory connection layer which doesn't have any clue about the circuit.
I've tried to take the approach we use with edge_connection_t where we put the circuit pointer in it (on_circuit) but since the directory request code is called from the connection read callback, there is no access to the circuit at that level either...
Solution is to test the directory connection channel to know if it is a client or not.
This code will allow HSDir connections from relays that are not in the consensus.
So an attacker could configure their client/onion service as an unpublished relay to pass this check.
(I'm not sure if tor2web mode supports a relay on the same instance, but I think it probably does.)
Do we want to allow this workaround?
We could check that the previous hop is a relay in the consensus.
If we do that check. then a small number of HSDir requests will fail, and the client will try another HSDir with another circuit.
Do we want to pay this cost?
We could check that the previous hop is a relay in the consensus.
If we do that check. then a small number of HSDir requests will fail, and the client will try another HSDir with another circuit.
Careful there! That might be true for client requests (doing a GET), but it will be less true for service requests (doing a POST).
Maybe I missed it, but, is there something specific we're aiming to fix with this patch? Or is this just completeness from the earlier "stop allowing single-hop anything" changes?
We could check that the previous hop is a relay in the consensus.
If we do that check. then a small number of HSDir requests will fail, and the client will try another HSDir with another circuit.
Careful there! That might be true for client requests (doing a GET), but it will be less true for service requests (doing a POST).
This checks if the previous channel is client or not. That is unauthenticated. If the link is unauthenticated, then it is denied.
The case of a service posting a descriptor will always work as long as the service does it through relays in consensus or not. If I'm not mistaken (?), all public relays will authenticate.
The case of the client trying to go around that check with a relay not in the consensus I believe will still authenticate on the link? Unless it is a bridge?
After discussion with teor on IRC, it appears the patch are good.
Reason is that a single onion service will always 3-hop to the HSDir. Thus anything not authenticating on the directory connection channel means it is not a public relay.
The goal of this is also to not allow C -> Bridge -> HSDir.
Maybe I missed it, but, is there something specific we're aiming to fix with this patch? Or is this just completeness from the earlier "stop allowing single-hop anything" changes?
To answer your question Roger, completeness yes. Point is to close down any access to HS component in a single hop fashion to both remove load on the network but also stop very early any single hop clients instead of stopping them at the rendezvous point only.
Code looks good to me, and this is not something that I consider unittestable, but I'd really appreciate good real-life testing. Have we tested this in the real network or chutney? It would be great to verify that descriptor uploads/downloads work just fine with client/HS/single-HS.
Code looks good to me, and this is not something that I consider unittestable, but I'd really appreciate good real-life testing. Have we tested this in the real network or chutney? It would be great to verify that descriptor uploads/downloads work just fine with client/HS/single-HS.
We can use "make test-network-all", or merge this branch with #29280 (moved), and Travis will run chutney to check client, HS, and single onion services.
We should also check the tor logs in chutney, because sometimes bugs show up there was warnings.
Also travis seems broken.
And Appveyor didn't even run.
I closed and re-opened the pull request.
Ok turns out that a unit test needed more love to pass the "connection is anonymous" test added by this branch.
HOWEVER, it highlighted a problem with the approach.
The linked_conn onto a directory connection is always of type EXIT. I'm going back to the point where I do not know how to get the or_connection_t that the dir_connection_t is coming from...
Ok turns out that a unit test needed more love to pass the "connection is anonymous" test added by this branch.
HOWEVER, it highlighted a problem with the approach.
The linked_conn onto a directory connection is always of type EXIT. I'm going back to the point where I do not know how to get the or_connection_t that the dir_connection_t is coming from...
BEGINDIR connections are dir connections, linked to an exit stream, which is on an OR circuit, which is on an OR connection.
I've almost redid the entire branch so I just rebased-squashed to latest master and force push the PR. It needs the review to start from the beginning. Unit tests and chutney tests pass.
Do we need to check for "marked for close" on the circuit or channel as well?
I'm not entirely sure actually... If the circuit or channel is closed, the descriptor will never be sent back. But if the edge connection is closed, then we sorta need to also deny the request even though it is not really suppose to happen...
I added some comment to the PR but I feel like I don't know enough about the conn/circuit subsystem to be able to review this effectively, given its reachability conseuqences in case of bug. Perhaps I can pass this to someone else (like Nick or Tim) next week?
Do we need to check for "marked for close" on the circuit or channel as well?
I'm not entirely sure actually... If the circuit or channel is closed, the descriptor will never be sent back. But if the edge connection is closed, then we sorta need to also deny the request even though it is not really suppose to happen...
Thoughts?
Let's do the closed and mark for closed checks, but BUG() if they ever happen?
Then we can switch the ones that do happen to info logs.
I added some comment to the PR but I feel like I don't know enough about the conn/circuit subsystem to be able to review this effectively, given its reachability conseuqences in case of bug. Perhaps I can pass this to someone else (like Nick or Tim) next week?
I can do the review. I wrote the code that this function is based on.