Beispiel #1
0
    def on_network_state_changed(self, state):
        """Network status signal handler.

        Args:
            state (int): connection state (NMState)
        """
        logger.info("Network state changed: {}".format(state))
        if state == 70:
            self.vpn_activator()
Beispiel #2
0
 def on_session_lock(self):
     logger.info("Inside session lock")
     logger.info("Is user session locked: {}".format(
         self.user_session_locked))
     logger.info("Session got \"locked\"")
     self.user_session_locked = True
     logger.info("Is user session locked: {}".format(
         self.user_session_locked))
Beispiel #3
0
    def setup_protonvpn_conn(self, active_connection, vpn_interface):
        """Setup and start new ProtonVPN connection.

        Args:
            active_connection (string): path to active connection
            vpn_interface (dbus.Proxy): proxy interface to vpn connection
        """
        logger.info("Setting up ProtonVPN connecton: {} {}".format(
            active_connection, vpn_interface))
        new_con = self.nm_wrapper.activate_connection(vpn_interface,
                                                      dbus.ObjectPath("/"),
                                                      active_connection)
        self.vpn_signal_handler(new_con)
        logger.info("Starting manually ProtonVPN connection with '{}'.".format(
            self.virtual_device_name))
Beispiel #4
0
 def on_session_unlock(self):
     logger.info("Inside session unlock")
     logger.info("Is user session locked: {}".format(
         self.user_session_locked))
     logger.info("Session got \"unlocked\"")
     self.user_session_locked = False
     logger.info("Is user session locked: {}".format(
         self.user_session_locked))
     self.vpn_activator()
Beispiel #5
0
 def __init__(self,
              virtual_device_name,
              loop,
              max_attempts=100,
              delay=5000):  # noqa
     logger.info("\n\n------------------------"
                 " Initializing Dbus daemon manager "
                 "------------------------\n")
     self.virtual_device_name = virtual_device_name
     self.loop = loop
     self.max_attempts = max_attempts
     self.delay = delay
     self.failed_attempts = 0
     self.bus = dbus.SystemBus()
     self.nm_wrapper = NetworkManagerUnitWrapper(self.bus)
     self.login1_wrapper = Login1UnitWrapper(self.bus)
     self.user_session_locked = None
     # Auto connect at startup (Listen for StateChanged going forward)
     self.vpn_activator()
     self.connect_signals()
     logger.info("Is user session locked: {}".format(
         self.user_session_locked))
Beispiel #6
0
    def vpn_signal_handler(self, conn):
        """Add signal handler to ProtonVPN connection.

        Args:
            vpn_conn_path (string): path to ProtonVPN connection
        """
        proxy = self.bus.get_object("org.freedesktop.NetworkManager", conn)
        iface = dbus.Interface(
            proxy, "org.freedesktop.NetworkManager.VPN.Connection")

        try:
            active_conn_props = self.nm_wrapper.get_active_connection_properties(
                conn)
            logger.info("Adding listener to active {} connection at {}".format(
                active_conn_props["Id"], conn))
        except dbus.exceptions.DBusException:
            logger.info("{} is not an active connection.".format(conn))
        except Exception as e:
            logger.info("Unknown add signal error: {}".format(e))
        else:
            logger.info("Listener added")
            iface.connect_to_signal("VpnStateChanged",
                                    self.on_vpn_state_changed)
Beispiel #7
0
    def on_vpn_state_changed(self, state, reason):
        """VPN status signal handler.

        Args:
            state (int): NMVpnConnectionState
            reason (int): NMActiveConnectionStateReason
        """
        state = VPNConnectionStateEnum(state)
        reason = VPNConnectionReasonEnum(reason)
        logger.info("State: {} - ".format(state) + "Reason: {}".format(reason))
        if state == VPNConnectionStateEnum.IS_ACTIVE and not self.user_session_locked:
            logger.info(
                "ProtonVPN with virtual device '{}' is running.".format(
                    self.virtual_device_name))
            self.failed_attempts = 0

            connection_metadata.save_connect_time()

            try:
                if ipv6_leak_protection.enable_ipv6_leak_protection:
                    ipv6_leak_protection.manage(KillSwitchActionEnum.ENABLE)
            except:  # noqa
                pass

            if (settings.killswitch != KillswitchStatusEnum.DISABLED):
                killswitch.manage(KillSwitchActionEnum.POST_CONNECTION)
                logger.info("Running killswitch post-conneciton mode")

        elif (state == VPNConnectionStateEnum.DISCONNECTED
              and reason == VPNConnectionReasonEnum.USER_HAS_DISCONNECTED
              and not self.user_session_locked):
            logger.info("ProtonVPN connection was manually disconnected.")
            self.failed_attempts = 0

            try:
                vpn_iface = self.nm_wrapper.get_vpn_interface()
            except TypeError as e:
                logger.exception(e)

            try:
                vpn_iface.Delete()
            except dbus.exceptions.DBusException as e:
                logger.error("Unable to remove connection. " +
                             "Exception: {}".format(e))
            except AttributeError:
                pass

            logger.info("ProtonVPN connection has been manually removed.")

            try:
                ipv6_leak_protection.manage(KillSwitchActionEnum.DISABLE)
            except:  # noqa
                pass

            if (settings.killswitch != KillswitchStatusEnum.HARD):
                killswitch.delete_all_connections()

            loop.quit()

        elif state in [
                VPNConnectionStateEnum.FAILED,
                VPNConnectionStateEnum.DISCONNECTED
        ] and not self.user_session_locked:
            # reconnect if haven't reached max_attempts
            if (not self.max_attempts) or (self.failed_attempts <
                                           self.max_attempts):
                logger.info("Connection failed, attempting to reconnect.")
                self.failed_attempts += 1
                glib_reconnect = True
                GLib.timeout_add(self.delay, self.vpn_activator,
                                 glib_reconnect)
            else:
                logger.warning(
                    "Connection failed, exceeded {} max attempts.".format(
                        self.max_attempts))
Beispiel #8
0
    def vpn_activator(self, glib_reconnect=False):
        """Monitor and activate ProtonVPN connections."""
        logger.info("\n\n------- "
                    "VPN Activator"
                    " -------\n" +
                    "Virtual device being monitored: {}; ".format(
                        self.virtual_device_name) +
                    "Attempt {}/{} with interval of {} ".format(
                        self.failed_attempts, self.max_attempts, self.delay) +
                    "ms;\n")
        if self.user_session_locked:
            return

        vpn_interface = self.nm_wrapper.get_vpn_interface()

        try:
            active_connection = self.nm_wrapper.get_active_connection()
        except (dbus.exceptions.DBusException, Exception) as e:
            logger.exception(e)
            active_connection = None

        logger.info("VPN interface: {}".format(vpn_interface))
        logger.info("Active connection: {}".format(active_connection))

        if active_connection is None or vpn_interface is None:
            if not glib_reconnect:
                logger.info("Calling manually on vpn state changed")
                self.on_vpn_state_changed(VPNConnectionStateEnum.FAILED,
                                          VPNConnectionReasonEnum.UNKNOWN)
            else:
                return True

        (is_active_conn_vpn, all_vpn_settings
         ) = self.nm_wrapper.check_active_vpn_connection(active_connection)

        # Check if primary active connection was started by ProtonVPN client
        if (is_active_conn_vpn) and (all_vpn_settings["vpn"]["data"]["dev"]
                                     == self.virtual_device_name):
            logger.info("Primary connection via ProtonVPN.")
            self.vpn_signal_handler(active_connection)
            return False

        server_ip = connection_metadata.get_server_ip()
        logger.info("Reconnecting to server IP \"{}\"".format(server_ip))

        try:
            (is_protonvpn, state,
             conn) = self.nm_wrapper.is_protonvpn_being_prepared()
        except dbus.exceptions.DBusException as e:
            logger.exception(e)
        else:

            # Check if connection is being prepared
            if is_protonvpn and state == 1:
                logger.info("ProtonVPN connection is being prepared.")
                if (settings.killswitch != KillswitchStatusEnum.DISABLED):
                    killswitch.manage(KillSwitchActionEnum.PRE_CONNECTION,
                                      server_ip=server_ip)
                self.vpn_signal_handler(conn)
                return False

        if not self.manually_start_vpn_conn(server_ip, vpn_interface):
            if not glib_reconnect:
                logger.info("Calling manually on vpn state changed")
                self.on_vpn_state_changed(VPNConnectionStateEnum.FAILED,
                                          VPNConnectionReasonEnum.UNKNOWN)
            else:
                return True
Beispiel #9
0
    def manually_start_vpn_conn(self, server_ip, vpn_interface):
        logger.info("User ks setting: {}".format(settings.killswitch))
        if (settings.killswitch != KillswitchStatusEnum.DISABLED):
            try:
                killswitch.manage(KillSwitchActionEnum.PRE_CONNECTION,
                                  server_ip=server_ip)
            except Exception as e:
                logger.exception(
                    "KS manager reconnect exception: {}".format(e))
                return False
        logger.info("Created routed interface")

        try:
            new_active_connection = self.nm_wrapper.get_active_connection()
        except (dbus.exceptions.DBusException, Exception) as e:
            logger.exception(e)
            new_active_connection = None

        logger.info("Active conn prior to "
                    "setup manual connection: {} {}".format(
                        new_active_connection, type(new_active_connection)))

        if not new_active_connection:
            logger.info("No active connection, retrying reconnect")
            return False
        else:
            logger.info("Setting up manual connection")

            try:
                self.setup_protonvpn_conn(new_active_connection, vpn_interface)
            except dbus.exceptions.DBusException as e:
                logger.exception(
                    "Unable to start VPN connection: {}.".format(e))
                return False
            except Exception as e:
                logger.exception("Unknown reconnector error: {}.".format(e))
                return False

            logger.info("New ProtonVPN connection has been started " +
                        "from service.")
            return True