Filename: xxx-pluggable-transport.txt Title: Pluggable transports for circumvention Author: Jacob Appelbaum, Nick Mathewson Created: 15-Oct-2010 Status: Draft Overview This is a document about transport plugins; it does not cover discovery, or bridgedb improvements. Each transport plugin specification should make clear any external requirements but those are generally out of scope if they fall into discovery or infrastructure components. We should include a description of how to write a good set of plugins, how to evaluate and how to classify a plugin. For example, if a plugin is said to be hard to detect on the wire if you know what it is and how it works, it should say so. If it's easy, it's still possibly functional for a given network but perhaps it is not well hidden or automatically filtered. Detection and blocking are not always the same thing right off. In both cases, a plugin should be quite clear about its security claims. Target use-cases[a][b] Here's some stuff we want to be able to support. We're listing these in the draft to try to define the problem space. We won't put this section in the final version. 1. The 'obfuscated SSH' superencipherment: http://github.com/brl/obfuscated-openssh/blob/master/README.obfuscation 2. Big P2P-network style transports where instead of connecting to a bridge at a known IP, you connect to a bridge by a username, a public key, or whatever. 1. We need the ability to have two kinds of proxies - one for incoming connections and one for outgoing connections. [Sure, but that's about how we implement stuff arg arg dumb touchpad -NM] 1. Probably we want to have the ability to get connections anyway we'll take them 2. So, bridges use the incoming kind, and clients use the ougoing kind? Sounds right.-N 1. Probably also we're a multi-plexed incoming kind of Tor relay - so we should take connections from say localhost's little helper and also, we should take connections from external ips. This would be useful to identify though. I think this is how we would already work as of today. 1. You mean, regular non-bridge relays should support this too? I hadn't considered that. it has seemed pointless because of IP blocking, but if we have a p2p transport, it would be useful for regular relays to allow it. Yes -io 1. Also it would be nice for stats purposes to ensure that we know what kinds of connections we're handling, even if we basically treat them exactly the same. Perhaps Karsten wants to weigh in on how we should have Tor handle these things? I guess we'll really fuck up his stats collection if all of sudden he's getting lots of connections from 127.0.0.1... 1. Various protocol-impersonation tools 1. NSTX, iodyne, Ozymandns or such, for the lulz. 1. DNS tunneling of many types - eg: TXT records or the NULL protocol trick 1. HTTP -- many kinds are possible, some may even be right 1. HTTP POST requests are implemented in Firepass 1. FTP 1. Perhaps some kind of anonymous ftp login with sending and receiving of data would be useful? 1. Lots to think about before designing off the cuff crappy protocol covert channels 1. NTP 1. Hardly anyone knows about NTP these days - it's almost always outbound allowed and it's usually not well inspected 1. That makes it good for short-term circumvention, but bad for long-term hiding. 1. Triangle-boy 2. IPSec look-alike 3. UDP 4. IPv6 1. A forged-RST-ignoring tool 1. A forged-RST-ignoring tool that pretends that it is getting all of its connections closed and retrying all the time, when really it is just carrying on with business as usual. Hooray for crypto. 1. Perhaps it's a good idea to mention CCTT? 1. What else goes here? 1. We should ask Nextgens about protocol filters from Freenet 2. http://gray-world.net/papers.shtml 3. http://gray-world.net/pr_cook_cc.shtml 4. http://gray-world.net/pr_firepass.shtml 5. We should ensure we cover the topics and lessons learned from "FIREWALL RESISTANCE TO METAFEROGRAPHY IN NETWORK COMMUNICATIONS" - see https://ritdml.rit.edu/bitstream/handle/1850/12272/RSavacoolThesis5-21-2010.pdf Here's some stuff that seems out-of-scope: 1. A generic firewall-breaker that works with all Tor nodes and bridges. Like, if you're using a VPN to get through your firewall, and it lets you connect to any Tor node, you can just use it without any special plug-in support. I think this spec is just for stuff that requires buy-in from the server side of the connection. Agreed? 1. Yeah - I think we should simply codify the proxy stuff to ensure that we plan to remain pluggable for incoming and outgoing connections in some formal way. I'm uncertain if we want to support stuff like: 1. An ssh tunnel that uses openssh to tunnel raw tor packets, with no actual TLS going on underneath. Promising, but risky. -NM 1. I think there isn't much to gain by doing this but perhaps so - we are too dependent on TLS and our certs are trivial to fingerprint -io 1. Also, Tor-over-TLS-tunneled-over-SSH looks even weirder than Tor-over-SSH. -N 2. It might be nice to allow certs [cn] fields to be configurable by bridge nodes? -io 1. If we allowed "raw traffic" transports, a transport could get this trivially by implementing TLS with the right certs. -NM 1. perhaps we just want a "raw traffic port" where we connect to pass around cells? thoughts? 1. A bridge-discovery-and-round-robin p2p tool that connects you to a randomly chosen one of an unknown number of bridges. 1. Stackable plugins 1. Tor over DNS over HTTP Post over Obfuscated Tor to reach the Tor network to read a copy of uncensored Google News. 1. Christ, what the fuck world are we building? Or even more, what kind of world are we resisting? 1. More like RST-drop plus sshobfs over HTTP over VPN. Goals & Motivation Frequently, people want to try a novel circumvention method to help users connect to Tor bridges. Some of these methods are already pretty easy to deploy: if the user knows an unblocked VPN or open SOCKS proxy, they can just use that with the Tor client today. Less easy to deploy are methods that require participation by both the client and the bridge. In order of increasing sophistication, we might want to support: 1. A protocol obfuscation tool that transforms the output of a TLS connection into something that looks like HTTP as it leaves the client, and back to TLS as it arrives at the bridge. 2. An additional authentication step that a client would need to perform for a given bridge before being allowed to connect. 3. An information passing system that uses a side-channel in some existing protocol to convey traffic between a client and a bridge without the two of them ever communicating directly. 4. A set of clients to tunnel client->bridge traffic over an existing large p2p network, such that the bridge is known by an identifier in that network rather than by an IP address. We could in theory support these almost fine with Tor as it stands today: every Tor client can take a SOCKS proxy to use for its outgoing traffic, so a suitable client proxy could handle the client's traffic and connections on its behalf, while a corresponding program on the bridge side could handle the bridge's side of the protocol transformation. Nevertheless, there are some reasons to add support for transportation plugins to Tor itself: 1. It would be good for bridges to have a standard way to advertise which transports they support, so that clients can have multiple local transport proxies, and automatically use the right one for the right bridge. 2. There are some changes to our architecture that we'll need for a system like this to work. For testing purposes, if a bridge blocks off its regular ORPort and instead has an obfuscated ORPort, the bridge authority has no way to test it. Also, unless the bridge has some way to tell that the bridge-side proxy at 127.0.0.1 is not the origin of all the connections it is relaying, it might decide that there are too many connections from 127.0.0.1, and start paring them down to avoid a DoS. 3. 4. (what else?) Non-Goals We're not going to talk about automatic verification of plugin correctness and safety via sandboxing, proof-carrying code, or whatever. We need to do more with discovery and distribution, but that's not what this proposal is about. We're pretty convinced that the problems are sufficiently orthogonal that we should be fine so long as we don't preclude a single program from implementing both transport and discovery extensions. This proposal is not about what transport plugins are the best ones for people to write. We've considered issues involved with completely replacing Tor's TLS with another encryption layer, rather than layering it inside the obfuscation layer. We describe how to do this in an appendix to the current proposal, though we are not currently sure whether it's a good idea to implement. Design overview Clients run one or more "Transport client" programs that act like SOCKS proxies. They accept connections on localhost on different ports. Each one implements one or more transport methods. Parameters are passed from Tor inside the regular username/password parts of the SOCKS protocol. Bridges (and maybe relays) run one or more programs that act like stunnel-server (or whatever the option is): they get connections from the network (typically by listening for connections on the network) and relay them to the Bridge's real ORPort. 1. The bridge needs to know which methods these servers support 1. The bridge needs to advertise this fact some way that the clients will find out about it--probably by sticking it in its bridge descriptor so that the bridgedb can find out and see that the clients get informed. 2. Somebody needs to launch these programs 3. The bridge may want to just not have a public ORPort at all. 4. The bridge may not want to advertise a real IP at all 5. The bridge will want to find out from the program any client identification information it can get (IP, etc) to implement rules about max clients at once Any methods that are wildly successful, we can bake into Tor. Proposed terminology: Transport protocol: Transport proxy: Specifications: Client behavior Bridge lines can now follow the extended format "bridge method address:port [[keyid=]id-fingerprint] [k=v] [k=v] [k=v]". To connect to such a bridge, a client must open a local connection to the SOCKS proxy for "method", and ask it to connect to address:port. If [id-fingerprint] is provided, it should expect the public identity key on the TLS connection to match the digest provided in [id-fingerprint]. If any [k=v] items are provided, they are configuration parameters for the proxy: Tor should separate them with NUL bytes and put them user and password fields of the request, splitting them across the fields as necessary. The "id-fingerprint" field is always provided in a field named "keyid", if it was given. example: if the bridge line is "bridge trebuchet www.example.com:3333 rocks=20 height=5.6m" then, if the Tor client knows that the ‘trebuchet' method is provided by a SOCKS5 proxy on 127.0.0.1:19999, it should connect to that proxy, ask it to connect to www.example.com, and provide the string "rocks=20\0height=5.6m" as the username, the password, or split across the username and password. There are two ways to tell Tor clients about protocol proxies: external proxies and managed proxies. An external proxy is configured with "Transport trebuchet socks5 127.0.0.1:9999". This tells Tor that another program is already running to handle ‘trubuchet' connections, and Tor doesn't need to worry about it. A managed proxy is configured with "Transport trebuchet /usr/libexec/tor-proxies/trebuchet [options]", and tells Tor to launch an external program on-demand to provide a socks proxy for ‘trebuchet' connections. The Tor client only launches one instance of each external program, even if the same executable is listed for more than one method. The same program can implement a managed or an external proxy: it just needs to take an argument saying which one to be. [I don't like the terminology here. We should pick better words before this "external/managed" stuff catches on. Also, to most users a "proxy" is a computer that relays stuff for them, not a local program on their computer. -NM I think we should go with Helper of some kind as it's less technically overloaded and more friendly feeling - io "Helper" is too overloaded already. -NM] Client proxy behavior When launched from the command-line by a Tor client, a transport proxy needs to tell Tor which methods and ports it supports. It does this by printing one or more METHOD: lines to its stdout. These look like CMETHOD: trebuchet SOCKS5 127.0.0.1:19999 ARGS:rocks,height OPT-ARGS:tensile-strength The ARGS field lists mandatory parameters that must appear in every bridge line for this method. The OPT-ARGS field lists optional parameters. If no ARGS or OPT-ARGS field is provided, Tor should not check the parameters in bridge lines for this method. The proxy should print a single "METHODS:DONE" line after it is finished telling Tor about the methods it provides. [Should methods be versionable? Can they be? -nm I think probably? -io Then how? -nm] The transport proxy MUST exit cleanly when it receives a SIGTERM from Tor. The Tor client MUST ignore lines beginning with a keyword and a colon if it does not recognize the keyword. In the future, if we need a control mechanism, we can use the stdin/stdout from Tor to the transport proxy. Transport proxy requirements A transport proxy MUST handle SOCKS connect requests using the SOCKS version it advertises. Server proxy behavior [So, we can have this work like client proxies, where the bridge launches some programs, and they tell the bridge, "I am giving you method X with parameters Y"? Do you have to take all the methods? If not, which do you specify?] [Do we allow programs that get started independently?] [We'll need to figure out how this works with port forwarding. Is port forwarding the bridge's problem, the proxy's problem, or some combination of the two?] [If we're using the bridge authority/bridgedb system for distributing bridge info, the right place to advertise bridge lines is probably the extrainfo document. We also need a way to tell the bridge authority "don't give out a default bridge line for me"] Server behavior Bridge authority behavior Implementation plan Finish the design work here. Clean up all the inline conversations to just get summarized by the conclusions they arrived at. Turn this into a draft proposal Circulate and discuss on or-dev (Use Cinderblock Of Loving Correction to reeducate anybody who tries to divert discussion of how pluggable transports should work into discussion of what is the best possible transport, or whatever.) We should ship a couple of null plugin implementations in one or two popular, portable languages so that people get an idea of how to write the stuff. 1. We should have one that's just a proof of concept that does nothing but transfer bytes back and forth. 1. We should not do a rot13 one. 2. We should implement a basic proxy that does not transform the bytes at all 1. We should implement DNS or HTTP using other software (as goodell did years ago with DNS) as an example of wrapping existing code into our plugin model. 2. The obfuscated-ssh superencipherment is pretty trivial and pretty useful. It makes the protocol stringwise unfingerprintable. 1. Nick needs to be told firmly not to bikeshed the obfuscated-ssh superencipherment too badly 1. Go ahead, bikeshed my day 1. If we do a raw-traffic proxy, openssh tunnels would be the logical choice. Appendix: recommendations for transports Be free/open-source software. Also, if you think your code might someday do so well at circumvention that it should be implemented inside Tor, it should use the same license as Tor. Use libraries that Tor already requires. (You can rely on openssl and libevent being present if current Tor is present.) Be portable: most Tor users are on Windows, and most Tor developers are not, so designing your code for just one of these platforms will make it either get a small userbase, or poor auditing. Think secure: if your code is in a C-like language, and it's hard to read it and become convinced it's safe then, it's probably not safe. Think small: we want to minimize the bytes that a Windows user needs to download for a transport client. Specify: if you can't come up with a good explanation Avoid security-through-obscurity if possible. Specify. Resist trivial fingerprinting: There should be no good string or regex to search for to distinguish your protocol from protocols permitted by censors. Imitate a real profile: There are many ways to implement most protocols -- and in many cases, most possible variants of a given protocol won't actually exist in the wild. Appendix: Raw-traffic transports This section describes an optional extension to the proposal above. [a]I agree that we should remove this section - perhaps we should also save the links and move them to the possible plugin examples? - ioerror [b]This whole section should get removed from the final thing. I tried to summarize broad themes in the Motivations section below. - NM [c]That doesn't really help - does it? Or do you mean that the Tor should set the CN to be say, the IP or hostname of the relay? - ioerror The "Address" field when we have it. After that, the hostname if we know it. After that, do a PTR lookup on our IP. After that, use our IP. -NM