wiki:doc/meek

Version 98 (modified by dcf, 5 years ago) (diff)

Link to mainline alpha bundles.

meek is a pluggable transport that uses HTTP for carrying bytes and TLS for obfuscation. Traffic is relayed through a third-party server that is hard to block, for example a CDN. It uses a trick called "domain fronting" to talk to a Tor relay while appearing to talk to another domain.

Quick start

Download a browser bundle for your platform:

Extract and run it, and then configure these settings:

  1. Configure on the first screen.
  2. No to Does this computer need to use a proxy to access the Internet?, unless you know you need to use a proxy.
  3. No to Does this computer's Internet connection go through a firewall that only allows connections to certain ports? meek uses port 443, which is allowed through most firewalls.
  4. Yes to Does your Internet Service Provider (ISP) block or otherwise censor connections to the Tor Network?
  5. Connect with provided bridges and select either meek-amazon or meek-google from the Transport type box. They both work about the same; you can pick either one. If one doesn't work, try the other. Then click Connect.

Tor Browser 7.5.3 settings screen 1 Tor Browser 7.5.3 settings screen 2 7.0.5 settings screen 3 7.0.5 settings screen 4 4.0-alpha-1 settings screen 4.

To build from source:

git clone https://git.torproject.org/pluggable-transports/meek.git
cd meek/meek-client
export GOPATH=~/go
go get
go build
tor -f torrc

FreeBSD port: http://www.freshports.org/security/meek/

Overview

meek uses a technique called "domain fronting" to send a message to a Tor relay in a way that is hard to block. Domain fronting is the use of different domain names at different communication layers. The meek-client program builds a special HTTPS request and sends it to an intermediate web service with many domains behind it, such as a CDN. What's special about the request is that one domain name (the "front domain") appears on the "outside" of the request—in the DNS query and SNI—and a different name appears on the "inside"—in the HTTP Host header. The censor sees the outside name but the CDN sees the inside name, and forwards the request to the meek-server program running on a Tor bridge. meek-server decodes the body of the request and feeds the data into Tor.

Domain fronting and meek work when the censor blocks some domains of a web service but not all of them. Some examples of fronting-capable services are Google, CloudFront, and others. On Google, we communicate with meek-reflect.appspot.com while appearing to communicate with the front domain www.google.com. On CloudFront, we communicate with d2zfqthxsdq309.cloudfront.net while appearing to communicate with the front domain a0.awsstatic.com.

Redrawn diagram, no longer Google-specific.

See A Child's Garden of Pluggable Transports for details of how the protocol looks at the byte level, both at the TLS layer (the part visible to a censor), and at the HTTP layer (the invisible layer that carries the data).

Web services

Here are some web services that support domain fronting.

Google App Engine

$ wget -O - -q https://www.google.com/ --header 'Host: meek-reflect.appspot.com'
I’m just a happy little web server.

Google App Engine is web application hosting on Google's infrastructure. This is the one that has been deployed so far. The front domain can be any Google domain, as far as I can tell, from www.google.com to www.youtube.com to www.orkut.com.

There are quotas for unpaid apps:

You can pay to get higher quotas:

The cost is $0.12 per gigabyte, with 1 gigabyte free each day. There are other potential ancillary costs, having to do with things like how often your app is reloaded.

Amazon CloudFront

$ wget -q -O - https://a0.awsstatic.com/ --header 'Host: d2zfqthxsdq309.cloudfront.net'
I’m just a happy little web server.

CloudFront is a CDN. Your files are hosted on a generated domain name that looks like d2k1ftgv7pobq7.cloudfront.net. All these domains support HTTPS with a wildcard cert for *.cloudfront.net, and they can front for each other.

There is a free tier, good for a year, that limits you to 50 GB per month. Per-request pricing differs by client country. Per-gigabyte costs go down the more you transfer, with a maximum of $0.19 per gigabyte. Bandwidth costs to the origin server (i.e., the Tor bridge) are lower. There's an additional cost of about $0.01 per 10,000 requests.

CloudFront allows you to use your own TLS domain name for an extra charge, but that appears to put you on a certificate with a bunch of shared SANs, which can't front for domains on different certificates.

The FAQ suggests that non-cacheable, dynamic traffic is fine.

  1. Does Amazon CloudFront support delivery of dynamic content?

Amazon CloudFront supports all files that can be served over HTTP. This includes dynamic web pages, such as HTML or PHP pages, any popular static files that are a part of your web application, such as website images, audio streams, video streams, media files or software downloads. For on-demand media files, you can also choose to stream your content using RTMP delivery. Amazon CloudFront also supports delivery of live media over HTTP.

  1. Does Amazon CloudFront cache POST responses?

Amazon CloudFront does not cache the responses to POST, PUT, DELETE, OPTIONS, and PATCH requests – these requests are proxied back to the origin server.

There's a question of what to use as the front domain. Any particular *.cloudfront.net name could be individually blockable. The generic names cloudfront.net and www.cloudfront.net don't resolve. Maybe pick one with a lot of collateral damage? Or a few, and randomly choose between them? Or connect to an IP, rather than a domain (#12208). Alexa has a list of the most popular cloudfront.net domains ("Where do visitors go on cloudfront.net?"), which starts out:

d3dsacqprgcsqh.cloudfront.net 	14.67%
deayhd4nq31b0.cloudfront.net 	6.06%
d396qusza40orc.cloudfront.net 	2.72%
d3v9w2rcr4yc0o.cloudfront.net 	2.26%
d13yacurqjgara.cloudfront.net 	2.09%

There's a list of CNAMES that point to an example cloudfront.net subdomain. It appears that GFW blacklists (through DNS poisoning) *.cloudfront.net, but some names are whitelisted including d3dsacqprgcsqh.cloudfront.net and d1y9yo7q4hy8a7.cloudfront.net (9gag).

The names a0.awsstatic.com, a1.awsstatic.com, and d0.awsstatic.com look promising. I found them in the source of https://aws.amazon.com/documentation/.

wget https://a0.awsstatic.com/favicon.ico --header 'Host: d36cz9buwru1tt.cloudfront.net' # AWS's favicon
wget https://a0.awsstatic.com/favicon.ico --header 'Host: d3dsacqprgcsqh.cloudfront.net' # 9gag's favicon

How to set up a CloudFront reflector

Read http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/GettingStarted.html. Skip step 2, which is about uploading your files to S3 (all our data comes straight from the Tor relay). For Origin Domain Name, enter "meek.bamsoftware.com", or wherever your meek-server lives. Fill out the HTTP port fields with the port that your meek-server listens on. For Allowed HTTP Methods, choose "GET, HEAD, PUT, POST, PATCH, DELETE, OPTIONS". For SSL Certificate select "Default CloudFront Certificate". Set the Viewer Protocol Policy to "HTTPS Only."

Picture of CLoudFront configuration screen.

You will get a domain name like d111111abcdef8.cloudfront.net. Wait about 15 minutes for it to start to resolve. Set up torrc like so:

ClientTransportPlugin meek exec ./meek-client --url=http://d111111abcdef8.cloudfront.net/ --log meek-client.log

You can front with a different *.cloudfront.net domain. For example, in the source code of http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/GettingStarted.html, we see d36cz9buwru1tt.cloudfront.net, so give that as the --front option.

ClientTransportPlugin meek exec ./meek-client --url=http://d111111abcdef8.cloudfront.net/ --front=d36cz9buwru1tt.cloudfront.net --log meek-client.log

CloudFlare

$ wget -O - -q https://cloudflare.com/ --header 'Host: news.ycombinator.com' | grep -io '<title>.*</title>'
<title>Hacker News</title>

CloudFlare is a CDN. You use your own domain name. TLS is terminated at CloudFlare's server.

There are different pricing plans. The cheapest one that supports SSL is Pro, for $20 per month. Business is $200 and Enterprise averages $5,000.

There's no per-gigabyte bandwidth charge. The terms of use suggest that they don't want you using it to serve other than ordinary web sites.

SECTION 10: LIMITATION ON NON-HTML CACHING

You acknowledge that CloudFlare's Service is offered as a platform to cache and serve web pages and websites and is not offered for other purposes, such as remote storage. Accordingly, you understand and agree to use the Service solely for the purpose of hosting and serving web pages as viewed through a web browser or other application and the Hypertext Markup Language (HTML) protocol or other equivalent technology....

Akamai

$ wget --no-check-certificate -q -O - https://a248.e.akamai.net/ --header 'Host: www.nytimes.com' | grep -io '<title>.*</title>'
<title>The New York Times - Breaking News, World News &amp; Multimedia</title>
$ wget --no-check-certificate -q -O - https://a248.e.akamai.net/ --header 'Host: www.reddit.com' | grep -io '<title>.*</title>'
<title>reddit: the front page of the internet</title>
$ wget --no-check-certificate -q -O - https://www.reddit.com/ --header 'Host: www.nytimes.com' | grep -io '<title>.*</title>'
<title>The New York Times - Breaking News, World News &amp; Multimedia</title>
(However this one doesn't work for some reason.)
$ wget --no-check-certificate -q -O - https://www.nytimes.com/ --header 'Host: www.reddit.com' | grep -io '<title>.*</title>'
<title>The New York Times - Breaking News, World News &amp; Multimedia</title>

(I use --no-check-certificate because the certificate isn't trusted by Wget, but it's okay in Firefox.)

Akamai is a CDN.

HTTPS Everywhere rule for akamai.net. I don't know what's so special about the a248.e.akamai.net name. For example, a247 and a249 exist, but the certificate they serve is only good for "*.akamaihd.net", "*.akamaihd-staging.net", and "a248.e.akamai.net".

It might be easier and cheaper to get Akamai through a reseller. For example Liquid Web posts a price list, $100/month for up to 1000 GB. This blog post describes how to use WordPress with the Liquid Web CDN. In that example they use a custom CNAME, cdn.lw.rrfaae.com, which for me has the reverse DNS a1711.g1.akamai.net. I can grab an HTTPS version of the blog while fronting through a248.e.akamai.net:

$ wget --no-check-certificate -q -O - https://a248.e.akamai.net/ --header 'Host: cdn.lw.rrfaae.com' | grep -io '<title>.*</title>'
<title>jgillman&#039;s Liquid Web Update</title>

However, Liquid Web's terms of service prohibit proxy servers:

We do not allow proxy servers of any kind, whether for personal or business use. Files with references to any proxy or likeness thereof are prohibited.

Cache Simple (formerly Distribution Cloud) is another Akamai reseller. Their pricing starts at $50/month for 100 GB. They want you to sign a contract with a confidentiality clause when you sign up.

Rackspace offers Akamai access with SSL support through their Cloud Files service. The domain you get looks like "c186397.ssl.cf1.rackcdn.com", and you can front it through a248.e.akamai.net:

$ wget --no-check-certificate https://a248.e.akamai.net/CloudFiles%20Akamai.pdf --header 'Host: c186397.ssl.cf1.rackcdn.com'

However, the CDN only works for static files hosted through Cloud Files. They don't support the "origin pull" service we need.

HP Cloud uses Akamai. But they have the same problem as Rackspace: it's only static files from HP Cloud Object Storage.

Fastly

Fastly is a CDN, being used by the meek-like transports of Psiphon and Lantern. It apparently requires you to front without a SNI, only an IP, because their frontend server checks the SNI against the Host, and sends a 400 response if they don't match. Both other projects had to fork an HTTPS library to make it possible.

You can get an idea of some of their domains by looking at the certificate for https://global.ssl.fastly.net/. Shared SSL hosting appears to be on subdomains of a.ssl.fastly.net, global.ssl.fastly.net, or hosts.fastly.net.

$ wget https://github.a.ssl.fastly.net/favicon.ico
Resolving github.a.ssl.fastly.net (github.a.ssl.fastly.net)... 23.235.47.196
HTTP request sent, awaiting response... 200 OK
$ wget https://a.ssl.fastly.net/favicon.ico --header 'Host: github.a.ssl.fastly.net'
Resolving a.ssl.fastly.net (a.ssl.fastly.net)... 23.235.40.130
HTTP request sent, awaiting response... 400 Bad Request
$ wget --no-check-certificate https://23.235.40.130/favicon.ico --header 'Host: github.a.ssl.fastly.net'
The certificate's owner does not match hostname ‘23.235.40.130’
HTTP request sent, awaiting response... 200 OK

Pricing is a minimum $50 per month, and $0.12–0.19 per GB for the first 10 TB per month. There's an additional charge per 10,000 requests.

Level 3

Level 3 is a tier-1 network operator and also has a CDN.

VPS.NET is a reseller of the Level 3 CDN (formerly they had a deal with Akamai). Pricing is pay-as-you-go, not per-month; in other words we can buy a TB and not pay more until it's used up. The first TB is $35 and after that it's $250.

CloudVPS is another reseller. There's no extra charge over the normal VPS fee, but they say:

"The maximum free throughput of the CDN is 100 Megabit per second (Mbit/sec). Traffic above 100 Mbit/sec will be billed at our normal traffic pricing. Contact us if you plan to use the CDN for large amounts of traffic." "The free CloudVPS CDN cannot be used for SSL delivery. Contact us if you want to speed up SSL traffic using the CDN."

It's not clear yet whether fronting works. I found some customer domains from http://trends.builtwith.com/websitelist/Level3-CDN, but I couldn't make them work.

Level 3 is suspected of collaborating with the NSA, so there's that.

Microsoft Azure

Azure is a cloud computing platform with a CDN.

Pricing is $0.12 to $0.19 per GB (depending on geographical region), getting less for higher volumes.

Their wildcard HTTPS domain seems to be *.vo.msecnd.net. ajax.aspnetcdn.com might be a good front. I've also seen azurecomcdn.net. HTTPS Everywhere rules for msecnd.net. All these fronting commands work:

wget https://az29590.vo.msecnd.net/img/rewardsSprite.png
wget --no-check-certificate https://cs1.wpc.v0cdn.net/img/rewardsSprite.png --header 'Host: az29590.vo.msecnd.net'
wget https://blahblahblah.vo.msecnd.net/img/rewardsSprite.png --header 'Host: az29590.vo.msecnd.net'
wget --no-check-certificate https://cdn.astonmartin.com/img/rewardsSprite.png --header 'Host: az29590.vo.msecnd.net'
wget https://ajax.aspnetcdn.com/img/rewardsSprite.png --header 'Host: az29590.vo.msecnd.net'

Additionally I found http://umacau-datacenter.com:4998/enothers-msn/20131110/az29590.vo.msecnd.net/img/rewardsSprite.png.

http://www.hanselman.com/blog/PennyPinchingVideoMovingMyWebsitesImagesToTheAzureCDNAndUsingACustomDomain.aspx

Microsoft is accepting research proposals. If the proposal is accepted, you get access to Azure including the CDN for a year.

There's also a 1-month trial.

Using nginx instead of Google App Engine/PHP/etc

Any web server that serves a site over https using nginx can act as a reflector just by editing the config.

Requirements:

  • A web server running a sufficiently recent version of nginx serving a site over SSL/TLS.
  • A valid certificate signed by a "real" CA. Currently meek-client does not have a way to accept self-signed certificates or easily add CA certs to the trusted list.

Config:

   # The configuration for the normal HTTPS server
   server {
           # Set default_server so that real content gets served by default
   #       listen 443 default_server;
           listen [::]:443 default_server;
           server_name www.example.com;

           # Boilerplate for SSL, adjust as appropriate.
           ssl on;
           ssl_certificate /etc/ssl/nginx/example.com.crt;
           ssl_certificate_key /etc/ssl/nginx/example.com.key;
           ssl_session_timeout 5m;
           ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
           ssl_ciphers !RC4:HIGH:!MD5:!aNULL:!DH;
           ssl_prefer_server_ciphers on;

           # Blah blah blah, normal site specific config
           root /usr/share/nginx/www;
           index index.html index.htm;
           location / {
                   index index.html;
           }
   }

   # Configuration for the reflector
   server {
   #       listen 443;
           listen [::]:443;

           # This does not need to be a real name, but it MUST be distinct from
           # the host used for real content.
           server_name meek-reflect.example.com;

           # Boilerplate for SSL/TLS (copy/paste from the other server block)
           ssl on;
           ssl_certificate /etc/ssl/nginx/example.com.crt;
           ssl_certificate_key /etc/ssl/nginx/example.com.key;
           ssl_session_timeout 5m;
           ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
           ssl_ciphers !RC4:HIGH:!MD5:!aNULL:!DH;
           ssl_prefer_server_ciphers on;

           # This is where the magic happens
           location / {
                   # Proxy traffic all traffic received with the meek Host to
                   # a meek-server instance.
                   proxy_pass http://meek.bamsoftware.com:7002;

                   # Disable logging for the reflector.
                   access_log off;
                   error_log /dev/null;
           }
   }

ClientTransportPlugin Line:

ClientTransportPlugin meek exec ./meek-client \
  --url=https://meek-reflect.example.com \
  --front=www.example.com \
  --log meek-client.log

Ideas

An idea to reduce overhead and eliminate polling is to use HTTP as a long-lived bidirectional channel, sending upstream data in a POST body and receiving data in the response body simultaneously. (That is, you send a POST with no Content-Length, the server reads your header and forwards the request to the relay, the server writes back a header, and after that you use the connection as an ordinary socket, with upstream and downstream data interleaved.) An implementation of this idea is at https://www.bamsoftware.com/git/meeker.git. The idea doesn't work with App Engine, for two reasons. 1) requests must be handled within 60 seconds, and 2) App Engine doesn't support streaming requests of this kind:

"App Engine calls the handler with a Request and a ResponseWriter, then waits for the handler to write to the ResponseWriter and return. When the handler returns, the data in the ResponseWriter's internal buffer is sent to the user. This is practically the same as when writing normal Go programs that use the http package. The one notable difference is that App Engine does not support streaming data in response to a single request."

App Engine doesn't even call your web app code until it has consumed the entire request body, and doesn't start flushing the response body until you close the output stream.

Instead of sending TLS with a front SNI, think about sending TLS with no SNI at all. (It might look like a really old browser or a non-browser daemon or something.) Then the censor doesn't have an SNI to match on, and has the choice of blocking an entire IP address (which may virtually host many domains) instead of a single SNI. This idea could be useful in deployment with a CDN, which though it may have thousands of domains, is blockable if we choose just one of those domains as a front. See #12208.

The App Engine Channel API provides a way to have long-lived push connections to the client, subject to a restricted interface. (HTTP handlers are otherwise required to finish within 60 seconds.) The client could use HTTP request bodies to send data, and a channel to receive, and remove the need for polling. It would require us to reimplement the client JavaScript channel API in order to make use of the particular Comet-based protocol.

Paid apps can create outbound sockets. I don't think it helps us because then the web app would be responsible for managing the session id mapping.

GoAgent is similar in that it also uses App Engine as a middleman.

GTor a.k.a. CloudEntry is based on GoAgent and uses App Engine. It uses App Engine's socket support to make two outgoing connections from App Engine: one to the relay and one back to the client. For that reason, the client can't be behind NAT (just like with flash proxy). The sockets can't live longer than 60 seconds because of App Engine limits, so after that your connection is broken and you have to start again. GTor works as an upstream HTTPProxy for Tor.

Flashlight from Lantern uses the Host header trick with CloudFlare. Like GoAgent, it uses local MITM for HTTPS connections and makes the actual HTTP requests from the remote server.

Users

https://metrics.torproject.org/userstats-bridge-transport.png
Link.

Distinguishability

Barriers to indistinguishability

  1. TLS ciphersuites
    Look like a browser. #4744 has the story of when tor changed its ciphersuite list to look like Firefox's in 2012. tor's list of ciphers is in src/common/ciphers.inc.
  2. TLS extensions
    Look like a browser.
  3. Packet lengths
    Do something to break up fixed-length cells.
  4. Interpacket times
  5. Upstream/downstream bandwidth ratio
  6. Polling interval
    When we have nothing to send, we start polling at 100 ms, and increase the interval by 50% every time no data is received, up to a maximum of 5 s. The growth pattern and the fixed cap is detectable.
    Here's what the fixed polling of 5 s looks like in the GNOME system monitor:
    Screenshot of the GNOME system monitor showing the 5 s polling interval of meek 0.1.
  7. Maximum payload lengths
    Payloads are limited to 65536 bytes. During bootstrapping and bulk downloads, a lot of bodies have exactly this size.
  8. Behavior on random drops
    Suppose the censor drops every hundredth connection to https://www.google.com/. Normal web users will just refresh; meek's stream will be broken.
  9. Number of simultaneous requests
    Browsers open many parallel connections to the same server; I think meek 0.4 opens just one.
  10. Extra latency
    The latency between the client and the front domain is likely to be measurably different from the latency between the client and the real destination.

Working in our advantage is that we are likely to be transporting web traffic, so we inherit some of its traffic characteristics.

How to look like browser HTTPS

We decided to use a browser extension to make all the HTTPS requests required by meek, so that the requests look just like those made by a browser. There's an extension for Firefox (which works with Tor Browser, so it can work in the browser bundle without shipping a second browser) and one for Chrome. The list below is a summary of a discussion that took place on the tor-dev mailing list and on IRC.

  1. Use your own HTTPS/TLS library, and take care to make sure your ciphersuites and extensions match those of a browser. There are Python bindings for NSS that might make it easier. Chromium is moving to OpenSSL in the future.
  2. Use a separate (headless) browser as an instrument for making HTTPS requests. This is what htpt plans to do.
    PhantomJS is a headless WebKit that is scriptable with JavaScript. Its compressed size is 7–13 MB. This postserver.js example shows it running its own web server, which we could use as a means of communication:

meek-client on localhost ←HTTP→ PhantomJS on localhost ←HTTPS→ www.google.com.

MozRepl (addons.mozilla.org) gives you a JavaScript REPL that allows you to control the browser. It looks like the in-browser JavaScript console, except accessible from outside. Firefox Puppeteer is a fork of MozRepl that is designed for machine-driven browser interaction. Another option is to write an extension for some other browser and communicate with it using some custom IPC.

  1. Use an extension in Tor Browser itself. The plugin bypasses Tor Browser's normal proxy settings in order to issue HTTPS requests directly to the front domain. GeKo says that nsISocketTransportService is what we want to look at. XPCOM is the Firefox API that includes the nsi* functions.
    #11183 is the progress of a browser extension.

Sample client hellos

A big list of client hellos from different applications was moved to meek/SampleClientHellos.

Here is a diff of the client hellos of Firefox 24.4.0 and Tor Browser with meek-http-helper, a browser extension that proxies the requests of meek-client. The only difference is in the client randomness.

--- firefox     2014-04-11 22:10:31.746597046 -0700
+++ meek-http-helper    2014-04-11 22:10:09.303527133 -0700
@@ -1,88 +1,88 @@
 Secure Sockets Layer
     SSL Record Layer: Handshake Protocol: Client Hello
         Content Type: Handshake (22)
         Version: TLS 1.0 (0x0301)
         Length: 169
         Handshake Protocol: Client Hello
             Handshake Type: Client Hello (1)
             Length: 165
             Version: TLS 1.0 (0x0301)
             Random
-                gmt_unix_time: Jul 12, 2089 08:23:06.000000000 PDT
-                random_bytes: f0b149a04ac4a554c5bda57030b17342cc1c0ab59c925cc8...
+                gmt_unix_time: Oct 23, 2081 13:09:42.000000000 PDT
+                random_bytes: 1608e4e50bbc5fb188ab87211ce29f35622d117a4829ebb2...
             Session ID Length: 0
             Cipher Suites Length: 70
             Cipher Suites (35 suites)
                 Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
                 Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
                 Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
                 Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
                 Cipher Suite: TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA (0xc008)
                 Cipher Suite: TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (0xc012)
                 Cipher Suite: TLS_ECDHE_ECDSA_WITH_RC4_128_SHA (0xc007)
                 Cipher Suite: TLS_ECDHE_RSA_WITH_RC4_128_SHA (0xc011)
                 Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033)
                 Cipher Suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA (0x0032)
                 Cipher Suite: TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (0x0045)
                 Cipher Suite: TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA (0x0044)
                 Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039)
                 Cipher Suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA (0x0038)
                 Cipher Suite: TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (0x0088)
                 Cipher Suite: TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA (0x0087)
                 Cipher Suite: TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (0x0016)
                 Cipher Suite: TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA (0x0013)
                 Cipher Suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA (0xc004)
                 Cipher Suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA (0xc00e)
                 Cipher Suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA (0xc005)
                 Cipher Suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA (0xc00f)
                 Cipher Suite: TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA (0xc003)
                 Cipher Suite: TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA (0xc00d)
                 Cipher Suite: TLS_ECDH_ECDSA_WITH_RC4_128_SHA (0xc002)
                 Cipher Suite: TLS_ECDH_RSA_WITH_RC4_128_SHA (0xc00c)
                 Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
                 Cipher Suite: TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (0x0041)
                 Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
                 Cipher Suite: TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (0x0084)
                 Cipher Suite: TLS_RSA_WITH_SEED_CBC_SHA (0x0096)
                 Cipher Suite: SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA (0xfeff)
                 Cipher Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a)
                 Cipher Suite: TLS_RSA_WITH_RC4_128_SHA (0x0005)
                 Cipher Suite: TLS_RSA_WITH_RC4_128_MD5 (0x0004)
             Compression Methods Length: 1
             Compression Methods (1 method)
                 Compression Method: null (0)
             Extensions Length: 54
             Extension: server_name
                 Type: server_name (0x0000)
                 Length: 19
                 Server Name Indication extension
                     Server Name list length: 17
                     Server Name Type: host_name (0)
                     Server Name length: 14
                     Server Name: www.google.com
             Extension: renegotiation_info
                 Type: renegotiation_info (0xff01)
                 Length: 1
                 Renegotiation Info extension
                     Renegotiation info extension length: 0
             Extension: elliptic_curves
                 Type: elliptic_curves (0x000a)
                 Length: 8
                 Elliptic Curves Length: 6
                 Elliptic curves (3 curves)
                     Elliptic curve: secp256r1 (0x0017)
                     Elliptic curve: secp384r1 (0x0018)
                     Elliptic curve: secp521r1 (0x0019)
             Extension: ec_point_formats
                 Type: ec_point_formats (0x000b)
                 Length: 2
                 EC point formats Length: 1
                 Elliptic curves point formats (1)
                     EC point format: uncompressed (0)
             Extension: SessionTicket TLS
                 Type: SessionTicket TLS (0x0023)
                 Length: 0
                 Data (0 bytes)
             Extension: next_protocol_negotiation
                 Type: next_protocol_negotiation (0x3374)
                 Length: 0

Style guide

The word "meek" should be written in lower case, even when it is the first word in a sentence. Exception: when it is the last word in a sentence, it should be in ALL CAPS. When printed on glossy paper, the word should be followed by a ™ symbol; when handwritten, decisively underlined. Exception to everything: if it is the nth appearance of "meek" in a document, and n is the description number of a non-halting Turing machine, then write "𝕸𝕰𝕰𝕶" in honor of Alan Turing and/or Sublime.

Tickets

#10935
Make bundles featuring meek
#10984
PHP relay for meek
#11183
Make an HTTP requestor Firefox extension for meek-client
#11184
Create meek repo
#11393
Make an HTTP requestor Chrome extension for meek-client
#11490
Include meek in userstats-bridge-transport
#12776
Move meek's URL and front configuration into bridge_prefs.js
#13106
Upgrade meek to 0.11
#13247
meek profile error after browser restarts (e.g., after update or add-on installation)
#13586
Use security.ssl.disable_session_identifiers pref in meek-http-helper to restore TLS session tickets
#14033
Upgrade meek to 0.15
#15428
Upgrade meek to 0.16
#15606
Upgrade meek to 0.17
#15872
Meek doesn't start in Tor Browser 4.5 on Windows 7
#15902
Upgrade meek to 0.18
#16014
Windows: staged update fails if Meek is enabled
#16281
Updating to 4.5.1 sets DisableNetwork
#16634
Use new CDN endpoint for meek-azure
#16662
Enable network.http.spdy.* prefs in meek-http-helper for a matching TLS fingerprint
#17330
Figure out what happens when a user's chosen transport is removed from bridge_prefs.js in an update
#17473
Update the meek-amazon fingerprint to B9E7141C594AF25699E0079C1F0146F409495296
#17476
Error console complaining it can't find meek helper
#18517
meek is broken in Tor Browser 6.0a3
#19646
Mac OS: wrong location for meek browser profile
#19732
"Tor circuit for this site" labels meek bridge as being in China
#20250
meek fails on macOS 10.12 when built with Go 1.4.3 or Go 1.6.3
#20290
Upgrade meek to 0.24
#20495
Unexplained drop in meek users, 2016-10-19 to 2016-11-10
#20781
Figure out how to sandbox meek in a sensible way.
#21342
Move meek-azure to the meek.azureedge.net backend and cymrubridge02 bridge.
#21732
Stop the Meek Tor Browser opening links or documents on macOS
#21918
Move meek-amazon to the d2cly7j4zqgua7.cloudfront.net backend
#22949
Add some IP-HOST pair for meek use
#24614
update to a newer Meek tag
#25529
Tor not reading torrc-defaults when started from command line, while it reads it successfully when started from Tor Browser
#26098
remove meek-amazon from the Tor Browser
#26891
Problem running meek server without CDN, stuck at Performing bandwidth self-test...done
#27723
Obfs4 stopped working 16 Sept 18
#29349
Remove obsolete prefs from meek-http-helper-user.js
#29430
Use uTLS for meek TLS camouflage in Tor Browser
#29611
Work around lack of app.update.enabled pref in Firefox 63+
#31464
meek and moat are broken on macOS 10.9 with the switch to Go 1.12
#31491
clean up the old meek http helper browser profiles

#18167
Don't trust "bridge-ips" blindly for user number estimates
#18585
Cannot specify custom meek bridges
#18611
Improve semantics for pluggable transports with dummy addresses
#19487
Meek and ReachableAddresses
#31149
Tor is stuck at "Loading Network Status"

Attachments (20)

Download all attachments as: .zip