-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.html
More file actions
265 lines (243 loc) · 15.5 KB
/
Copy pathindex.html
File metadata and controls
265 lines (243 loc) · 15.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=.85">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<link rel="icon" href="/favicon.ico" type="image/x-icon">
<title>DoHProxy.com | DoH Proxy & Anonymizer</title>
<style>body{margin:40px auto;max-width:900px;line-height:1.6;font-size:18px;color:#444;padding:0 10px;background-color:#eee;font-family: 'Roboto', sans-serif;}h1,h2,h3{line-height:1.2;color:black;margin-bottom:0}pre{font-size:smaller;background-color:#ccc;padding:5px;overflow:scroll}code{font-size:smaller}</style>
<meta name="Description" content="A DNS-over-HTTPS anonymous proxy and traffic tumbler -- keep your DNS queries away from prying eyes!">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Roboto&display=swap" rel="stylesheet">
</head>
<body>
<header>
<h1>DoHProxy.com</h1>
<p>This site proxies your DNS-over-HTTPS (DoH) lookups. <del>Use it by setting your DoH client to use <code>https://DoHProxy.com/dns-query</code></del>.</p>
<p><del>DNS traffic is currently resolving via:</del></p>
<ul>
<li><del>https://dns.google</del></li>
<li><del>https://cloudflare-dns.com</del></li>
<li><del>https://doh.opendns.com</del></li>
<li><del>https://doh.42l.fr</del></li>
</ul>
<h3>Due to unexpectedly excessive load, DoHProxy will stop proxying DOH traffic on December 15, 2019. Please, though, use this guide to set up your own proxy!</h3>
</header>
<main>
<h2>What?</h2>
<p><a href="https://en.wikipedia.org/wiki/DNS_over_HTTPS">DNS-over-HTTPS</a> is a protocol for making DNS requests (which are not encrypted) via HTTPS (which is encrypted), keeping your DNS lookups from the prying eyes of your ISP.</p>
<p>However, while your queries are safe from your ISP, it's still possible for DoH providers to keep track of who's looking up what domains -- no matter how vehement they are about privacy, I'd rather have control in my own hands. This proxy setup sends requests to a round-robin-selected list of providers, effectively masking your traffic from any single provider and providing tumbling with other users' data.</p>
<h2>Why should I trust you to run this?</h2>
<p>You shouldn't, so don't. Keep reading and go set your own up!</p>
<h1>Setting up a DoH Proxy</h1>
<h2>In Brief</h2>
<ul>
<li>
Procure and harden a VPS.
</li>
<li>
Point a domain at the VPS.
</li>
<li>
Install nginx and an SSL certificate.
</li>
<li>
Run the nginx config below.
</li>
<li>
???
</li>
<li>
<del>Profit</del> Give back to the community and foster a free and open internet
</li>
</ul>
<h2>Server Configuration</h2>
<p>You'll need a lightweight server to get this set up on. This page runs on a tiny <a href="https://lightsail.aws.amazon.com">AWS Lightsail</a> instance; I find it's a nice balance between control (you can configure load balancers, static IPs, etc.) and ease of use, but any server you can get root on will do (these instructions are oriented towards Ubuntu 18.04 but are fairly portable). If you go the Lightsail route, you'll need to <a href="https://lightsail.aws.amazon.com/ls/docs/en_us/articles/how-to-create-amazon-lightsail-instance-virtual-private-server-vps">provision an instance</a> and then <a href="https://lightsail.aws.amazon.com/ls/docs/en_us/articles/lightsail-create-static-ip">attach a static IP to it</a>.</p>
<p>
Hardening is a Good Thing™; at the least, disable root and password SSH login. There are plenty of hardening guides on the web so give it a Google. Set your firewall up for the holy trinity of 80/443/22. Update your packages. You know the drill.
</p>
<h2>Domain & SSL Setup</h2>
<p>
You'll need a domain pointing at your box; my registrar of choice <a href="https://www.hover.com/">Hover</a>. Update the domain's DNS records and set the A/AAA record to your server's static IP address.
</p>
<p>
We'll be using nginx and <a href="https://letsencrypt.org/">Let's Encrypt</a> via <a href="https://certbot.eff.org/">Certbot</a>, the EFF's easy tool to automate SSL certificate generation and renewal. I've duplicated the <a href="https://certbot.eff.org/lets-encrypt/ubuntubionic-nginx">instructions for nginx on Ubuntu 18.04</a> below:
</p>
<pre><code class="bash">sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot python-certbot-nginx
sudo certbot certonly --nginx # actual cert generation</code></pre>
<p>
Take note of the location of the certificate chain and the key; we'll need those for our nginx setup. You may also bump into issues if nginx is already listening; if certbot complains just stop the nginx service and bring it back up afterwards (<code>sudo service nginx stop</code>).
</p>
<p>
Once the certificate is generated, it's good practice to test the renewal with <code>sudo certbot renew --dry-run</code>. Note that depending on your OS, you may need to manually set up a scheduled task to automate renewal; check the instructions for your setup on the <a href="https://certbot.eff.org/instructions">Certbot instructions page</a>.
</p>
<h2>Nginx Configuration</h2>
<h3>Diffie-Helman Prime Generation</h3>
<p>We want a bullet-proof SSL setup, so get started by generating <a href="https://security.stackexchange.com/questions/94390/whats-the-purpose-of-dh-parameters">fresh Diffie-Helman primes</a>:</p>
<pre><code class="bash">sudo openssl dhparam -out /etc/nginx/dhparam.pem 4096</code></pre>
<p>This will take a while (the lowest grade lightsail instance takes nearly an hour); open a second SSH session and let's keep going.</p>
<h3>Static Site</h3>
<p>
Optionally, create a folder to serve a static page so that your proxy has a web presence (just like this one). Feel free to use the content and styling of this page as a reference (<a href="https://github.com/jkingsman/DoHProxy">see git repo</a>); it's generally drawn from <a href="http://bettermotherfuckingwebsite.com/">Better Motherfucking Website</a> and is a single page with just a few lines of styling (this page is licensed under <a href="http://www.wtfpl.net/faq/">WTFPL</a>).
</p>
<pre>
<code class="bash">sudo mkdir /srv/proxy_static
sudo vim /srv/proxy_static/index.html # set the page contents
sudo chmod 644 /srv/proxy_static/index.html</code></pre>
<h3>Base Server Configuration</h3>
<p>We'll replace the default configuration nginx ships with (<code>/etc/nginx/sites-enabled/default</code>). Open that file, empty it, and dump the following config in. There are inline comments, and we'll break it down in more detail below (find a raw copy at <a href="https://raw.githubusercontent.com/jkingsman/DoHProxy/master/default.conf">this site's git repo</a>).</p>
<pre><code>##
# Individual DoH server entries, one server per resolver.
# These establish proxy ports that the upstream resolvers
# can be reached via.
##
server {
listen 8001 default_server;
server_name _;
location / {
proxy_pass https://dns.google;
add_header X-Resolved-By $upstream_addr always; # optional debugging header
}
}
server {
listen 8002 default_server;
server_name _;
location / {
proxy_pass https://cloudflare-dns.com;
add_header X-Resolved-By $upstream_addr always; # optional debugging header
}
}
server {
listen 8003 default_server;
server_name _;
location / {
proxy_pass https://doh.opendns.com;
add_header X-Resolved-By $upstream_addr always; # optional debugging header
}
}
server {
listen 8004 default_server;
server_name _;
location / {
proxy_pass https://doh.42l.fr/dns-query;
add_header X-Resolved-By $upstream_addr always; # optional debugging header
}
}
##
# Aggregate our resolver proxies into a single upstream
##
upstream dohproviders {
server 127.0.0.1:8001;
server 127.0.0.1:8002;
server 127.0.0.1:8003;
server 127.0.0.1:8004;
}
server {
listen [::]:443 ssl http2 ipv6only=on;
listen 443 ssl http2;
server_name _;
root /srv/proxy_static; # Changeme: if you put your static site root elsewhere, change that here
##
# SSL Configuration
# Changme: you'll need to change these to reflect your actual cert and key location
##
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# not all of these are compatible with all nginx versions
# sourced from https://cipherli.st/
ssl_protocols TLSv1.3 TLSv1.2; # Requires nginx >= 1.13.0 else use TLSv1.2
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/dhparam.pem;
ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0
ssl_session_timeout 10m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off; # Requires nginx >= 1.5.9
ssl_stapling on; # Requires nginx >= 1.3.7
ssl_stapling_verify on; # Requires nginx => 1.3.7
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
##
# Actual DNS endpoint
##
location /dns-query {
proxy_pass http://dohproviders;
}
##
# Secondary ".well-known" endpoint
##
location /.well-known/dns-query {
rewrite ^/\.well-known/(.*) /$1 break;
proxy_pass http://dohproviders;
}
##
# Default greeting page for web browsers
##
location / {
index index.html;
}
}
##
# HTTP => HTTPS redirect
##
server {
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
}</code></pre>
<p>Whew, that's a big chunk of config. Let's break this down step by step.</p>
<p>First, we set up a server for each DoH resolver we're going to route to and set them to listen on a unique port. Essentially, these are proxied portals to those providers. When adding new resolvers, you'll need a new server block for each one. As an added advantage, this allows you to do per-server request rewriting if they don't respond on the semi-standard <code>/dns-query</code>. These port 800x endpoints are not publically accessible; they're purely for our own internal routing. I also added a <code>X-Resolved-By</code> header to indicate what resolver actually responded when debugging. It's completely optional and can be removed.</p>
<p>The <code>upstream</code> block aggregates these endpoints into a single traffic-ready block. As specified, it will route traffic in a round-robin fashion to each resolver/server in turn. Nginx has <a href="http://nginx.org/en/docs/http/ngx_http_upstream_module.html">documentation on the <code>upstream</code> module</a> that allows for all kinds of interesting options such as weighting, connection-count limiting, and other options that may be of interest if you're routing to smaller resolvers or want to shape your traffic at all.</p>
<p>Finally, we put it all together in our hefty public-facing server block. Make sure you change your <code>ssl_certificate</code> and <code>ssl_certificate_key</code> locations to reflect your key location. The sizable chunk of SSL options are mostly sourced from <a href="https://cipherli.st/">Cipherli.st</a> and are modern best-practices SSL settings (you'll even get an A+ from <a href="https://www.ssllabs.com/ssltest">SSL Labs' test</a>!).</p>
<p>The actual <code>/dns-query</code> endpoint routes to our upstream provider collection set up above; I also add a <code>.well-known/</code> endpoint to mirror Cloudflare and because <a href="https://tools.ietf.org/html/rfc8615">RFC 8615</a> is cool. Then there's the static page if you have one as well as an HTTP => HTTPS redirect. Make sure you modify the <code>root</code> directive to point to your static files folder if it's not in <code>/srv/proxy_static</code>.</p>
<p>You can double check you've made all necessary changes by grepping for <code>Changeme</code>; there's a marker each place you will or might need to make modifications before going live.</p>
<p>Finally, check your configuration and bring the new config up:</p>
<pre><code class="bash">sudo nginx -t # run a configuration sanity check
sudo nginx -s reload # send a reload signal to nginx
</code></pre>
<h2>Adding Servers</h2>
<p>
When adding new DNS servers, you'll need to create a server block for it:
</p>
<pre><code class="nginx">server {
listen 8001 default_server; # make sure ports are unique
server_name _;
location / {
proxy_pass https://your-resolver-url.com;
add_header X-Resolved-By $upstream_addr always;
}
}</code></pre>
<p>And make sure you update your <code>upstream</code> block with the new address (e.g. <code>server 127.0.0.1:8001;</code>).</p>
<h2>Testing & Final Words</h2>
<p>For testing, I'd highly recommend Daniel Stenberg's fantastic <a href="https://github.com/curl/doh">doh</a> tool. It compiles nearly dependency-free out of the box (just clone and <code>make</code>; you may need to <code>sudo apt-get install libcurl4 libcurl4-openssl-dev -y</code>) and provides easy testing (just run <code>./doh www.example.com https://yourdomain.com/dns-query</code>).</p>
<p>
In the spirit of anonymization, I'd suggest disabling access logging in nginx which can be disabled by commenting out this line in <code>/etc/nginx/nginx.conf</code>:
</p>
<pre><code class="nginx">access_log /var/log/nginx/access.log;</code></pre>
<p>
Curl maintains a <a href="https://github.com/curl/curl/wiki/DNS-over-HTTPS#publicly-available-servers">list of publicly available DoH resolvers; that's a great place to start populating your upstream resolvers</a>. Note that not all resolvers on this are still live or compatible with this setup; make sure to test before you throw them in your config.
</p>
<h2>Next Steps</h2>
I'm currently looking into options for running this as a standalone script free of Nginx, or possibly via beefier AWS tools. This documentation and site contents are open-source on <a href="https://github.com/jkingsman/DoHProxy">GitHub</a>; feel free to offer improvements or bring up issues there.
<p>Here's to a free and open internet!</p>
<hr />
</main>
<footer>
This site is run by <a href="https://jacksbrain.com/">Jack Kingsman</a>, a software engineer in San Francisco.
</footer>
<link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/styles/googlecode.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/styles/googlecode.min.css">
</noscript>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>