Discussion:
[tor-dev] Pluggable Transports 2.0 Specification, Draft 2
Brandon Wiley
2017-06-20 18:07:39 UTC
Permalink
Attached is the second draft of the Pluggable Transport 2.0 Specification.
If you have feedback on this draft, please send me your comments by July 20.
Brandon Wiley
2017-06-20 19:22:26 UTC
Permalink
Changelog from Draft 1

● Renamed version flag to ptversion to avoid naming conflict with goptlib
● Modified Go examples to use correct Go syntax
● Renamed pt module in Go examples to base to avoid naming conflict with
goptlib
● Reworded introduction
● Clarified Go examples with more details on how to implement a transport
in Go
● Removed unused Javascript and Python APIs
● Removed SSH transport example
● Standardized use of Transports API and Dispatcher IPC language throughout
● Added length to per-connection parameter encoding
Post by Brandon Wiley
Attached is the second draft of the Pluggable Transport 2.0 Specification.
If you have feedback on this draft, please send me your comments by July 20.
Yawning Angel
2017-06-20 22:07:05 UTC
Permalink
On Tue, 20 Jun 2017 14:07:39 -0400
Post by Brandon Wiley
Attached is the second draft of the Pluggable Transport 2.0
Specification. If you have feedback on this draft, please send me
your comments by July 20.
I'll raise this because it bothers me, but maybe the other people who
drafted the original document don't care as much as I do. I find
the attribution in the acknowledgments section entirely inadequate. I
explicitly credited all previous authors when I last rewrote the
specification for a reason.

Regards,
--
Yawning Angel
Brandon Wiley
2017-06-20 22:31:59 UTC
Permalink
Thanks for the feedback. I'll fix this in the next draft.
Post by Yawning Angel
On Tue, 20 Jun 2017 14:07:39 -0400
Post by Brandon Wiley
Attached is the second draft of the Pluggable Transport 2.0
Specification. If you have feedback on this draft, please send me
your comments by July 20.
I'll raise this because it bothers me, but maybe the other people who
drafted the original document don't care as much as I do. I find
the attribution in the acknowledgments section entirely inadequate. I
explicitly credited all previous authors when I last rewrote the
specification for a reason.
Regards,
--
Yawning Angel
_______________________________________________
tor-dev mailing list
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-dev
teor
2017-06-21 03:16:20 UTC
Permalink
Post by Brandon Wiley
If you have feedback on this draft, please send me your comments by July 20.
Thanks for putting this together.
It looks like it's taken a lot of work to do this and the implementation.

I seem to be missing some context:
What is the goal of writing this specification?

I'm going to assume you want to implement parts in tor and parts in Go.

Here is my feedback:

In general, have you searched tor trac for PT protocol bugs, and made
sure this spec doesn't suffer from the same issues?

In general, is there a separate document or proposal that describes
how Tor will implement the relevant interfaces? There doesn't seem
to be much on Tor-specific issues in this spec.

There is one "Tor" note in the spec, maybe it should be in that
separate document? Or maybe there should be more Tor notes in the
spec?

3.1. Pluggable Transport Naming

How are unique names coordinated?

When is a PT a different version of an older transport with the same
name? When does a PT need a new name?

3.2.1. Goals for interface design

Definitions:

The destination address (and many other terms) aren't defined
anywhere. Are they IPv4, IPv6, DNS, or protocol-specific?

If they are not just IPv4 addresses, please give examples with
other address types.

Maybe section 3.3.5.1 defines some of these terms?

3.3.1 Pluggable Transport Configuration Parameters

Optional Addresses:

Since the address is optional, what value is used when it is not
required by the transport?

It looks mandatory in the Go interface, but isn't mandatory in the
environmental variables. Can you please map each environmental
variable to the Go interface?

I ask because we have had some issues in Tor with PT 1.0,
because Tor Browser uses a fake IPv4 address for transports like meek.
This interacts really badly with ReachableAddresses and similar.

Any new Tor code will need to resolve this issue by using non-address
identifiers or a defined placeholder address.

We have also had bugs where tor connects to the actual bridge address
rather than a proxy. So using a placeholder address for all PTs might
be a good idea for security in tor.

Multiple Addresses:

If there are multiple addresses, are these separate instances of the
transport, or can one transport have multiple connections?
Does this differ between the client and the server?

For example, the same bridge can have an IPv4 and IPv6 address.
Or two different bridges can use the same PT.

How is this handled in tor and in Go?
(It's specified that each PT has zero or one addresses, but there
isn't anything explicit about using multiple addresses.)

Banned Addresses:

Tor users often configure ReachableAddresses (or similar) and expect
pluggable transports to respect them. Is there a standard way of
telling a transport which addresses it can't connect to?

Or, alternately, is there a standard way for a transport to tell tor
which addresses it is actually using *before* it connects to it?

Client Addresses:

The client protocol is missing a standard way to configure:
* a local bind address
* a remote server address
* other common PT info

Is this intentional?
If so, do we really want each transport defining its own slightly
different JSON keys for common items like addresses?
Even worse, what if they format addresses inconsistently?

This will be difficult to implement in applications if it is not
standardised.

I suggest we make the server address an environmental variable.

3.3.1.4 Command Line Flags

How is an environmental variable name turned into a command-line flag?
Or are the command-line flags different for each transport?
(Let's not do that, it would be annoying.)

You give examples, but some have typos:
obfs4proxy -state =/var/lib/tor/pt_state/
obfs4proxy - transports obfs3,scramblesuit
Obfs4proxy -options scramblesuit:key=banana;automata:rule=110;automata:depth=3

3.3.2. Pluggable Transport To Parent Process Communication

What is the correct IPv6 address quoting for CMETHOD and SMETHOD?
Please give an example in the text.

"Equal signs and commas MUST be escaped with a backslash."

This is unclear: equals signs and commas in Key and Value?
What about colons or backslashes?
(Otherwise, it is impossible to end a value with a backslash.)
Must Key be an identifier? What's the format?

Why not just use an existing escaping scheme?

"Tor: The ARGS are included in the transport line of the Bridge's extra-info document."

Really? This seems insecure. Do we publish bridge extra-infos anywhere?

3.3.5 UDP Support

The TOC breaks here.

3.3.5.1 Obfuscating Proxy Architecture

This section belongs at the top of the document.

3.3.5.2. Configuring the Transports

There are no details for how this works over UDP: what is the UDP
equivalent to Pluggable PT Client Per-Connection Arguments, and do
TCP implementations have to support that environmental variable as
well?

I suggest we standardise it as an environmental variable and
command-line flag, and make all transports support it.

3.3.5.5. Implementation of the PT Server

Is the text in this section two different sizes?

T
--
Tim Wilson-Brown (teor)

teor2345 at gmail dot com
PGP C855 6CED 5D90 A0C5 29F6 4D43 450C BA7F 968F 094B
ricochet:ekmygaiu4rzgsk6n
xmpp: teor at torproject dot org
------------------------------------------------------------------------
David Fifield
2017-06-21 04:27:35 UTC
Permalink
Post by teor
In general, is there a separate document or proposal that describes
how Tor will implement the relevant interfaces? There doesn't seem
to be much on Tor-specific issues in this spec.
There is one "Tor" note in the spec, maybe it should be in that
separate document? Or maybe there should be more Tor notes in the
spec?
As I understand it, one of the goals of the PT 2.0 spec is to make it
easier for projects *other* than Tor to use pluggable transports. The
current spec (the 1.0 spec) basically doesn't work for anyone other than
desktop Tor--this is something we've heard over and over from other
projects that use circumvention, and Brandon is well plugged in to those
conversations. Even closely affiliated projects like Orbot haven't been
able to use pluggable transports strictly according to the spec, because
of the various constraints on mobile platforms.

What various circumvention developers have said they prefer, is a
Go-based API. They would rather link against a library, than do the
whole subprocess-and-stdout thing that the PT 1.0 spec requires. That's
the reason for introducing the new Go stuff in the 2.0 spec. Inside and
outside Tor, a lot of projects have converged on implementing their
circumvention code in Go. The API of the 2.0 spec is based on the
internal architecture of obfs4proxy, which is de facto the main
implementation of most of Tor's pluggable transports.

If I understand correctly, Tor wouldn't have to implement glue code to
interface with the Go API. It could continue spawning subprocesses,
similar to what it does now. The executables it invokes, if they are
written in Go, will likely internally use a PT library that uses the 2.0
spec's API, but Tor wouldn't have to know those details.

PT 1.0 succeeded in being "pluggable" in one sense: it's easy to hotswap
a lot of circumvention technologies within Tor. But it failed in being
"pluggable" in another sense: it's not easy to share common transport
modules beyond Tor (in either direction). It would be great if the new
spec can realize that second sense of pluggability.
teor
2017-06-21 04:42:18 UTC
Permalink
Post by David Fifield
Post by teor
In general, is there a separate document or proposal that describes
how Tor will implement the relevant interfaces? There doesn't seem
to be much on Tor-specific issues in this spec.
There is one "Tor" note in the spec, maybe it should be in that
separate document? Or maybe there should be more Tor notes in the
spec?
As I understand it, one of the goals of the PT 2.0 spec is to make it
easier for projects *other* than Tor to use pluggable transports. The
current spec (the 1.0 spec) basically doesn't work for anyone other than
desktop Tor-...
There are also edge cases where it works badly even for desktop Tor.
Post by David Fifield
Post by teor
I ask because we have had some issues in Tor with PT 1.0,
because Tor Browser uses a fake IPv4 address for transports like meek.
This interacts really badly with ReachableAddresses and similar.
Any new Tor code will need to resolve this issue by using non-address
identifiers or a defined placeholder address.
We have also had bugs where tor connects to the actual bridge address
rather than a proxy. So using a placeholder address for all PTs might
be a good idea for security in tor.
Tor users often configure ReachableAddresses (or similar) and expect
pluggable transports to respect them. Is there a standard way of
telling a transport which addresses it can't connect to?
Or, alternately, is there a standard way for a transport to tell tor
which addresses it is actually using *before* it connects to it?
If I understand correctly, Tor wouldn't have to implement glue code to
interface with the Go API. It could continue spawning subprocesses,
similar to what it does now. The executables it invokes, if they are
written in Go, will likely internally use a PT library that uses the 2.0
spec's API, but Tor wouldn't have to know those details.
I wasn't talking about interfaces, I was talking about the configs
exchanged via the protocol regardless of interface.

If we want to fix some of these application issues, we need to make sure
the protocol provides the means to do so. Regardless of how tor interfaces
or updates its PT interface.
Post by David Fifield
PT 1.0 succeeded in being "pluggable" in one sense: it's easy to hotswap
a lot of circumvention technologies within Tor. But it failed in being
"pluggable" in another sense: it's not easy to share common transport
modules beyond Tor (in either direction). It would be great if the new
spec can realize that second sense of pluggability.
It would be great if this new spec could also fix some of the issues
around transport addresses, regardless of the application using it.

Or, we could rule those issues explicitly out of scope, essentially
pushing them onto each individual transport and application to deal
with in a custom manner. (Or, more likely, to ignore.)
Post by David Fifield
Post by teor
* a local bind address
* a remote server address
* other common PT info
Is this intentional?
If so, do we really want each transport defining its own slightly
different JSON keys for common items like addresses?
Even worse, what if they format addresses inconsistently?
T
--
Tim Wilson-Brown (teor)

teor2345 at gmail dot com
PGP C855 6CED 5D90 A0C5 29F6 4D43 450C BA7F 968F 094B
ricochet:ekmygaiu4rzgsk6n
xmpp: teor at torproject dot org
------------------------------------------------------------------------
Yawning Angel
2017-06-21 06:20:44 UTC
Permalink
On Tue, 20 Jun 2017 21:27:35 -0700
Even closely affiliated projects like Orbot haven't been able to use
pluggable transports strictly according to the spec, because of the
various constraints on mobile platforms.
This is basically totally and utterly wrong.

https://gitweb.torproject.org/orbot.git/tree/orbotservice/src/main/java/org/torproject/android/service/TorService.java#n1691

(The extra acrobatics are for programatically generating the config to
handle the binary's install path being system dependent, which is
beyond the scope of the PT spec itself.)

Orbot can use normal Pluggable Transports just fine, and has at various
points in time used:

* obfsproxy (C)
* obfsclient (C++)
* obfs4proxy

All basically exactly as specified by the Pluggable Transports spec.
The only problem in this regard has been "Python on Android was a
nightmare" which precluded the deployment of obfsproxy (Python). This
has little to nothing to do with the Pluggable Transport spec itself.

Perhaps you mean iOS? In which case, yeah, implementing something
that's based around fork + exec, on an OS that doesn't allow that, is
difficult, go figure (https://github.com/mtigas/iObfs for how it's
done).
The API of the 2.0 spec is based on the internal architecture of
obfs4proxy, which is de facto the main implementation of most of
Tor's pluggable transports.
I don't think that's a good idea, because the API was written by me, for
me, to fit my use-cases (and I'm more and more dissatisfied with Go, to
the point where all my new "for fun" code is going to be in C++ or D).

But if it works for them, great I guess. I didn't use the API when I
was working on basket2, so this has 0 impact on anything I will be
doing, or anything that I've written.
But it failed in being "pluggable" in another sense: it's not easy to
share common transport modules beyond Tor (in either direction). It
would be great if the new spec can realize that second sense of
pluggability.
I still don't understand what was so hard about implementing the old
API, on anything but iOS.

The "2.0" spec still doesn't have any provisions for using AF_LOCAL
instead of the loopback interface, go figure. It's not as if I bring
it up every time this topic comes up or anything right?

Regards,
--
Yawning Angel
teor
2017-06-21 13:00:30 UTC
Permalink
Post by Yawning Angel
The "2.0" spec still doesn't have any provisions for using AF_LOCAL
instead of the loopback interface, go figure. It's not as if I bring
it up every time this topic comes up or anything right?
Th exact types of addr and port are not specified, so application
could pass:
unix:/var/run/tor/obfsocket
And still remain within the spec.

But to make this usage clear, I suggest we change:
<addr:port>
To:
<addr>[:<port>]
And define addr as either an IPv4, IPv6, hostname, file path, or some
other address understood by the application / proxy.

If we don't want to do that, please at least change it to:
<addr>:<port>

T

--
Tim Wilson-Brown (teor)

teor2345 at gmail dot com
PGP C855 6CED 5D90 A0C5 29F6 4D43 450C BA7F 968F 094B
ricochet:ekmygaiu4rzgsk6n
xmpp: teor at torproject dot org
------------------------------------------------------------------------
teor
2017-07-20 11:54:06 UTC
Permalink
Hi Brandon,

There's a bunch of feedback in this thread.

Some of it involves relatively minor spec updates or clarifications.
Other parts involve solving complex issues, and might belong in
another spec (or a future version of the PT spec).

Can you let us know which feedback will make it into PT 2.0?

Thanks

Tim
Post by teor
Post by Yawning Angel
The "2.0" spec still doesn't have any provisions for using AF_LOCAL
instead of the loopback interface, go figure. It's not as if I bring
it up every time this topic comes up or anything right?
Th exact types of addr and port are not specified, so application
unix:/var/run/tor/obfsocket
And still remain within the spec.
<addr:port>
<addr>[:<port>]
And define addr as either an IPv4, IPv6, hostname, file path, or some
other address understood by the application / proxy.
<addr>:<port>
T

--
Tim Wilson-Brown (teor)

teor2345 at gmail dot com
PGP C855 6CED 5D90 A0C5 29F6 4D43 450C BA7F 968F 094B
ricochet:ekmygaiu4rzgsk6n
xmpp: teor at torproject dot org
------------------------------------------------------------------------
David Fifield
2017-06-21 15:12:28 UTC
Permalink
Post by Yawning Angel
On Tue, 20 Jun 2017 21:27:35 -0700
Even closely affiliated projects like Orbot haven't been able to use
pluggable transports strictly according to the spec, because of the
various constraints on mobile platforms.
This is basically totally and utterly wrong.
I'm sorry. I guess this bit of folk knowledge I had picked up was wrong.
I thought it was somehow more complicated. I may have been confusing
Android and iOS issues.
Brandon Wiley
2017-10-10 19:25:58 UTC
Permalink
Hi teor. Thank you for the detailed feedback on the Pluggable Transport
2.0, Draft 2 proposal.

Your email covers a number of topics, which I will attempt to address. I
have grouped the issues you've raised into some different categories.

1. Issues inherited from the PT 1.0 specification - We tried not to make
many large changes from PT 1.0 in order to preserve as much compatibility
as possible. We would be happy to discuss making additional changes in the
upcoming PT 2.1 specification process.

2. Feature requests to help serve the needs of Tor - Tor folks were
certainly involved in the PT 2.0 specification process. Roger, Nick, and
Yawning attended the meetings. However, I can see that there are some
feature requests from you and Yawning that did not make it into the PT 2.0
specification. We would love to see these discussed as part of the PT 2.1
specification. I have already made a note to include them on the agenda for
the Pluggable Transport Implementers Meeting, which is happening after
TorDev. If you would like to participate in the specification process, that
would be very helpful and ensure that these feature requests make it into
the proposal and are specified in a way that meets your needs for Tor.

3. Requests for clarification - These have generally been incorporated into
the latest draft, PT 2.0 draft 3. I will be sending this out shortly. I
hope that you will find that the new draft addresses many of the areas that
you found unclear in the previous draft.

4. Clarification of issues outside of the scope of the specification
document - I will attempt to answer these below:

How will Tor implement the relevant interfaces?

These is discussed in this Trac issue from the last TorDev:
https://trac.torproject.org/projects/tor/ticket/21816

The code changes to Tor are minimal. The authentication method uses to send
per-connection arguments to transports has been changed in PT 2.0 to use a
custom SOCKS authentication method instead of using the username and
password authentication method. No other changes are required to Tor to use
PT 2.0 transport providers. We have provided a patch to Tor to implement
this functionality in a backwards-incompatible way, so both PT 1.0 and PT
2.0 providers can be used with the patch. We have also implemented a PT
2.0-compatible transport provider, which is available here:
https://github.com/OperatorFoundation/shapeshifter-dispatcher/

Can you please map each environmental variable to the Go interface?

There is not a one-to-one mapping between the environment variables and the
Go interface. There are two parts to the PT implementation. There is the
proxy and there are the transports. The environment variables are for
configuring the proxy, which includes the information necessary to
configure the transports. The Go interface is for using the transports
directly in your code, without a proxy process. Therefore, only a subset of
the information specified for the environment variables is required when
using the Go interface, and so a one-to-one mapping is not possible.

What is the UDP equivalent to PT Client Per-Connection Arguments?

There is no equivalent to PT Client Per-Connection Arguments for UDP. PT
1.0 supported only one proxy mode, SOCKS5. PT 2.0 supports multiple proxy
modes, but only the SOCKS5 proxy mode supports PT Client Per-Connection
Arguments. This is because it is the SOCKS5 protocol that provides the
channel to supply PT Client Per-Connection Arguments (through the custom
authentication method). You may be wondering, how do you use a transport
that requires PT Client Per-Connection Arguments in a proxy mode other than
SOCKS5 (for instance, UDP). You can set them when you start the PT client
using the -options command line flag. Of course, in this scenario, they
will not be "per connection" as they will be the same for every connection.
However, this should work fine with the current PTs. If you truly need
per-connection arguments, then you are limited to SOCKS5.

I hope that I have answered some of your questions. I will be at TorDev all
week, so I would love to discuss some of the finer details with you at your
convenience.

Also, I wanted to clear up one thing that was said later in this thread.
The Go transports API is not based on the obfs4proxy internal API. The very
first draft was based on the obfs4proxy code and everyone agreed that this
was not ideal. The current Go API specified in PT 2.0 draft 3 is based on
the Go net.Conn API. following the general principle set forth in the
specification document to make the transport library look as much as
possible like the native socket implementation for the language.
Post by Brandon Wiley
Post by Brandon Wiley
If you have feedback on this draft, please send me your comments by
July 20.
Thanks for putting this together.
It looks like it's taken a lot of work to do this and the implementation.
What is the goal of writing this specification?
I'm going to assume you want to implement parts in tor and parts in Go.
In general, have you searched tor trac for PT protocol bugs, and made
sure this spec doesn't suffer from the same issues?
In general, is there a separate document or proposal that describes
how Tor will implement the relevant interfaces? There doesn't seem
to be much on Tor-specific issues in this spec.
There is one "Tor" note in the spec, maybe it should be in that
separate document? Or maybe there should be more Tor notes in the
spec?
3.1. Pluggable Transport Naming
How are unique names coordinated?
When is a PT a different version of an older transport with the same
name? When does a PT need a new name?
3.2.1. Goals for interface design
The destination address (and many other terms) aren't defined
anywhere. Are they IPv4, IPv6, DNS, or protocol-specific?
If they are not just IPv4 addresses, please give examples with
other address types.
Maybe section 3.3.5.1 defines some of these terms?
3.3.1 Pluggable Transport Configuration Parameters
Since the address is optional, what value is used when it is not
required by the transport?
It looks mandatory in the Go interface, but isn't mandatory in the
environmental variables. Can you please map each environmental
variable to the Go interface?
I ask because we have had some issues in Tor with PT 1.0,
because Tor Browser uses a fake IPv4 address for transports like meek.
This interacts really badly with ReachableAddresses and similar.
Any new Tor code will need to resolve this issue by using non-address
identifiers or a defined placeholder address.
We have also had bugs where tor connects to the actual bridge address
rather than a proxy. So using a placeholder address for all PTs might
be a good idea for security in tor.
If there are multiple addresses, are these separate instances of the
transport, or can one transport have multiple connections?
Does this differ between the client and the server?
For example, the same bridge can have an IPv4 and IPv6 address.
Or two different bridges can use the same PT.
How is this handled in tor and in Go?
(It's specified that each PT has zero or one addresses, but there
isn't anything explicit about using multiple addresses.)
Tor users often configure ReachableAddresses (or similar) and expect
pluggable transports to respect them. Is there a standard way of
telling a transport which addresses it can't connect to?
Or, alternately, is there a standard way for a transport to tell tor
which addresses it is actually using *before* it connects to it?
* a local bind address
* a remote server address
* other common PT info
Is this intentional?
If so, do we really want each transport defining its own slightly
different JSON keys for common items like addresses?
Even worse, what if they format addresses inconsistently?
This will be difficult to implement in applications if it is not
standardised.
I suggest we make the server address an environmental variable.
3.3.1.4 Command Line Flags
How is an environmental variable name turned into a command-line flag?
Or are the command-line flags different for each transport?
(Let's not do that, it would be annoying.)
obfs4proxy -state =/var/lib/tor/pt_state/
obfs4proxy - transports obfs3,scramblesuit
depth=3
3.3.2. Pluggable Transport To Parent Process Communication
What is the correct IPv6 address quoting for CMETHOD and SMETHOD?
Please give an example in the text.
"Equal signs and commas MUST be escaped with a backslash."
This is unclear: equals signs and commas in Key and Value?
What about colons or backslashes?
(Otherwise, it is impossible to end a value with a backslash.)
Must Key be an identifier? What's the format?
Why not just use an existing escaping scheme?
"Tor: The ARGS are included in the transport line of the Bridge's extra-info document."
Really? This seems insecure. Do we publish bridge extra-infos anywhere?
3.3.5 UDP Support
The TOC breaks here.
3.3.5.1 Obfuscating Proxy Architecture
This section belongs at the top of the document.
3.3.5.2. Configuring the Transports
There are no details for how this works over UDP: what is the UDP
equivalent to Pluggable PT Client Per-Connection Arguments, and do
TCP implementations have to support that environmental variable as
well?
I suggest we standardise it as an environmental variable and
command-line flag, and make all transports support it.
3.3.5.5. Implementation of the PT Server
Is the text in this section two different sizes?
T
--
Tim Wilson-Brown (teor)
teor2345 at gmail dot com
PGP C855 6CED 5D90 A0C5 29F6 4D43 450C BA7F 968F 094B
ricochet:ekmygaiu4rzgsk6n
xmpp: teor at torproject dot org
------------------------------------------------------------------------
_______________________________________________
tor-dev mailing list
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-dev
Loading...