Beispiel #1
0
def print_version():
    """Prints the version of connord along with the copyright."""
    printer = Printer()
    print("connord {}".format(__version__), file=printer)
    print(__copyright__, file=printer)
    printer.info("\nConfiguration directory: '{}'".format(
        resources.get_config_dir()))
Beispiel #2
0
def _update_openvpn_conf(force):
    printer = Printer()
    try:
        resources.get_zip_dir(create=False)
        initial_run = False
    except resources.ResourceNotFoundError:
        initial_run = True

    if force or initial_run:
        get()
        unzip()
    else:
        update_archives = False
        for archive in __ARCHIVES.values():
            zip_file = resources.get_zip_path(archive)
            # if one archive needs an update all archives are updated
            if update_needed(zip_file):
                update_archives = True
                break
        else:
            raise UpdateError(
                "Just one update per hour allowed. Use --force to ignore "
                "the timeout."
            )

        if update_archives:
            get()
            for archive in __ARCHIVES.values():
                zip_file = resources.get_zip_path(archive)
                orig_file = resources.get_zip_path(archive + ".orig")
                if not file_equals(orig_file, zip_file):
                    unzip()
                    break
            else:
                printer.info("Configurations are up-to-date.")
Beispiel #3
0
def ping(server):
    """
    Ping a server
    :param dict server: A server as dictionary
    :returns: copy of server with additional key 'ping'
    """

    server_copy = server.copy()
    pattern = re.compile(r"rtt .* = ([\d\.]+)/([\d\.]+)/([\d\.]+)/.* ms")
    ip_address = server["ip_address"]
    with subprocess.Popen(
        ["ping", "-q", "-n", "-c", "1", "-l", "1", "-W", "1", ip_address],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    ) as ping_:

        out, _ = ping_.communicate()
        mat = pattern.search(out.decode())
        if mat:
            server_copy["ping"] = float(mat.group(2))
        else:
            server_copy["ping"] = float("inf")

        printer = Printer()
        printer.info(
            "{:6}: ping: {}".format(server_copy["domain"], server_copy["ping"])
        )
        return server_copy
Beispiel #4
0
    def run(self):
        """High-level command to run openvpn with the assembled command-line.
        Shuts down openvpn after a timeout. Waits this time for openvpn to startup
        and writes the environment files from the scripts. As soon as they are
        present iptables rules are applied. If something goes wrong call the panic
        method

        :returns: True if everything went fine or running in daemon mode.
        """

        config_dict = resources.get_config()["openvpn"]
        self.cleanup()

        printer = Printer()
        printer.info("Running openvpn with '{}'".format(self.cmd))
        with subprocess.Popen(self.cmd) as ovpn:
            # give openvpn a maximum of 60 seconds to startup. A lower value is bad if
            # asked for username/password.
            # pylint: disable=unused-variable
            for i in range(300):
                try:
                    if self.is_running(ovpn):
                        # delay initialization of iptables until resource files are
                        # created. If none are created the delay still applies as normal
                        # timeout
                        time.sleep(0.2)
                        for script in config_dict["scripts"]:
                            stage = script["stage"]
                            if stage in ("up", "always"):
                                resources.get_stats_file(
                                    stats_name=script["creates"], create=False
                                )

                    else:
                        self.panic(ovpn, "Openvpn process stopped unexpected.")

                    if iptables.apply_config_dir(self.server, self.protocol):
                        resources.write_stats(self.server, stats_name="server")

                        stats_dict = resources.get_stats()
                        stats_dict["last_server"] = {}
                        stats_dict["last_server"]["domain"] = self.domain
                        stats_dict["last_server"]["protocol"] = self.protocol
                        resources.write_stats(stats_dict)
                    else:
                        self.panic(ovpn, "Applying iptables failed.")

                    break
                except resources.ResourceNotFoundError:
                    pass
            ### for
            else:
                self.panic(ovpn, "Timeout reached.")

            if self.is_running(ovpn):
                ovpn.wait()

        return True
Beispiel #5
0
def connect(
    domain,
    countries_,
    areas_,
    features_,
    categories_,
    netflix,
    load_,
    match,
    daemon,
    openvpn,
    protocol,
):
    """High-level function to connect to a openvpn server. Filters servers and
    tries to connect to an openvpn server 'max_retries' times or else raise an
    exception.

    :param domain: list of domains. defaults to one value 'best'.
    :param countries_: list of countries
    :param areas_: list of areas
    :param features_: list of features
    :param categories_: list of categories
    :param netflix: True to filter netflix optimized servers
    :param load_: depending on match, filter by max, min or equal load servers
    :param match: may be 'max', 'min' or 'equal'
    :param daemon: True if openvpn shall run in daemon mode
    :param config_: the path to the openvpn configuration file
    :param openvpn: options to pass-through to openvpn as string
    :param protocol: may be 'udp' or 'tcp'
    :returns: True if running openvpn was successful
    :raises: ConnectError
    """

    if "best" not in domain:
        return connect_to_specific_server(domain, openvpn, daemon, protocol)

    servers_ = servers.get_servers()
    servers_ = filter_servers(
        servers_, netflix, countries_, areas_, features_, categories_, load_, match
    )

    best_servers = filter_best_servers(servers_)
    max_retries = 3
    printer = Printer()
    for i, server in enumerate(best_servers):
        if i == max_retries:
            raise ConnectError("Maximum retries reached.")

        if categories.has_category(server, "Obfuscated Servers"):
            if not printer.yes_no(
                (
                    "WARNING: {} is an obfuscated server.\n"
                    "This may fail if not configured properly.\n"
                    "Are you sure you want to continue?"
                ).format(server["domain"])
            ):
                continue

        if server["ping"] != inf:
            printer.info(
                "Trying to connect to {}: {} ms".format(
                    server["domain"], server["ping"]
                )
            )
            printer.print_map(server["location"]["lat"], server["location"]["long"])
            if run_openvpn(server, openvpn, daemon, protocol):
                return True

            # else give the next server a try
        else:
            raise ConnectError("No server left with a valid ping.")

    raise ConnectError("No server found to establish a connection.")