def on_answer(self, request, dnsr=None, dnsq=None): headers = CIMultiDict() if dnsr is None: dnsr = dns.message.make_response(dnsq) dnsr.set_rcode(dns.rcode.SERVFAIL) elif len(dnsr.answer): ttl = min(r.ttl for r in dnsr.answer) headers["cache-control"] = "max-age={}".format(ttl) clientip = utils.get_client_ip(request.transport) interval = int((time.time() - self.time_stamp) * 1000) self.logger.info("[HTTPS] {} (Original IP: {}) {} {}ms".format( clientip, request.remote, utils.dnsans2log(dnsr), interval)) if request.method == "HEAD": body = b"" else: body = dnsr.to_wire() return aiohttp.web.Response( status=200, body=body, content_type=constants.DOH_MEDIA_TYPE, headers=headers, )
async def doh1handler(request): path, params = utils.extract_path_params(request.rel_url.path_qs) if request.method in ["GET", "HEAD"]: try: ct, body = utils.extract_ct_body(params) except DOHParamsException as e: return aiohttp.web.Response(status=400, body=e.body()) elif request.method == "POST": body = await request.content.read() ct = request.headers.get("content-type") else: return aiohttp.web.Response(status=501, body=b"Not Implemented") if ct != constants.DOH_MEDIA_TYPE: return aiohttp.web.Response(status=415, body=b"Unsupported content type") # Do actual DNS Query try: dnsq = utils.dns_query_from_body(body, debug=request.app.debug) except DOHDNSException as e: return aiohttp.web.Response(status=400, body=e.body()) clientip = utils.get_client_ip(request.transport) request.app.logger.info("[HTTPS] {} (Original IP: {}) {}".format( clientip, request.remote, utils.dnsquery2log(dnsq))) return await request.app.resolve(request, dnsq)
def on_answer(self, stream_id, dnsr=None, dnsq=None): try: request_data = self.stream_data[stream_id] except KeyError: # Just return, we probably 405'd this already return response_headers = [ (":status", "200"), ("content-type", constants.DOH_MEDIA_TYPE), ("server", "asyncio-h2"), ] if dnsr is None: dnsr = dns.message.make_response(dnsq) dnsr.set_rcode(dns.rcode.SERVFAIL) elif len(dnsr.answer): ttl = min(r.ttl for r in dnsr.answer) response_headers.append( ("cache-control", "max-age={}".format(ttl))) clientip = utils.get_client_ip(self.transport) interval = int((time.time() - self.time_stamp) * 1000) self.logger.info("[HTTPS] {} {} {}ms".format(clientip, utils.dnsans2log(dnsr), interval)) if request_data.headers[":method"] == "HEAD": body = b"" else: body = dnsr.to_wire() response_headers.append(("content-length", str(len(body)))) self.conn.send_headers(stream_id, response_headers) self.conn.send_data(stream_id, body, end_stream=True) self.transport.write(self.conn.data_to_send())
async def resolve(self, dnsq, stream_id): clientip = utils.get_client_ip(self.transport) dnsclient = DNSClient(self.upstream_resolver, self.upstream_port, logger=self.logger) dnsr = await dnsclient.query(dnsq, clientip, ecs=self.ecs) if dnsr is None: self.on_answer(stream_id, dnsq=dnsq) else: self.on_answer(stream_id, dnsr=dnsr)
def stream_complete(self, stream_id: int): """ When a stream is complete, we can send our response. """ try: request_data = self.stream_data[stream_id] except KeyError: # Just return, we probably 405'd this already return headers = request_data.headers method = request_data.headers[':method'] # Handle the actual query path, params = utils.extract_path_params(headers[':path']) if path != self.uri: self.return_404(stream_id) return if method in ['GET', 'HEAD']: try: ct, body = utils.extract_ct_body(params) except DOHParamsException as e: self.return_400(stream_id, body=e.body()) return elif method == 'POST': body = request_data.data.getvalue() ct = headers.get('content-type') else: self.return_501(stream_id) return if ct != constants.DOH_MEDIA_TYPE: self.return_415(stream_id) return # Do actual DNS Query try: dnsq = utils.dns_query_from_body(body, self.debug) except DOHDNSException as e: self.return_400(stream_id, body=e.body()) return clientip = utils.get_client_ip(self.transport) self.logger.info( '[HTTPS] {} {}'.format( clientip, utils.dnsquery2log(dnsq) ) ) self.time_stamp = time.time() asyncio.ensure_future(self.resolve(dnsq, stream_id))
def receive_data(self, data: bytes, stream_id: int): """ We've received some data on a stream. If that stream is one we're expecting data on, save it off. Otherwise, reset the stream. """ try: stream_data = self.stream_data[stream_id] except KeyError: # Unknown stream, log and ignore (the stream may already be ended) clientip = utils.get_client_ip(self.transport) self.logger.info("[HTTPS] %s Unknown stream %d", clientip, stream_id) else: stream_data.data.write(data)