Hi everyone,
At the beginning of March we launched a social media campaign to recruit more testers of Snowflake on Tor Browser Alpha, with the intention of stress-testing the system as traffic is amped up. To collect feedback in a slightly more structured manner, the Anti-Censorship team designed a survey which ran on our LimeSurvey instance (survey.torproject.org) for the month of March and a little into April.
The response was amazing, and we got over 700 submissions from Snowflake users. A lot of it involved qualitative, freeform feedback too – which isn't included in the report to protect the privacy of our participants – but has been received and read by both the Anti-Censorship and UX teams at Tor (and we're very grateful for it!).
I won't spoil anything, but you can find a copy of the short report in PDF format here (direct download):
https://gitlab.torproject.org/tpo/ux/research/-/raw/master/reports/2021/pub… <https://gitlab.torproject.org/tpo/ux/research/-/raw/master/reports/2021/pub…>
Thank you very much to everyone who participated, and let us know if you have any questions or comments about the results!
—
Duncan Larsen-Russell
UX Designer
duncan(a)torproject.org <mailto:duncan@torproject.org>
We'll have a meeting tomorrow to talk about redesigning changing the
format of client–broker rendezvous messages, in order to support client
registration methods other than domain-fronted HTTPS. To save time, this
message has a proposed agenda and background information to read before
the meeting.
- Answer questions about background, the status quo, and future broker
development goals.
- Message versioning
- Inside or outside JSON?
- Backward compatibility with legacy-format messages.
- Future need for encrypted/signed messages.
- How do alternative rendezvous methods interface with the broker?
- Same process or separate processes?
- If separate, then how does IPC with the broker work? Convert
registrations to localhost HTTP, or create some other local
communication protocol?
Recent work on this topic is:
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snow…https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snow…
Background
A client sends a message to the Snowflake broker to request proxy
service. See https://www.bamsoftware.com/papers/thesis/#p279 for a
high-level description. Concretely, the client sends a domain-fronted
HTTP POST request with a body that is a JSON serialization of an SDP
offer (https://pkg.go.dev/github.com/pion/webrtc/v3#SessionDescription):
https://gitweb.torproject.org/pluggable-transports/snowflake.git/tree/clien…
A request looks like this:
POST /client HTTP/1.1
Snowflake-NAT-Type: restricted
{"type":"offer","sdp":"v=0\r\n..."}
If the broker can match the client with a proxy, the response has status
200 and the body is the JSON serialization of an SDP answer:
HTTP/1.1 200 OK
{"type":"answer","sdp":"v=0\r\n..."}
If the broker cannot make a match, the response has a status of 503 or
504, and an empty body:
HTTP/1.1 503 Service Unavailable
If there is a syntax problem with the client's offer, the response has
status 400:
HTTP/1.1 400 Bad Request
The problem with the current message formats is that they rely of
features of HTTP not present in other protocols, and they are not easily
extensible. The HTTP bodies are assumed to contain an SDP offer/answer
and that only, so any side information has to go somewhere else, such as
Snowflake-NAT-Type which is sent in an HTTP header (#34129). The
200/503/400 status codes also are not present in other protocols.
Parts of what is conceptually a single message are scattered across the
HTTP body, header, and status code. The goal is to move all the
information into a common message format that can also be used by other
rendezvous channels. That means *all* the necessary information will be
present in the HTTP body, and status codes will always be 200.
Some past design sketches:
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snow…
When the client requests /client, the broker returns either a
200 with a response body, an empty 503, or an empty 400. This is
awkward when doing rendezvous over non-HTTP channels, or even
over AMP cache, which doesn't reliably pass through the server's
original status code... It would be easier if all the necessary
information in the broker's response were in the HTTP body,
because that's easier to port to other channels.
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snow…
I propose to remove this ambiguity by including the data payload
inside the JSON object that represents an error. Just like in an
HTTP response, we have two things—a status code and a
message—inside one package.
We have already made a similar change to /proxy messages, for example
changing status codes 200 and 504 to the strings "client match" and
"no match":
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snow…https://github.com/cohosh/snowflake/pull/8/files
We don't have plans to use anything other than HTTP for proxy–broker
messages, so it was less important in that case to remove all reliance
on HTTP. We are also generally less concerned about backward
compatibility for proxies than we are for clients.
cohosh has drafted a merge request that moves almost all message
information into JSON in HTTP bodies:
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snow…https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snow…
The above client request would become:
POST /client HTTP/1.1
{"Version":"1.0","Offer":{"type":"offer","sdp":"v=0\r\n..."},"NAT":"restricted"}
In the event of a match, the responses would be:
HTTP/1.1 200 OK
{"Answer":{"type":"answer","sdp":"v=0\r\n..."}}
If no match:
HTTP/1.1 200 OK
{"Error":"timed out waiting for answer!"}
Parsing errors currently still use an HTTP status code:
HTTP/1.1 400 Bad Request
This work is primarily towards the goal of supporting other rendezvous
methods:
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snow…
But we also want to keep in mind other development goals for the
Snowflake broker. We want to encrypt and authenticate broker messages in
the future, and the message format should facilitate that, without our
having to think of another backcompat scheme in the future:
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snow…
And we want to be able to move the broker away from being one big
process that manages everything. Ideally, different rendezvous methods
run in different processes, with reduced privileges, and can crash and
be restarted independently of the main broker.
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snow…
Hey everyone,
We're in the process of switching to using `main` as the default branch
in our repositories. I've created a ticket to document and manage this
switch:
https://gitlab.torproject.org/tpo/anti-censorship/team/-/issues/6
The impact to contributors will be small. Those who have already cloned
the repository just need to remember to develop new patches off of the
`main` branch. Merge requests in Gitlab will automatically open against
the default branch, so if your MR has more commits than you expect
you'll just need to rebase it onto the main branch.
The hardest part is on the maintainer side since we manage so many
repositories. I've tried to document all the repositories in the ticket
above, but left out some very old unmaintained repos (such as pyptlib)
that I don't have permission to maintain. If in the unlikely event these
projects are brought back to life we can deal with a branch change then.
If you think anything on or off this list is a mistake, feel free to
comment on the ticket!
For the procedure, I'll be running this script written by anarcat (our
sysadmin):
https://gitlab.com/anarcat/scripts/-/blob/main/git-branch-rename-remote
The script will generally:
- run `git branch --move master main`
- change symbolic refs for remote:
`git symbolic-ref refs/remotes/remote/HEAD \
refs/remotes/remote/main`
- set local branch to track new upstream
`git branch -u remote/main`
- push new main branch to remote
`git push -u remote main`
- remove old master branch from remote:
`git push -d remote master`
- For GitLab, update the default branch to main
My plan will be to make this change on Friday unless we realize there is
more prerequisite work to do. Let me know if you have questions.
Cecylia