Exemple #1
0
 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)
Exemple #2
0
 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)])
Exemple #3
0
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)
Exemple #4
0
    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")
Exemple #5
0
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))
Exemple #6
0
                            "-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"]))
Exemple #7
0
 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)
Exemple #8
0
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)