• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..18-Aug-2021-

badproxy/H18-Aug-2021-272225

flagx/H18-Aug-2021-12188

httpproxy/H18-Aug-2021-212167

iptables/H18-Aug-2021-610536

resolver/H18-Aug-2021-305261

tlsproxy/H18-Aug-2021-379315

uncensored/H18-Aug-2021-163130

.gitignoreH A D18-Aug-202114 21

README.mdH A D18-Aug-20219.4 KiB259197

main.goH A D18-Aug-20217.9 KiB288248

main_test.goH A D18-Aug-20211.7 KiB9083

README.md

1# Jafar
2
3> We stepped up the game of simulating censorship upgrading from the
4> evil genius to the evil grand vizier.
5
6Jafar is a censorship simulation tool used for testing OONI. It builds on
7any system but it really on works on Linux.
8
9## Building
10
11We use Go >= 1.16. Jafar also needs the C library headers,
12iptables installed, and root permissions.
13
14With Linux Alpine edge, you can compile Jafar with:
15
16```bash
17apk add go git musl-dev iptables
18go build -v .
19```
20
21Otherwise, using Docker:
22
23```bash
24docker build -t jafar-runner .
25docker run -it --privileged -v`pwd`:/jafar -w/jafar jafar-runner
26go build -v .
27```
28
29## Usage
30
31You need to run Jafar as root. You can get a complete list
32of all flags using `./jafar -help`. Jafar is composed of modules. Each
33module is controllable via flags. We describe modules below.
34
35### main
36
37The main module starts all the other modules. If you don't provide the
38`-main-command <command>` flag, the code will run until interrupted. If
39instead you use the `-main-command` flag, you can specify a command to
40run inside the censored environment. In such case, the main module
41will exit when the specified command terminates. Note that the main
42module will propagate the child exit code, if the child fails.
43
44The command can also include arguments. Make sure you quote the arguments
45such that your shell passes the whole string to the specified option, as
46in `-main-command 'ls -lha'`. This will execute the `ls -lha` command line
47inside the censored Jafar context. You can also combine that with quoting
48and variables interpolation, e.g., `-main-command "echo '$USER is the
49walrus'"`. The `$USER` variable will be expanded by your shell. Assuming
50your user name is `paul`, then Jafar will lex the main command as `echo
51"paul is the walrus"` and will execute it.
52
53Use the `-main-user <username>` flag to select the user to use for
54running child commands. By default, we use the `nobody` user for this
55purpose. We implement this feature using `sudo`, therefore you need
56to make sure that `sudo` is installed.
57
58### iptables
59
60The iptables module is only available on Linux. It exports these flags:
61
62```bash
63  -iptables-drop-ip value
64        Drop traffic to the specified IP address
65  -iptables-drop-keyword-hex value
66        Drop traffic containing the specified hex keyword
67  -iptables-drop-keyword value
68        Drop traffic containing the specified keyword
69  -iptables-hijack-dns-to string
70        Hijack all DNS UDP traffic to the specified endpoint
71  -iptables-hijack-https-to string
72        Hijack all HTTPS traffic to the specified endpoint
73  -iptables-hijack-http-to string
74        Hijack all HTTP traffic to the specified endpoint
75  -iptables-reset-ip value
76        Reset TCP/IP traffic to the specified IP address
77  -iptables-reset-keyword-hex value
78        Reset TCP/IP traffic containing the specified hex keyword
79  -iptables-reset-keyword value
80        Reset TCP/IP traffic containing the specified keyword
81```
82
83The difference between `drop` and `reset` is that in the former case
84a packet is dropped, in the latter case a RST is sent.
85
86The difference between `ip` and `keyword` flags is that the former
87match an outgoing IP, the latter uses DPI.
88
89The `drop` and `reset` rules allow you to simulate, respectively, when
90operations timeout and when a connection cannot be established (with
91`reset` and `ip`) or is reset after a keyword is seen (with `keyword`).
92
93Hijacking DNS traffic is useful, for example, to redirect all DNS UDP
94traffic from the box to the `dns-proxy` module.
95
96Hijacking HTTP and HTTPS traffic actually hijacks based on ports rather
97than on DPI. As a known bug, when hijacking HTTP or HTTPS traffic, we
98do not hijack traffic owned by root. This is because Jafar runs as root
99and therefore its traffic must not match the hijack rule.
100
101When matching keywords, the simplest option is to use ASCII strings as
102in `-iptables-drop-keyword ooni`. However, you can also specify a sequence
103of hex bytes, as in `-iptables-drop-keyword-hex |6f 6f 6e 69|`.
104
105Note that with `-iptables-drop-keyword`, DNS queries containing such
106keyword will fail returning `EPERM`. For a more realistic approach to
107dropping specific DNS packets, combine DNS traffic hijacking with
108`-dns-proxy-ignore`, to "drop" packets at the DNS proxy.
109
110### dns-proxy (aka resolver)
111
112The DNS proxy or resolver allows to manipulate DNS. Unless you use DNS
113hijacking, you will need to configure your application explicitly to use
114the proxy with application specific command line flags.
115
116```bash
117  -dns-proxy-address string
118        Address where the DNS proxy should listen (default "127.0.0.1:53")
119  -dns-proxy-block value
120        Register keyword triggering NXDOMAIN censorship
121  -dns-proxy-hijack value
122        Register keyword triggering redirection to 127.0.0.1
123  -dns-proxy-ignore value
124        Register keyword causing the proxy to ignore the query
125```
126
127The `-dns-proxy-address` flag controls the endpoint where the proxy is
128listening.
129
130The `-dns-proxy-block` tells the resolver that every incoming request whose
131query contains the specifed string shall receive an `NXDOMAIN` reply.
132
133The `-dns-proxy-hijack` is similar but instead lies and returns to the
134client that the requested domain is at `127.0.0.1`. This is an opportunity
135to redirect traffic to the HTTP and TLS proxies.
136
137The `-dns-proxy-ignore` is similar but instead just ignores the query.
138
139### http-proxy
140
141The HTTP proxy is an HTTP proxy that may refuse to forward some
142specific requests. It's controlled by these flags:
143
144```bash
145  -http-proxy-address string
146        Address where the HTTP proxy should listen (default "127.0.0.1:80")
147  -http-proxy-block value
148        Register keyword triggering HTTP 451 censorship
149```
150
151The `-http-proxy-address` flag has the same semantics it has for the DNS
152proxy.
153
154The `-http-proxy-block` flag tells the proxy that it should return a `451`
155response for every request whose `Host` contains the specified string.
156
157### tls-proxy
158
159TLS proxy is a proxy that routes traffic to specific servers depending
160on their SNI value. It is controlled by the following flags:
161
162```bash
163  -tls-proxy-address string
164        Address where the HTTP proxy should listen (default "127.0.0.1:443")
165  -tls-proxy-block value
166        Register keyword triggering TLS censorship
167```
168
169The `-tls-proxy-address` flags has the same semantics it has for the DNS
170proxy.
171
172The `-tls-proxy-block` specifies which string or strings should cause the
173proxy to return an internal-erorr alert when the incoming ClientHello's SNI
174contains one of the strings provided with this option.
175
176### bad-proxy
177
178```bash
179  -bad-proxy-address string
180        Address where to listen for TCP connections (default "127.0.0.1:7117")
181  -bad-proxy-address-tls string
182        Address where to listen for TLS connections (default "127.0.0.1:4114")
183  -bad-proxy-tls-output-ca string
184        File where to write the CA used by the bad proxy (default "badproxy.pem")
185```
186
187The bad proxy is a proxy that reads some bytes from any incoming connection
188and then closes the connection without replying anything. This simulates a
189proxy that is not working properly, hence the name of the module.
190
191When connecting using TLS, the above behaviour happens after the handshake.
192
193We write the CA on the file specified using `-bad-proxy-tls-output-ca` such that
194tools like curl(1) can use such CA to avoid TLS handshake errors. The code will
195generate on the fly a certificate for the provided SNI. Not providing any SNI in
196the client Hello message will cause the TLS handshake to fail.
197
198### uncensored
199
200```bash
201  -uncensored-resolver-url string
202    	URL of an hopefully uncensored resolver (default "dot://1.1.1.1:853")
203```
204
205The HTTP, DNS, and TLS proxies need to resolve domain names. If you setup DNS
206censorship, they may be affected as well. To avoid this issue, we use a different
207resolver for them, which by default is `dot://1.1.1.1:853`. You can change such
208default by using the `-uncensored-resolver-url` command line flag. The input
209URL is `<transport>://<domain>[:<port>][/<path>]`. Here are some examples:
210
211* `system:///` uses the system resolver (i.e. `getaddrinfo`)
212* `udp://8.8.8.8:53` uses DNS over UDP
213* `tcp://8.8.8.8:53` used DNS over TCP
214* `dot://8.8.8.8:853` uses DNS over TLS
215* `https://dns.google/dns-query` uses DNS over HTTPS
216
217So, for example, if you are using Jafar to censor `1.1.1.1:853`, then you
218most likely want to use `-uncensored-resolver-url`.
219
220## Examples
221
222Block `play.google.com` with RST injection, force DNS traffic to use the our
223DNS proxy, and force it to censor `play.google.com` with `NXDOMAIN`.
224
225```bash
226# ./jafar -iptables-reset-keyword play.google.com \
227          -iptables-hijack-dns-to 127.0.0.1:5353  \
228          -dns-proxy-address 127.0.0.1:5353       \
229          -dns-proxy-block play.google.com
230```
231
232Force all traffic through the HTTP and TLS proxy and use them to censor
233`play.google.com` using HTTP 451 and responding with TLS alerts:
234
235```bash
236# ./jafar -iptables-hijack-dns-to 127.0.0.1:5353 \
237          -dns-proxy-address 127.0.0.1:5353      \
238          -dns-proxy-hijack play.google.com      \
239          -http-proxy-block play.google.com      \
240          -tls-proxy-block play.google.com
241```
242
243Run `ping` in a censored environment:
244
245```bash
246# ./jafar -iptables-drop-ip 8.8.8.8 -main-command 'ping -c3 8.8.8.8'
247```
248
249Run `curl` in a censored environment where it cannot connect to
250`play.google.com` using `https`:
251
252```bash
253# ./jafar -iptables-hijack-https-to 127.0.0.1:443         \
254          -tls-proxy-block play.google.com                \
255          -main-command 'curl -Lv http://play.google.com'
256```
257
258For more usage examples, see `../../testjafar.bash`.
259