forked from rthalley/dnspython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdoh.py
More file actions
65 lines (57 loc) · 2.09 KB
/
doh.py
File metadata and controls
65 lines (57 loc) · 2.09 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
# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
import base64
import functools
import socket
import hypercorn.config
import hypercorn.trio
import quart
import quart_trio
def setup(server, connection_type):
name = f"{__name__}-{connection_type.name}"
app = quart_trio.QuartTrio(name)
app.logger.handlers = []
@app.route("/dns-query", methods=["GET", "POST"])
async def dns_query():
if quart.request.method == "POST":
wire = await quart.request.body
else:
encoded = quart.request.args["dns"]
remainder = len(encoded) % 4
if remainder != 0:
encoded += "=" * (4 - remainder)
wire = base64.urlsafe_b64decode(encoded)
for body in server.handle_wire(
wire,
quart.request.remote_addr,
quart.request.server,
connection_type,
):
if body is not None:
return quart.Response(body, mimetype="application/dns-message")
else:
return quart.Response(status=500)
return app
def make_server(server, sock, connection_type, tls_chain, tls_key):
doh_app = setup(server, connection_type)
hconfig = hypercorn.config.Config()
fd = sock.fileno()
if sock.type == socket.SOCK_STREAM:
# We put http/1.1 in the ALPN as we don't mind, but DoH is
# supposed to be H2 officially.
hconfig.alpn_protocols = ["h2", "http/1.1"]
hconfig.bind = [f"fd://{fd}"]
hconfig.quic_bind = []
else:
hconfig.alpn_protocols = ["h3"]
# We should be able to pass bind=[], but that triggers a bug in
# hypercorn. So, create a dummy socket and bind to it.
tmp_sock = socket.create_server(("127.0.0.1", 0))
hconfig.bind = [f"fd://{tmp_sock.fileno()}"]
tmp_sock.detach()
hconfig.quic_bind = [f"fd://{fd}"]
sock.detach()
hconfig.certfile = tls_chain
hconfig.keyfile = tls_key
hconfig.accesslog = None
hconfig.errorlog = None
return functools.partial(hypercorn.trio.serve, doh_app, hconfig)