Пример #1
0
    def import_config(self, file_path: str, username: str, password: str) -> bool:
        updated = False
        imported = False
        if self.remove_legacy_files():
            self.logger.info("Removed legacy files")

        if not os.path.isfile(file_path):
            self.logger.error("Configuration file '%s' does not exist.", file_path)
            return None

        # remove all old connections and any auto-connect, until a better import routine is added
        if self.remove_active_connections():
            updated = True
        if networkmanager.remove_autoconnect():
            updated = True

        dns_list = self.settings.get_custom_dns_servers()
        connection_name = os.path.splitext(os.path.basename(file_path))[0]

        if networkmanager.import_connection(file_path, connection_name, username, password, dns_list):
            updated = True
            imported = True
            self.active_servers[IMPORTED_SERVER_KEY] = {
                'name': connection_name,
                'domain': '<' + connection_name + '>',
                'score': -1,
                'load': -1,
                'latency': -1,
            }
            self.save_active_servers(self.active_servers, paths.ACTIVE_SERVERS)

        if updated:
            networkmanager.reload_connections()

        return imported
Пример #2
0
    def run(self, credentials, settings, update, sync, purge, auto_connect,
            kill_switch):
        self.setup()

        if credentials:
            self.credentials.save_new_credentials()
        if settings:
            self.settings.save_new_settings()
        if update:
            self.get_configs()

        if sync:
            if self.sync_servers():
                networkmanager.reload_connections()
        elif purge:
            networkmanager.remove_autoconnect()
            networkmanager.remove_killswitch(paths.KILLSWITCH)

            self.purge_active_connections()

        if auto_connect:
            self.enable_auto_connect(auto_connect[0], auto_connect[1],
                                     auto_connect[2])

        if kill_switch:
            networkmanager.set_killswitch(paths.KILLSWITCH)
Пример #3
0
    def sync(self, update_config=True, preserve_vpn=False, slow_mode=False):
        if self.remove_legacy_files():
            self.logger.info("Removed legacy files")

        if update_config:
            self.get_configs()

        if self.sync_servers(preserve_vpn, slow_mode):
            networkmanager.reload_connections()
Пример #4
0
    def __init__(self):
        parser = argparse.ArgumentParser()
        subparsers = parser.add_subparsers(title="commands", help="Each command has its own help page, which can be accessed via nordnm <COMMAND> --help", metavar='')

        # Kill-switch and auto-connect are repeated, to allow their use with or without the sync command.
        # TODO: Find out if there's a way to re-use the attributes so they don't need to be manually repeated
        parser.add_argument("-v", "--version", help="Display the package version.", action="store_true")
        parser.add_argument("-k", "--kill-switch", help="Sets a network kill-switch, to disable the active network interface when an active VPN connection disconnects.", action="store_true")
        parser.add_argument("-a", "--auto-connect", nargs=3, metavar=("[COUNTRY_CODE]", "[VPN_CATEGORY]", "[PROTOCOL]"), help="Configure NetworkManager to auto-connect to the chosen server type. Takes country code, category and protocol.")

        remove_parser = subparsers.add_parser("remove", aliases=['r'], help="Remove active connections, auto-connect, kill-switch, data, mac settings or all.")
        remove_parser.add_argument("--all", dest="remove_all", help="Remove all connections, enabled features and local data.", action="store_true")
        remove_parser.add_argument("-c", "--connections", dest="remove_c", help="Remove all active connections and auto-connect.", action="store_true")
        remove_parser.add_argument("-a", "--auto-connect", dest="remove_ac", help="Remove the active auto-connect feature.", action="store_true")
        remove_parser.add_argument("-k", "--kill-switch", dest="remove_ks", help="Remove the active kill-switch feature.", action="store_true")
        remove_parser.add_argument("-d", "--data", dest="remove_d", help="Remove existing local data (VPN Configs, Credentials & Settings).", action="store_true")
        remove_parser.add_argument("-m", "--mac-settings", dest="remove_m", help="Remove existing MAC Address settings configured by nordnm.", action="store_true")
        remove_parser.set_defaults(remove=True)

        update_parser = subparsers.add_parser('update', aliases=['u'], help='Update a specified setting.')
        update_parser.add_argument('-c', '--credentials', help='Update your existing saved credentials.', action='store_true')
        update_parser.add_argument('-s', '--settings', help='Update your existing saved settings.', action='store_true')
        update_parser.set_defaults(update=True)

        list_parser = subparsers.add_parser('list', aliases=['l'], help="List the specified information.")
        list_parser.add_argument('--active-servers', help='Display a list of the active servers currently synchronised.', action='store_true', default=False)
        list_parser.add_argument('--countries', help='Display a list of the available NordVPN countries.', action='store_true', default=False)
        list_parser.add_argument('--categories', help='Display a list of the available NordVPN categories..', action='store_true', default=False)
        list_parser.set_defaults(list=True)

        sync_parser = subparsers.add_parser('sync', aliases=['s'], help="Synchronise the optimal servers (based on load and latency) to NetworkManager.")
        sync_parser.add_argument('-s', '--slow-mode', help="Run benchmarking in 'slow mode'. May increase benchmarking success by pinging servers at a slower rate.", action='store_true')
        sync_parser.add_argument('-p', '--preserve-vpn', help="When provided, synchronising will preserve any active VPN instead of disabling it for more accurate benchmarking.", action='store_true')
        sync_parser.add_argument('-n', '--no-update', help='Do not download the latest OpenVPN configurations from NordVPN.', action='store_true', default=False)
        sync_parser.add_argument("-k", "--kill-switch", help="Sets a network kill-switch, to disable the active network interface when an active VPN connection disconnects.", action="store_true")
        sync_parser.add_argument('-a', '--auto-connect', nargs=3, metavar=('[COUNTRY_CODE]', '[VPN_CATEGORY]', '[PROTOCOL]'), help='Configure NetworkManager to auto-connect to the chosen server type. Takes country code, category and protocol.')
        sync_parser.set_defaults(sync=True)

        import_parser = subparsers.add_parser('import', aliases=['i'], help="Import an OpenVPN config file to NetworkManager.")
        import_parser.add_argument("config_file", metavar='CONFIG_FILE', help="The OpenVPN config file to be imported.")
        import_parser.add_argument("-k", "--kill-switch", help="Sets a network kill-switch, to disable the active network interface when an active VPN connection disconnects.", action="store_true")
        import_parser.add_argument('-a', '--auto-connect', help='Configure NetworkManager to auto-connect to the the imported config.', action="store_true", dest="auto_connect_imported", default=False)
        import_parser.add_argument('-u', '--username', required=True, help="Specify the username used for the OpenVPN config.", metavar="USERNAME")
        import_parser.add_argument('-p', '--password', required=True, help="Specify the password used for the OpenVPN config.", metavar="PASSWORD")
        import_parser.set_defaults(import_config=True)

        # For reference: https://blogs.gnome.org/thaller/category/networkmanager/
        mac_parser = subparsers.add_parser('mac', aliases=['m'], help="Global NetworkManager MAC address preferences. This command will affect ALL NetworkManager connections permanently.")
        mac_parser.add_argument('-r', '--random', help="A randomised MAC addresss will be generated on each connect.", action='store_true')
        mac_parser.add_argument('-s', '--stable', help="Use a stable, hashed MAC address on connect.", action='store_true')
        mac_parser.add_argument('-e', '--explicit', help="Specify a MAC address to use on connect.", nargs=1, metavar='"MAC_ADDRESS"')
        mac_parser.add_argument('--preserve', help="Don't change the current MAC address upon connection.", action='store_true')
        mac_parser.add_argument('--permanent', help="Use the permanent MAC address of the device on connect.", action='store_true')
        mac_parser.set_defaults(mac=True)

        self.logger = logging.getLogger(__name__)
        self.active_servers = {}

        try:
            args = parser.parse_args()
        except Exception:
            parser.print_help()
            sys.exit(1)

        # Count the number of arguments provided
        arg_count = 0
        for arg in vars(args):
            if getattr(args, arg):
                arg_count += 1

        if arg_count == 0:
            parser.print_help()
            sys.exit(1)

        if "version" in args and args.version:
            print(__version__)
            sys.exit(1)

        self.print_splash()

        # Check for commands that should be run on their own
        if "remove" in args and args.remove:
            removed = False

            if not args.remove_c and not args.remove_d and not args.remove_ac and not args.remove_ks and not args.remove_m and not args.remove_all:
                remove_parser.print_help()
                sys.exit(1)

            if args.remove_all:
                # Removing all, so set all args to True
                args.remove_ks = True
                args.remove_ac = True
                args.remove_c = True
                args.remove_d = True
                args.remove_m = True
            elif args.remove_c:
                # We need to remove the auto-connect if we are removing all connections
                args.remove_ac = True

            if args.remove_ks:
                if networkmanager.remove_killswitch():
                    removed = True

            if args.remove_ac:
                if networkmanager.remove_autoconnect():
                    removed = True

            if args.remove_c:
                # Get the active servers, since self.setup() hasn't run
                if os.path.isfile(paths.ACTIVE_SERVERS):
                    self.active_servers = self.load_active_servers(paths.ACTIVE_SERVERS)

                if self.remove_active_connections():
                    removed = True

            if args.remove_d:
                if self.remove_data():
                    removed = True

            if args.remove_m:
                if networkmanager.remove_global_mac_address():
                    removed = True

            if removed:
                networkmanager.reload_connections()
            else:
                self.logger.info("Nothing to remove.")

            sys.exit(0)
        elif "list" in args and args.list:
            if not args.countries and not args.categories and not args.active_servers:
                list_parser.print_help()
                sys.exit(1)

            if args.categories:
                self.print_categories()
            if args.countries:
                self.print_countries()
            if args.active_servers:
                self.print_active_servers()

            sys.exit(0)
        elif "mac" in args and args.mac:
            value = None
            if args.random:
                value = "random"
            elif args.stable:
                value = "stable"
            elif args.explicit:
                value = args.explicit[0]
            elif args.preserve:
                value = "preserve"
            elif args.permanent:
                value = "permanent"

            if value:
                if networkmanager.set_global_mac_address(value):
                    networkmanager.restart()
            else:
                mac_parser.print_help()

        # Now that arguments that don't need to be disturbed by setup() are over, do setup()
        self.setup()

        if "update" in args and args.update:
            if not args.credentials and not args.settings:
                update_parser.print_help()
                sys.exit(1)

            if args.credentials:
                self.credentials.save_new_credentials()
            if args.settings:
                self.settings.save_new_settings()

            sys.exit(0)

        # Now check for commands that can be chained...
        if "sync" in args and args.sync:
            # Take the inverse of no_update arg as update parameter
            self.sync(not args.no_update, args.preserve_vpn, args.slow_mode)

        if "import_config" in args and args.import_config:
            if not self.import_config(args.config_file, args.username, args.password):
                sys.exit(1)

            if args.auto_connect_imported:
                self.enable_auto_connect(*IMPORTED_SERVER_KEY)

        if args.kill_switch:
            networkmanager.set_killswitch()

        if args.auto_connect:
            country_code = args.auto_connect[0]
            category = args.auto_connect[1]
            protocol = args.auto_connect[2]

            self.enable_auto_connect(country_code, category, protocol)

        sys.exit(0)
Пример #5
0
 def sync(self, preserve_vpn=False):
     # remove legacy files
     if self.sync_servers(preserve_vpn):
         networkmanager.reload_connections()