def __init__(self, domain, *args, ipv4_address=None, ipv6_address=None, **kwargs): self.middlewares = JsonRoutes(protocol="dns_middleware") dns_client = clients.dns.DNSJsonClient(domain, ipv4_address=ipv4_address, ipv6_address=ipv6_address) super().__init__(*args, clients=[dns_client], **kwargs)
def __init__(self, domain, ipv4_address=None, ipv6_address=None): self.domain = domain self.ipv4_address = ipv4_address or get_ipv4_address() self.ipv6_address = ipv6_address or get_ipv6_address() self.routes = JsonRoutes(protocol="dns", domain=self.domain) self.replace_args = {"domain": self.domain, "ipv4": self.ipv4_address, "ipv6": self.ipv6_address} super().__init__(servers=[("8.8.8.8", 53)])
class SSLContextFactory(ssl.ContextFactory): """ A TLS context factory which selects a certificate from the files/keys directory """ def __init__(self): self.ctx = SSL.Context(SSL.TLSv1_METHOD) self.ctx.set_tlsext_servername_callback(self.pick_certificate) self.tls_ctx = None self.middlewares = JsonRoutes(protocol="ssl_middleware") try: dk_path = os.path.join("files", "keys", "domain.key") dc_path = os.path.join("files", "keys", "domain.crt") if os.path.exists(dk_path) and os.path.exists(dc_path): ctx = SSL.Context(SSL.TLSv1_METHOD) ctx.use_privatekey_file(dk_path) ctx.use_certificate_file(dc_path) ctx.use_certificate_chain_file(dc_path) self.tls_ctx = ctx except Exception: logger.exception("Unable to load TLS certificate information") def getContext(self): return self.ctx def pick_certificate(self, connection): def _pick_certificate(connection): return self.tls_ctx # Apply middlewares server_name_indication = (connection.get_servername() or b'').decode("UTF-8") ctx = apply_middlewares(self.middlewares.get_descriptors(server_name_indication), _pick_certificate)(connection) if ctx is not None: connection.set_context(self.tls_ctx)
def __init__(self): self.ctx = SSL.Context(SSL.TLSv1_METHOD) self.ctx.set_tlsext_servername_callback(self.pick_certificate) self.tls_ctx = None self.middlewares = JsonRoutes(protocol="ssl_middleware") dk_path = os.path.join("files", "keys", "domain.key") dc_path = os.path.join("files", "keys", "domain.crt") if os.path.exists(dk_path) and os.path.exists(dc_path): ctx = SSL.Context(SSL.TLSv1_METHOD) ctx.use_privatekey_file(dk_path) ctx.use_certificate_file(dc_path) ctx.use_certificate_chain_file(dc_path) self.tls_ctx = ctx else: raise Exception("Unable to load TLS certificate information")
class DNSJsonServerFactory(server.DNSServerFactory): noisy = False def __init__(self, domain, *args, **kwargs): self.middlewares = JsonRoutes(protocol="dns_middleware") dns_client = clients.dns.DNSJsonClient(domain) super().__init__(*args, clients=[dns_client], **kwargs) def sendReply(self, protocol, message, address): r_addr, r_port = address if address is not None else ("N/A", 0) if len(message.answers): for answer in message.answers: r_name = answer.name.name.decode("UTF-8") r_type = dns.QUERY_TYPES.get(answer.type, "UnknownType") r_answer = str(answer.payload) logger.info("DNS: [{client:s}] - {query:s} {type:s} {answer:s}".format(client=r_addr, query=r_name, type=r_type, answer=r_answer)) else: for query in message.queries: r_name = query.name.name.decode("UTF-8") r_type = dns.QUERY_TYPES.get(query.type, "UnknownType") logger.info("DNS: [{client:s}] - {query:s} {type:s} -".format(client=r_addr, query=r_name, type=r_type)) super().sendReply(protocol, message, address) def handleQuery(self, message, protocol, address): _super = super() def _handleQuery(mpa): message, protocol, address = mpa return _super.handleQuery(message, protocol, address) name = message.queries[0].name.name.decode("UTF-8") return apply_middlewares(self.middlewares.get_descriptors(name), _handleQuery)((message, protocol, address))
"-d", type=str, default="example.com", help="the root domain name for this server") parser.add_argument("--full", "-f", default=False, action="store_true", help="show the full matching route definition") parser.add_argument("route", type=str, default=None, help="the route to match") args = parser.parse_args(cmdline) routes = JsonRoutes(protocol=args.protocol, domain=args.domain) route_files = sorted(routes.json_routes.keys(), key=routes.key) for i, route in enumerate(routes.get_descriptors(args.route)): route = route[0] # Get the file the route is defined in, this is a bit of a hack definition_file = None for x in route_files: if route in routes.json_routes[x]: definition_file = x break print("!" if i == 0 else " ", end="") if args.full: print("[{}] {}:\n\t{}".format(i, definition_file, repr(route))) else: print("[{}] {}: {}".format(i, definition_file, route["route"]))
def __init__(self, *args, **kwargs): self.filesroot = os.path.abspath(os.path.join("files")) self.routes = JsonRoutes(protocol="http") self.middlewares = JsonRoutes(protocol="http_middleware") super().__init__(*args, **kwargs)
class HTTPJsonResource(resource.Resource): """ HTTP resource which serves response based on a JsonRoutes object """ def __init__(self, *args, **kwargs): self.filesroot = os.path.abspath(os.path.join("files")) self.routes = JsonRoutes(protocol="http") self.middlewares = JsonRoutes(protocol="http_middleware") super().__init__(*args, **kwargs) def getChild(self, name, request): # Rebuild the request parts for route matching scheme = "https" if request.isSecure() else "http" host = request.getRequestHostname().decode("UTF-8") or "-" port = request.getHost().port path = request.path.decode("UTF-8") args = (request.uri.decode("UTF-8").split("?", 1) + [""])[1] request_path = path request_parts = [request_path] if args: request_parts.append(request_path + "?" + args) request_parts.append("{}://{}{}{}".format( scheme, host, (":%d" % port) if port != {"http": 80, "https": 443}[scheme] else "", request_parts[-1] )) def _getChild(request): headers = {} resource_path = request_path route_descriptor, route_match = self.routes.get_descriptor(*request_parts) if route_descriptor is not None: headers = route_descriptor.get("headers", {}) # Forward case if "forward" in route_descriptor: # Recreate the URL if route_descriptor.get("recreate_url", True): fscheme, fnetloc, _, _, _, _ = urllib.parse.urlparse(route_descriptor["forward"]) url = urllib.parse.urlunparse((fscheme, fnetloc, request.uri.decode("UTF-8"), "", "", "")) else: url = route_descriptor["forward"] replace = route_descriptor.get("replace", []) return ForwardResource(url, headers=headers, replace=replace) # Code case elif "code" in route_descriptor: code = route_descriptor.get("code", 200) body = route_descriptor.get("body", "") return SimpleResource(request_path, code, headers=headers, body=body) # Path case elif "path" in route_descriptor: resource_path = route_descriptor["path"] # Replace regex groups in the route path for i, group in enumerate(re.search(route_descriptor["route"], route_match).groups()): if group is not None: resource_path = resource_path.replace("${}".format(i + 1), group) # Security: Ensure the absolute resource_path is within the wwwroot! # Prepend the resource_path with the wwwroot and canonicalize resource_path = os.path.abspath(os.path.join(self.filesroot, resource_path.lstrip("/"))) if resource_path.startswith(self.filesroot): if os.path.exists(resource_path): # Security: Don't show the soruce of python files! if os.path.splitext(resource_path)[1].lower() == ".py": try: res = exec_cached_script(resource_path) return resource.IResource(res["get_resource"](request)) except Exception: logger.exception("Unahandled exception in exec'd file '{}'".format(resource_path)) else: with open(resource_path, "r") as f: data = f.read() return SimpleResource(request_path, 200, headers=headers, body=data) # Default handling, 404 here return super().getChild(name, request) return apply_middlewares(self.middlewares.get_descriptors(*request_parts), _getChild)(request)