1 Champa – general-purpose proxy through an AMP cache
2 David Fifield <david@bamsoftware.com>
6 Champa is a pair of programs—champa-client and champa-server—that
7 implements a proxy tunnel over an AMP cache, with the goal of
8 circumventing Internet censorship. It is not limited to tunneling HTTP;
9 it encodes data into HTTP requests that satisfy the requirements of AMP.
11 AMP ("Accelerated Mobile Pages") is a framework for mobile web pages.
12 AMP pages are written in a restricted subset of HTML. An
13 [AMP cache](https://amp.dev/documentation/guides-and-tutorials/learn/amp-caches-and-cors/how_amp_pages_are_cached/)
14 is a cache and proxy for AMP HTML pages: it forwards HTTP requests from
15 a client to an origin server, and relays HTTP responses back to the
16 client, while enforcing the requirement that responses be written in AMP
17 HTML. Champa transforms a specialized AMP cache proxy into a
18 general-purpose proxy.
20 Access through an AMP cache normally exposes the domain name of the
21 origin server in the hostname of the URL by which the cache is accessed.
22 To hide the origin server from an observer, the champa-client supports
23 domain fronting to make it appear to an external observer that you are
24 accessing a different domain. When you run champa-client, you provide
25 both the URL of an AMP cache
27 As of 2021, there is really only one option for an AMP cache,
28 [Google AMP Cache](https://developers.google.com/amp/cache/) at
29 https://cdn.ampproject.org/. When you run champa-client, you will
30 therefore always use the `-cache https://cdn.ampproject.org/` option,
31 along with a `-front` option specifying a Google domain for domain
34 Champa is an application-layer tunnel that runs in userspace. It doesn't
35 provide a TUN/TAP interface; it only connects a local TCP port to a
36 remote TCP port by way of an AMP cache tunnel DNS resolver. It does not
37 itself provide a SOCKS or HTTP proxy interface, but you can get the same
38 effect by running a proxy on the tunnel server and having the tunnel
44 The server end of the tunnel must be run on a publicly accessible
45 server, outside the censor's zone of control. champa-server is a
46 plaintext HTTP server. It is meant to listen on localhost, behind a
47 reverse web proxy that can provide TLS to incoming traffic, such as
50 Compile champa-server:
52 tunnel-server$ cd champa-server
53 tunnel-server$ go build
56 Generate a keypair that will be used for end-to-end confidentiality and
57 integrity with tunnel clients. The server needs to keep a copy of the
58 private key. Each clients needs a copy of the public key.
60 tunnel-server$ ./champa-server -gen-key -privkey-file server.key -pubkey-file server.pub
61 privkey written to server.key
62 pubkey written to server.pub
65 Run champa-server. In this example `127.0.0.1:8080` is the port that the
66 HTTP server will listen on. `127.0.0.1:7001` is the TCP address to which
67 incoming tunneled connection will be forwarded—this can be a proxy
70 tunnel-server$ ./champa-server -privkey-file server.key 127.0.0.1:8080 127.0.0.1:7001
73 Next, you need to configure a reverse web proxy to connect
74 champa-server's HTTP port to the outside world. Below are instructions
75 for how to do this using Apache and Nginx on Debian. The examples assume
76 that you have already installed a web server and configured it to answer
77 requests for the domain example.com. Clients will access the server at
78 the URL `https://example.com/champa/` (through an AMP cache).
81 ### Apache reverse proxy
83 For general information on configuring a reverse proxy with Apache, see
84 https://httpd.apache.org/docs/current/howto/reverse_proxy.html#simple.
86 Configure the server to use TLS, if it does not already. You can do this
89 tunnel-server$ apt install python3-certbot-apache
90 tunnel-server$ certbot
93 Enable the proxy_http Apache module. Although not required, you probably
94 also want to enable the http2 module.
96 tunnel-server$ a2enmod proxy_http http2
99 Find the `<VirtualHost>` directive, and add a new `<Location>` directive
100 with the path prefix you want to reserve for Champa traffic (here,
101 `"/champa/"`). Add `ProxyPass` and `ProxyPassReverse` directives
102 pointing to champa-server's HTTP listening port. You may also want to
103 disable logging for requests under the path prefix.
106 ServerName example.com
107 <Location "/champa/">
108 ProxyPass http://127.0.0.1:8080/
109 ProxyPassReverse http://127.0.0.1:8080/
112 CustomLog ${APACHE_LOG_DIR}/access.log combined env=!nolog
118 tunnel-server$ apache2ctl restart
122 ### Nginx reverse proxy
124 For general information on configuring a reverse proxy with Nginx, see
125 https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/#passing-a-request-to-a-proxied-server.
127 Configure the server to use TLS, if it does not already. You can do this
130 tunnel-server$ apt install python3-certbot-nginx
131 tunnel-server$ certbot
134 Find the `server` directive, and add a new `location` directive with the
135 path prefix you want to reserve for Champa traffic (here, `/champa/`).
136 Add a `proxy_pass` directive pointing to champa-server's HTTP listening
137 port. The trailing slash in the URL after `proxy_pass` is important. You
138 may also want to disable logging for requests under the path prefix. Add
139 `http2` to the `listen` directives, if it is not there already.
142 server_name example.com;
144 proxy_pass http://127.0.0.1:8080/;
145 proxy_redirect default;
148 listen [::]:443 ssl http2 ipv6only=on; # managed by Certbot
149 listen 443 ssl http2; # managed by Certbot
155 tunnel-server$ nginx -s reload
161 Compile champa-client:
163 tunnel-client$ cd champa-client
164 tunnel-client$ go build
167 Copy the server's public key (server.pub) to the client. You don't need
168 the private key (server.key) on the client.
172 tunnel-client$ ./champa-client -pubkey-file server.pub -cache https://cdn.ampproject.org/ -front www.google.com https://example.com/champa/ 127.0.0.1:7000
175 The champa-client command line requires five pieces of information:
176 * `-pubkey-file server.pub`
177 The server's public key.
178 * `-cache https://cdn.ampproject.org/`
179 The URL of the AMP cache to proxy through.
180 * `-front www.google.com`
181 The externally visible domain name to use when connecting to the AMP
182 cache. You can use a Google-operated domain here.
183 * `https://example.com/champa/`
184 The URL of the tunnel server.
186 The local TCP port that will receive connections and forward them
189 In this example, connections to 127.0.0.1:7000 on the tunnel client
190 will be tunneled through the AMP cache at https://cdn.ampproject.org/
191 with www.google.com as a domain front, arriving at the tunnel server at
192 https://example.com/champa/, which will then forward the tunneled
193 connections to its own 127.0.0.1:7001.
196 ## How to make a proxy
198 Champa is only a tunnel: it connects a local TCP port to a remote TCP
199 port in a hard-to-detect way. What you connect to those ports is your
200 choice, but generally it will be some kind of proxy.
205 [Ncat](https://nmap.org/ncat/) has a simple built-in HTTP/HTTPS proxy,
206 good for testing. Be aware that Ncat's proxy isn't intended for use by
207 untrusted clients; it won't prevent them from connecting to localhost
208 ports on the tunnel server, for example.
211 tunnel-server$ ncat -l -k --proxy-type http 127.0.0.1 7001
212 tunnel-server$ ./champa-server -privkey-file server.key 127.0.0.1:8080 127.0.0.1:7001
215 On the client, have the tunnel client listen on 127.0.0.1:7000, and
216 configure your applications to use 127.0.0.1:7000 as an HTTP proxy.
219 tunnel-client$ ./champa-client -pubkey-file server.pub -cache https://cdn.ampproject.org/ -front www.google.com https://example.com/champa/ 127.0.0.1:7000
220 tunnel-client$ curl --proxy http://127.0.0.1:7000/ https://wtfismyip.com/text