v0.38.0 Latest Latest

This package is not in the latest version of its module.

Go to latest
Published: Oct 28, 2022 License: CC0-1.0 Imports: 27 Imported by: 0



meek-client is the client transport plugin for the meek pluggable transport.

Sample usage in torrc:

Bridge meek url=https://forbidden.example/ front=allowed.example
ClientTransportPlugin meek exec ./meek-client

The transport ignores the bridge address and instead connects to the URL given by url=. When front= is given, the domain in the URL is replaced by the front domain for the purpose of the DNS lookup, TCP connection, and TLS SNI, but the HTTP Host header in the request will be the one in url=.

Most user configuration can happen either through SOCKS args (i.e., args on a Bridge line) or through command line options. SOCKS args take precedence per-connection over command line options. For example, this configuration using SOCKS args:

Bridge meek url=https://forbidden.example/ front=allowed.example
ClientTransportPlugin meek exec ./meek-client

is the same as this one using command line options:

Bridge meek
ClientTransportPlugin meek exec ./meek-client --url=https://forbidden.example/ --front=allowed.example

The command-line configuration interface is for compatibility with tor 0.2.4 and older, which doesn't support parameters on Bridge lines.

The --helper option prevents this program from doing any network operations itself. Rather, it will send all requests through a browser extension that makes HTTP requests.

Support code for TLS camouflage using uTLS.

The goal is: provide an http.RoundTripper abstraction that retains the features of http.Transport (e.g., persistent connections and HTTP/2 support), while making TLS connections using uTLS in place of crypto/tls. The challenge is: while http.Transport provides a DialTLS hook, setting it to non-nil disables automatic HTTP/2 support in the client. Most of the uTLS fingerprints contain an ALPN extension containing "h2"; i.e., they declare support for HTTP/2. If the server also supports HTTP/2, then uTLS may negotiate an HTTP/2 connection without the http.Transport knowing it, which leads to an HTTP/1.1 client speaking to an HTTP/2 server, a protocol error.

The code here uses an idea adapted from meek_lite in obfs4proxy: Instead of setting DialTLS on an http.Transport and exposing it directly, we expose a wrapper type, UTLSRoundTripper, that contains within it either an http.Transport or an http2.Transport. The first time a caller calls RoundTrip on the wrapper, we initiate a uTLS connection (bootstrapConn), then peek at the ALPN-negotiated protocol: if "h2", create an internal http2.Transport; otherwise, create an internal http.Transport. In either case, set DialTLS on the created Transport to a function that dials using uTLS. As a special case, the first time the DialTLS callback is called, it reuses bootstrapConn (the one made to peek at the ALPN), rather than make a new connection.

Subsequent calls to RoundTripper on the wrapper just pass the requests though the previously created http.Transport or http2.Transport. We assume that in future RoundTrips, the ALPN-negotiated protocol will remain the same as it was in the initial RoundTrip. At this point it is the http.Transport or http2.Transport calling DialTLS, not us, so we can't dynamically swap the underlying transport based on the ALPN.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL