diff options
| -rw-r--r-- | changes/feature_2877-improve_gateway_selector | 1 | ||||
| -rw-r--r-- | src/leap/services/eip/eipconfig.py | 33 | ||||
| -rw-r--r-- | src/leap/services/eip/vpnlaunchers.py | 24 | 
3 files changed, 32 insertions, 26 deletions
diff --git a/changes/feature_2877-improve_gateway_selector b/changes/feature_2877-improve_gateway_selector new file mode 100644 index 00000000..5162a09e --- /dev/null +++ b/changes/feature_2877-improve_gateway_selector @@ -0,0 +1 @@ +  o Improve gateway selector based on timezone. It allows to use multiple gateways in openvpn for redundancy. Closes #2894. diff --git a/src/leap/services/eip/eipconfig.py b/src/leap/services/eip/eipconfig.py index f7d03963..a85fe64a 100644 --- a/src/leap/services/eip/eipconfig.py +++ b/src/leap/services/eip/eipconfig.py @@ -52,33 +52,32 @@ class VPNGatewaySelector(object):          self._set_local_offset()          self._eipconfig = eipconfig -    def _get_best_gateway(self): +    def get_gateways(self):          """ -        Returns index of the closest gateway, using timezones offsets. +        Returns the 4 best gateways, sorted by timezone proximity. -        :rtype: int +        :rtype: list of IPv4Address or IPv6Address object.          """ -        best_gateway = (-1, 99)  # gateway, distance +        gateways_timezones = []          locations = self._eipconfig.get_locations()          gateways = self._eipconfig.get_gateways() +          for idx, gateway in enumerate(gateways): -            gateway_offset = int(locations[gateway['location']]['timezone']) -            gateway_distance = self._get_timezone_distance(gateway_offset) -            if gateway_distance < best_gateway[1]: -                best_gateway = (idx, gateway_distance) +            gateway_location = gateway.get('location') +            gateway_distance = 99  # if hasn't location -> should go last -        return best_gateway[0] +            if gateway_location is not None: +                gw_offset = int(locations[gateway['location']]['timezone']) +                gateway_distance = self._get_timezone_distance(gw_offset) -    def get_best_gateway_ip(self): -        """ -        Returns the ip of the best possible gateway. +            ip = self._eipconfig.get_gateway_ip(idx) +            gateways_timezones.append((ip, gateway_distance)) -        :rtype: An IPv4Address or IPv6Address object. -        """ -        best_gateway = self._get_best_gateway() -        gateway_ip = self._eipconfig.get_gateway_ip(best_gateway) +        gateways_timezones = sorted(gateways_timezones, +                                    key=lambda gw: gw[1])[:4] -        return gateway_ip +        gateways = [ip for ip, dist in gateways_timezones] +        return gateways      def _get_timezone_distance(self, offset):          ''' diff --git a/src/leap/services/eip/vpnlaunchers.py b/src/leap/services/eip/vpnlaunchers.py index fa2989bc..fdc863c6 100644 --- a/src/leap/services/eip/vpnlaunchers.py +++ b/src/leap/services/eip/vpnlaunchers.py @@ -229,16 +229,18 @@ class LinuxVPNLauncher(VPNLauncher):          # TODO: handle verbosity          gateway_selector = VPNGatewaySelector(eipconfig) -        gateway_ip = gateway_selector.get_best_gateway_ip() +        gateways = gateway_selector.get_gateways() -        logger.debug("Using gateway ip %s" % (gateway_ip,)) +        logger.debug("Using gateways ips: {}".format(', '.join(gateways))) + +        for gw in gateways: +            args += ['--remote', gw, '1194', 'udp']          args += [              '--client',              '--dev', 'tun',              '--persist-tun',              '--persist-key', -            '--remote', gateway_ip, '1194', 'udp',              '--tls-client',              '--remote-cert-tls',              'server' @@ -393,16 +395,18 @@ class DarwinVPNLauncher(VPNLauncher):          # TODO: handle verbosity          gateway_selector = VPNGatewaySelector(eipconfig) -        gateway_ip = gateway_selector.get_best_gateway_ip() +        gateways = gateway_selector.get_gateways() + +        logger.debug("Using gateways ips: {}".format(', '.join(gateways))) -        logger.debug("Using gateway ip %s" % (gateway_ip,)) +        for gw in gateways: +            args += ['--remote', gw, '1194', 'udp']          args += [              '--client',              '--dev', 'tun',              '--persist-tun',              '--persist-key', -            '--remote', gateway_ip, '1194', 'udp',              '--tls-client',              '--remote-cert-tls',              'server' @@ -534,16 +538,18 @@ class WindowsVPNLauncher(VPNLauncher):          # TODO: handle verbosity          gateway_selector = VPNGatewaySelector(eipconfig) -        gateway_ip = gateway_selector.get_best_gateway_ip() +        gateways = gateway_selector.get_gateways() + +        logger.debug("Using gateways ips: {}".format(', '.join(gateways))) -        logger.debug("Using gateway ip %s" % (gateway_ip,)) +        for gw in gateways: +            args += ['--remote', gw, '1194', 'udp']          args += [              '--client',              '--dev', 'tun',              '--persist-tun',              '--persist-key', -            '--remote', gateway_ip, '1194', 'udp',              '--tls-client',              '--remote-cert-tls',              'server'  | 
