diff options
10 files changed, 764 insertions, 298 deletions
diff --git a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java index ae8901e0..511893d7 100644 --- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java +++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java @@ -5,6 +5,8 @@ package de.blinkt.openvpn; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4_HOP; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PROFILE; import static se.leap.bitmaskclient.base.utils.ConfigHelper.stringEqual; @@ -50,6 +52,7 @@ import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; import java.security.spec.MGF1ParameterSpec; import java.security.spec.PSSParameterSpec; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Locale; @@ -73,10 +76,12 @@ import de.blinkt.openvpn.core.VpnStatus; import de.blinkt.openvpn.core.X509Utils; import de.blinkt.openvpn.core.connection.Connection; import de.blinkt.openvpn.core.connection.ConnectionAdapter; +import de.blinkt.openvpn.core.connection.Obfs4Connection; import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.models.ProviderObservable; import se.leap.bitmaskclient.base.utils.PreferenceHelper; +import se.leap.bitmaskclient.pluggableTransports.models.Obfs4Options; public class VpnProfile implements Serializable, Cloneable { // Note that this class cannot be moved to core where it belongs since @@ -272,11 +277,20 @@ public class VpnProfile implements Serializable, Cloneable { } @Override + public int hashCode() { + int result =(mGatewayIp != null ? mGatewayIp.hashCode() : 0); + result = 31 * result + Arrays.hashCode(mConnections); + result = 31 * result + mTransportType; + return result; + } + + @Override public boolean equals(Object obj) { if (obj instanceof VpnProfile) { VpnProfile vp = (VpnProfile) obj; return stringEqual(vp.mGatewayIp, mGatewayIp) && - vp.mTransportType == mTransportType; + vp.mTransportType == mTransportType && + Arrays.equals(mConnections, vp.mConnections); } return false; } @@ -315,6 +329,22 @@ public class VpnProfile implements Serializable, Cloneable { return Connection.TransportType.fromInt(mTransportType); } + public @Nullable Obfs4Options getObfs4Options() { + Connection.TransportType transportType = getTransportType(); + if (!(transportType == OBFS4 || transportType == OBFS4_HOP)) { + return null; + } + return ((Obfs4Connection) mConnections[0]).getObfs4Options(); + } + + public String getObfuscationTransportLayerProtocol() { + try { + return getObfs4Options().transport.getProtocols()[0]; + } catch (NullPointerException | ArrayIndexOutOfBoundsException ignore) { + return null; + } + } + public String getName() { if (TextUtils.isEmpty(mName)) return "No profile name"; diff --git a/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java b/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java index 0b28cbca..9943faff 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java +++ b/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java @@ -9,10 +9,13 @@ import static de.blinkt.openvpn.core.connection.Connection.TransportType.*; import android.text.TextUtils; +import androidx.annotation.NonNull; + import com.google.gson.annotations.JsonAdapter; import java.io.Serializable; import java.util.Locale; +import java.util.Objects; @JsonAdapter(ConnectionAdapter.class) public abstract class Connection implements Serializable, Cloneable { @@ -301,5 +304,54 @@ public abstract class Connection implements Serializable, Cloneable { this.mProxyAuthPassword = proxyAuthPassword; } - public abstract TransportType getTransportType(); + public abstract @NonNull TransportType getTransportType(); + + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Connection that)) return false; + + if (mUseUdp != that.mUseUdp) return false; + if (mUseCustomConfig != that.mUseCustomConfig) return false; + if (mEnabled != that.mEnabled) return false; + if (mConnectTimeout != that.mConnectTimeout) return false; + if (mUseProxyAuth != that.mUseProxyAuth) return false; + if (!Objects.equals(mServerName, that.mServerName)) + return false; + if (!Objects.equals(mServerPort, that.mServerPort)) + return false; + if (!Objects.equals(mCustomConfiguration, that.mCustomConfiguration)) + return false; + if (mProxyType != that.mProxyType) return false; + if (!Objects.equals(mProxyName, that.mProxyName)) + return false; + if (!Objects.equals(mProxyPort, that.mProxyPort)) + return false; + if (!Objects.equals(mProxyAuthUser, that.mProxyAuthUser)) + return false; + if (getTransportType() != that.getTransportType()) { + return false; + } + return Objects.equals(mProxyAuthPassword, that.mProxyAuthPassword); + } + + @Override + public int hashCode() { + int result = mServerName != null ? mServerName.hashCode() : 0; + result = 31 * result + (mServerPort != null ? mServerPort.hashCode() : 0); + result = 31 * result + (mUseUdp ? 1 : 0); + result = 31 * result + (mCustomConfiguration != null ? mCustomConfiguration.hashCode() : 0); + result = 31 * result + (mUseCustomConfig ? 1 : 0); + result = 31 * result + (mEnabled ? 1 : 0); + result = 31 * result + mConnectTimeout; + result = 31 * result + (mProxyType != null ? mProxyType.hashCode() : 0); + result = 31 * result + (mProxyName != null ? mProxyName.hashCode() : 0); + result = 31 * result + (mProxyPort != null ? mProxyPort.hashCode() : 0); + result = 31 * result + (mUseProxyAuth ? 1 : 0); + result = 31 * result + (mProxyAuthUser != null ? mProxyAuthUser.hashCode() : 0); + result = 31 * result + (mProxyAuthPassword != null ? mProxyAuthPassword.hashCode() : 0); + result = 31 * result + getTransportType().toInt(); + return result; + } } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java index ed61ca13..42935341 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -33,9 +33,7 @@ import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_STOP_BLOCKI import static se.leap.bitmaskclient.base.models.Constants.EIP_EARLY_ROUTES; import static se.leap.bitmaskclient.base.models.Constants.EIP_N_CLOSEST_GATEWAY; import static se.leap.bitmaskclient.base.models.Constants.EIP_RECEIVER; -import static se.leap.bitmaskclient.base.models.Constants.EIP_RESTART_ON_BOOT; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PROFILE; -import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.base.utils.ConfigHelper.ensureNotOnMainThread; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferredCity; import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_INVALID_PROFILE; @@ -71,8 +69,6 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.Closeable; import java.lang.ref.WeakReference; -import java.util.Observable; -import java.util.Observer; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; @@ -87,7 +83,6 @@ import se.leap.bitmaskclient.base.OnBootReceiver; import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.models.ProviderObservable; import se.leap.bitmaskclient.base.utils.PreferenceHelper; -import se.leap.bitmaskclient.eip.GatewaysManager.GatewayOptions; /** * EIP is the abstract base class for interacting with and managing the Encrypted @@ -251,8 +246,8 @@ public final class EIP extends JobIntentService implements PropertyChangeListene return; } - GatewayOptions gatewayOptions = gatewaysManager.select(nClosestGateway); - launchActiveGateway(gatewayOptions, nClosestGateway, result); + VpnProfile gatewayOptions = gatewaysManager.selectVpnProfile(nClosestGateway); + launchProfile(gatewayOptions, nClosestGateway, result); if (result.containsKey(BROADCAST_RESULT_KEY) && !result.getBoolean(BROADCAST_RESULT_KEY)) { tellToReceiverOrBroadcast(this, EIP_ACTION_START, RESULT_CANCELED, result); } else { @@ -266,7 +261,7 @@ public final class EIP extends JobIntentService implements PropertyChangeListene */ private void startEIPAlwaysOnVpn() { GatewaysManager gatewaysManager = new GatewaysManager(getApplicationContext()); - GatewayOptions gatewayOptions = gatewaysManager.select(0); + VpnProfile vpnProfile = gatewaysManager.selectVpnProfile(0); Bundle result = new Bundle(); if (shouldUpdateVPNCertificate()) { @@ -274,8 +269,7 @@ public final class EIP extends JobIntentService implements PropertyChangeListene p.setShouldUpdateVpnCertificate(true); ProviderObservable.getInstance().updateProvider(p); } - - launchActiveGateway(gatewayOptions, 0, result); + launchProfile(vpnProfile, 0, result); if (result.containsKey(BROADCAST_RESULT_KEY) && !result.getBoolean(BROADCAST_RESULT_KEY)){ VpnStatus.logWarning("ALWAYS-ON VPN: " + getString(R.string.no_vpn_profiles_defined)); } @@ -317,15 +311,15 @@ public final class EIP extends JobIntentService implements PropertyChangeListene } /** - * starts the VPN and connects to the given gateway + * starts the VPN and connects to the given Gateway the VpnProfile belongs to * - * @param gatewayOptions GatewayOptions model containing a Gateway and the associated transport used to connect + * @param profile VpnProfile which contains all information to setup a OpenVPN connection + * and optionally obfsvpn + * @param nClosestGateway gateway index, indicating the distance to the user + * @param result Bundle containing possible error messages shown to the user */ - private void launchActiveGateway(@Nullable GatewayOptions gatewayOptions, int nClosestGateway, Bundle result) { - VpnProfile profile; - - if (gatewayOptions == null || gatewayOptions.gateway == null || - (profile = gatewayOptions.gateway.getProfile(gatewayOptions.transportType)) == null) { + private void launchProfile(@Nullable VpnProfile profile, int nClosestGateway, Bundle result) { + if (profile == null) { String preferredLocation = getPreferredCity(); if (preferredLocation != null) { setErrorResult(result, NO_MORE_GATEWAYS.toString(), getStringResourceForNoMoreGateways(), getString(R.string.app_name), preferredLocation); @@ -379,7 +373,6 @@ public final class EIP extends JobIntentService implements PropertyChangeListene } } - /** * Stop VPN * First checks if the OpenVpnConnection is open then diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java index d2592cd7..16c92855 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java @@ -38,6 +38,7 @@ import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferUDP; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useObfuscationPinning; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.google.gson.Gson; @@ -45,8 +46,9 @@ import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; -import java.util.HashMap; import java.util.HashSet; +import java.util.Set; +import java.util.Vector; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConfigParser; @@ -75,10 +77,7 @@ public class Gateway { private String name; private int timezone; private int apiVersion; - /** FIXME: We expect here that not more than one obfs4 transport is offered by a gateway, however - * it's possible to setup gateways that have obfs4 over kcp and tcp which result in different VpnProfiles each - */ - private HashMap<Connection.TransportType, VpnProfile> vpnProfiles; + private Vector<VpnProfile> vpnProfiles; /** * Build a gateway object from a JSON OpenVPN gateway definition in eip-service.json @@ -190,10 +189,10 @@ public class Gateway { /** * Create and attach the VpnProfile to our gateway object */ - private @NonNull HashMap<Connection.TransportType, VpnProfile> createVPNProfiles(VpnConfigGenerator.Configuration profileConfig) + private @NonNull Vector<VpnProfile> createVPNProfiles(VpnConfigGenerator.Configuration profileConfig) throws ConfigParser.ConfigParseError, IOException, JSONException { VpnConfigGenerator vpnConfigurationGenerator = new VpnConfigGenerator(generalConfiguration, secrets, gateway, profileConfig); - HashMap<Connection.TransportType, VpnProfile> profiles = vpnConfigurationGenerator.generateVpnProfiles(); + Vector<VpnProfile> profiles = vpnConfigurationGenerator.generateVpnProfiles(); return profiles; } @@ -201,28 +200,68 @@ public class Gateway { return name; } - public HashMap<Connection.TransportType, VpnProfile> getProfiles() { + public Vector<VpnProfile> getProfiles() { return vpnProfiles; } - public VpnProfile getProfile(Connection.TransportType transportType) { - return vpnProfiles.get(transportType); + /** + * Returns a VpnProfile that supports a given transport type and any of the given transport + * layer protocols (e.g. TCP, KCP). If multiple VpnProfiles fulfill these requirements, a random + * profile will be chosen. This can currently only occur for obfuscation protocols. + * @param transportType transport type, e.g. openvpn or obfs4 + * @param obfuscationTransportLayerProtocols Vector of transport layer protocols PTs can be based on + * @return + */ + public @Nullable VpnProfile getProfile(Connection.TransportType transportType, @Nullable Set<String> obfuscationTransportLayerProtocols) { + Vector<VpnProfile> results = new Vector<>(); + for (VpnProfile vpnProfile : vpnProfiles) { + if (vpnProfile.getTransportType() == transportType) { + if (!vpnProfile.usePluggableTransports() || + obfuscationTransportLayerProtocols == null || + obfuscationTransportLayerProtocols.contains(vpnProfile.getObfuscationTransportLayerProtocol())) { + results.add(vpnProfile); + } + } + } + if (results.size() == 0) { + return null; + } + int randomIndex = (int) (Math.random() * (results.size())); + return results.get(randomIndex); } - public boolean supportsTransport(Connection.TransportType transportType) { + public boolean hasProfile(VpnProfile profile) { + return vpnProfiles.contains(profile); + } + + /** + * Checks if a transport type is supported by the gateway. + * In case the transport type is an obfuscation transport, you can pass a Vector of required transport layer protocols. + * This way you can filter for TCP based obfs4 traffic versus KCP based obfs4 traffic. + * @param transportType transport type, e.g. openvpn or obfs4 + * @param obfuscationTransportLayerProtocols filters for _any_ of these transport layer protocols (e.g. TCP or KCP) of a given obfuscation transportType, can be omitted if transportType is OPENVPN. + * + * @return + */ + public boolean supportsTransport(Connection.TransportType transportType, @Nullable Set<String> obfuscationTransportLayerProtocols) { if (transportType == PT) { return supportsPluggableTransports(); } - return vpnProfiles.get(transportType) != null; + return getProfile(transportType, obfuscationTransportLayerProtocols) != null; } public HashSet<Connection.TransportType> getSupportedTransports() { - return new HashSet<>(vpnProfiles.keySet()); + HashSet<Connection.TransportType> transportTypes = new HashSet<>(); + for (VpnProfile p : vpnProfiles) { + transportTypes.add(p.getTransportType()); + } + return transportTypes; } public boolean supportsPluggableTransports() { - for (Connection.TransportType transportType : vpnProfiles.keySet()) { - if (transportType.isPluggableTransport() && vpnProfiles.get(transportType) != null) { + for (VpnProfile profile : vpnProfiles) { + Connection.TransportType transportType = profile.getTransportType(); + if (transportType.isPluggableTransport()) { return true; } } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java index 9b4d431c..cd85f419 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -22,8 +22,10 @@ import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN import static de.blinkt.openvpn.core.connection.Connection.TransportType.PT; import static se.leap.bitmaskclient.base.models.Constants.GATEWAYS; import static se.leap.bitmaskclient.base.models.Constants.HOST; +import static se.leap.bitmaskclient.base.models.Constants.KCP; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.base.models.Constants.SORTED_GATEWAYS; +import static se.leap.bitmaskclient.base.models.Constants.TCP; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningCert; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningIP; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningKCP; @@ -46,10 +48,13 @@ import org.json.JSONObject; import java.io.IOException; import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; +import java.util.Set; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConfigParser; @@ -101,16 +106,6 @@ public class GatewaysManager { } } - public static class GatewayOptions { - public Gateway gateway; - public TransportType transportType; - - public GatewayOptions(Gateway gateway, TransportType transportType) { - this.gateway = gateway; - this.transportType = transportType; - } - } - private static final String TAG = GatewaysManager.class.getSimpleName(); public static final String PINNED_OBFUSCATION_PROXY = "pinned.obfuscation.proxy"; @@ -130,12 +125,12 @@ public class GatewaysManager { } /** - * select closest Gateway - * @return the n closest Gateway + * selects a VpnProfile of the n closest Gateway or a pinned gateway + * @return VpnProfile of the n closest Gateway or null if no remaining VpnProfiles available */ - public GatewayOptions select(int nClosest) { + public @Nullable VpnProfile selectVpnProfile(int nClosestGateway) { if (PreferenceHelper.useObfuscationPinning()) { - if (nClosest > 2) { + if (nClosestGateway > 2) { // no need to try again the pinned proxy, probably configuration error return null; } @@ -143,19 +138,35 @@ public class GatewaysManager { if (gateway == null) { return null; } - return new GatewayOptions(gateway, OBFS4); + return gateway.getProfile(OBFS4, null); } String selectedCity = getPreferredCity(); - return select(nClosest, selectedCity); + return selectVpnProfile(nClosestGateway, selectedCity); } - public GatewayOptions select(int nClosest, String city) { + /** + * Selects a VPN profile, filtered by distance to the user, transportType and + * optionally by city and transport layer protocol + * @param nClosestGateway + * @param city location filter + * @return VpnProfile of the n closest Gateway or null if no remaining VpnProfiles available + */ + public @Nullable VpnProfile selectVpnProfile(int nClosestGateway, String city) { TransportType[] transportTypes = getUseBridges() ? new TransportType[]{OBFS4, OBFS4_HOP} : new TransportType[]{OPENVPN}; + Set<String> obfuscationTransportLayerProtocols = getObfuscationTransportLayerProtocols(); if (presortedList.size() > 0) { - return getGatewayFromPresortedList(nClosest, transportTypes, city); + return getVpnProfileFromPresortedList(nClosestGateway, transportTypes, obfuscationTransportLayerProtocols, city); } - return getGatewayFromTimezoneCalculation(nClosest, transportTypes, city); + return getVpnProfileFromTimezoneCalculation(nClosestGateway, transportTypes, obfuscationTransportLayerProtocols, city); + } + @Nullable + private static Set<String> getObfuscationTransportLayerProtocols() { + Set<String> obfuscationTransportLayerProtocols = null; + if (getUseBridges()) { + obfuscationTransportLayerProtocols = new HashSet<>(Arrays.asList(TCP, KCP)); + } + return obfuscationTransportLayerProtocols; } public void updateTransport(TransportType transportType) { @@ -239,7 +250,7 @@ public class GatewaysManager { } private void updateLocation(Location location, Gateway gateway, Connection.TransportType transportType) { - if (gateway.supportsTransport(transportType)) { + if (gateway.supportsTransport(transportType, null)) { double averageLoad = location.getAverageLoad(transportType); int numberOfGateways = location.getNumberOfGateways(transportType); averageLoad = (numberOfGateways * averageLoad + gateway.getFullness()) / (numberOfGateways + 1); @@ -277,7 +288,7 @@ public class GatewaysManager { return Load.getLoadByValue(location.getAverageLoad(transportType)); } - private GatewayOptions getGatewayFromTimezoneCalculation(int nClosest, TransportType[] transportTypes, @Nullable String city) { + private VpnProfile getVpnProfileFromTimezoneCalculation(int nClosest, TransportType[] transportTypes, @Nullable Set<String> protocols, @Nullable String city) { List<Gateway> list = new ArrayList<>(gateways.values()); if (gatewaySelector == null) { gatewaySelector = new GatewaySelector(list); @@ -287,10 +298,10 @@ public class GatewaysManager { int i = 0; while ((gateway = gatewaySelector.select(i)) != null) { for (TransportType transportType : transportTypes) { - if ((city == null && gateway.supportsTransport(transportType)) || - (gateway.getName().equals(city) && gateway.supportsTransport(transportType))) { + if ((city == null && gateway.supportsTransport(transportType, protocols)) || + (gateway.getName().equals(city) && gateway.supportsTransport(transportType, protocols))) { if (found == nClosest) { - return new GatewayOptions(gateway, transportType); + return gateway.getProfile(transportType, protocols); } found++; } @@ -300,19 +311,18 @@ public class GatewaysManager { return null; } - private GatewayOptions getGatewayFromPresortedList(int nClosest, TransportType[] transportTypes, @Nullable String city) { + private VpnProfile getVpnProfileFromPresortedList(int nClosest, TransportType[] transportTypes, @Nullable Set<String> protocols, @Nullable String city) { int found = 0; for (Gateway gateway : presortedList) { for (TransportType transportType : transportTypes) { - if ((city == null && gateway.supportsTransport(transportType)) || - (gateway.getName().equals(city) && gateway.supportsTransport(transportType))) { + if ((city == null && gateway.supportsTransport(transportType, protocols)) || + (gateway.getName().equals(city) && gateway.supportsTransport(transportType, protocols))) { if (found == nClosest) { - return new GatewayOptions(gateway, transportType); + return gateway.getProfile(transportType, protocols); } found++; } } - } return null; } @@ -331,35 +341,28 @@ public class GatewaysManager { } private int getPositionFromPresortedList(VpnProfile profile) { - TransportType transportType = profile.getTransportType(); - int nClosest = 0; + int nClosestGateway = 0; for (Gateway gateway : presortedList) { - if (gateway.supportsTransport(transportType)) { - if (profile.equals(gateway.getProfile(transportType))) { - return nClosest; - } - nClosest++; + if (gateway.hasProfile(profile)) { + return nClosestGateway; } + nClosestGateway++; } return -1; } private int getPositionFromTimezoneCalculatedList(VpnProfile profile) { - TransportType transportType = profile.getTransportType(); if (gatewaySelector == null) { gatewaySelector = new GatewaySelector(new ArrayList<>(gateways.values())); } Gateway gateway; - int nClosest = 0; + int nClosestGateway = 0; int i = 0; - while ((gateway = gatewaySelector.select(i)) != null) { - if (gateway.supportsTransport(transportType)) { - if (profile.equals(gateway.getProfile(transportType))) { - return nClosest; - } - nClosest++; + while ((gateway = gatewaySelector.select(nClosestGateway)) != null) { + if (gateway.hasProfile(profile)) { + return nClosestGateway; } - i++; + nClosestGateway++; } return -1; } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java index 8cbc4289..5defa7e6 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -31,6 +31,7 @@ import static se.leap.bitmaskclient.base.models.Constants.TCP; import static se.leap.bitmaskclient.base.models.Constants.TRANSPORT; import static se.leap.bitmaskclient.base.models.Constants.UDP; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import org.json.JSONArray; @@ -39,17 +40,15 @@ import org.json.JSONObject; import java.io.IOException; import java.io.StringReader; -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Set; +import java.util.Vector; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConfigParser; import de.blinkt.openvpn.core.VpnStatus; -import de.blinkt.openvpn.core.connection.Connection; import de.blinkt.openvpn.core.connection.Connection.TransportType; -import de.blinkt.openvpn.core.connection.Obfs4Connection; import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.models.Transport; import se.leap.bitmaskclient.base.utils.ConfigHelper; @@ -60,7 +59,7 @@ public class VpnConfigGenerator { private final JSONObject generalConfiguration; private final JSONObject gateway; private final JSONObject secrets; - HashMap<TransportType, Transport> transports = new HashMap<>(); + Vector<Transport> transports = new Vector<>(); private final int apiVersion; private final boolean preferUDP; private final boolean experimentalTransports; @@ -116,7 +115,7 @@ public class VpnConfigGenerator { JSONArray supportedTransports = gateway.getJSONObject(CAPABILITIES).getJSONArray(TRANSPORT); for (int i = 0; i < supportedTransports.length(); i++) { Transport transport = Transport.fromJson(supportedTransports.getJSONObject(i)); - transports.put(transport.getTransportType(), transport); + transports.add(transport); } } } catch (Exception e) { @@ -124,32 +123,34 @@ public class VpnConfigGenerator { } } - public HashMap<TransportType, VpnProfile> generateVpnProfiles() throws + public Vector<VpnProfile> generateVpnProfiles() throws ConfigParser.ConfigParseError, NumberFormatException { - HashMap<Connection.TransportType, VpnProfile> profiles = new HashMap<>(); - if (supportsOpenvpn()) { - try { - profiles.put(OPENVPN, createProfile(OPENVPN)); - } catch (ConfigParser.ConfigParseError | NumberFormatException | JSONException | IOException e) { - e.printStackTrace(); - } - } + Vector<VpnProfile> profiles = new Vector<>(); + if (apiVersion >= 3) { - for (TransportType transportType : transports.keySet()) { - Transport transport = transports.get(transportType); - if (transportType.isPluggableTransport()) { + for (Transport transport : transports){ + if (transport.getTransportType().isPluggableTransport()) { Transport.Options transportOptions = transport.getOptions(); if (!experimentalTransports && transportOptions != null && transportOptions.isExperimental()) { continue; } - try { - profiles.put(transportType, createProfile(transportType)); - } catch (ConfigParser.ConfigParseError | NumberFormatException | JSONException | IOException e) { - e.printStackTrace(); - } + } else if (transport.getTransportType() == OPENVPN && useObfuscationPinning) { + continue; + } + try { + profiles.add(createProfile(transport)); + } catch (ConfigParser.ConfigParseError | NumberFormatException | JSONException | IOException e) { + e.printStackTrace(); } } + } else if (supportsOpenvpn()) { + // API v1 - TODO: let's remove support for API v1 soon + try { + profiles.add(createApiv1OpenvpnProfile()); + } catch (ConfigParser.ConfigParseError | NumberFormatException | JSONException | IOException e) { + e.printStackTrace(); + } } if (profiles.isEmpty()) { throw new ConfigParser.ConfigParseError("No supported transports detected."); @@ -159,14 +160,14 @@ public class VpnConfigGenerator { private boolean supportsOpenvpn() { return !useObfuscationPinning && - ((apiVersion >= 3 && transports.containsKey(OPENVPN)) || - (apiVersion < 3 && !gatewayConfiguration(OPENVPN).isEmpty())); + ((apiVersion >= 3 && getTransport(OPENVPN) != null) || + (apiVersion < 3 && !gatewayConfiguration(null).isEmpty())); } - private String getConfigurationString(TransportType transportType) { + private String getConfigurationString(Transport transport) { return generalConfiguration() + newLine - + gatewayConfiguration(transportType) + + gatewayConfiguration(transport) + newLine + androidCustomizations() + newLine @@ -174,12 +175,13 @@ public class VpnConfigGenerator { } @VisibleForTesting - protected VpnProfile createProfile(TransportType transportType) throws IOException, ConfigParser.ConfigParseError, JSONException { - String configuration = getConfigurationString(transportType); + protected VpnProfile createProfile(Transport transport) throws IOException, ConfigParser.ConfigParseError, JSONException { + TransportType transportType = transport.getTransportType(); + String configuration = getConfigurationString(transport); ConfigParser icsOpenvpnConfigParser = new ConfigParser(); icsOpenvpnConfigParser.parseConfig(new StringReader(configuration)); if (transportType == OBFS4 || transportType == OBFS4_HOP) { - icsOpenvpnConfigParser.setObfs4Options(getObfs4Options(transportType)); + icsOpenvpnConfigParser.setObfs4Options(getObfs4Options(transport)); } VpnProfile profile = icsOpenvpnConfigParser.convertProfile(transportType); @@ -191,17 +193,29 @@ public class VpnConfigGenerator { return profile; } - private Obfs4Options getObfs4Options(TransportType transportType) throws JSONException { + @VisibleForTesting + protected VpnProfile createApiv1OpenvpnProfile() throws IOException, ConfigParser.ConfigParseError, JSONException { + String configuration = getConfigurationString(null); + ConfigParser icsOpenvpnConfigParser = new ConfigParser(); + icsOpenvpnConfigParser.parseConfig(new StringReader(configuration)); + + VpnProfile profile = icsOpenvpnConfigParser.convertProfile(OPENVPN); + profile.mName = profileName; + profile.mGatewayIp = remoteGatewayIP; + if (excludedApps != null) { + profile.mAllowedAppsVpn = new HashSet<>(excludedApps); + } + return profile; + } + + private Obfs4Options getObfs4Options(Transport transport) throws JSONException { String ip = gateway.getString(IP_ADDRESS); - Transport transport; if (useObfuscationPinning) { transport = new Transport(OBFS4.toString(), new String[]{obfuscationPinningKCP ? KCP : TCP}, new String[]{obfuscationPinningPort}, obfuscationPinningCert); ip = obfuscationPinningIP; - } else { - transport = transports.get(transportType); } return new Obfs4Options(ip, transport); } @@ -229,7 +243,7 @@ public class VpnConfigGenerator { return commonOptions; } - private String gatewayConfiguration(TransportType transportType) { + private String gatewayConfiguration(@Nullable Transport transport) { String configs = ""; StringBuilder stringBuilder = new StringBuilder(); @@ -250,11 +264,13 @@ public class VpnConfigGenerator { String[] ipAddresses = ipAddress6.isEmpty() ? new String[]{ipAddress} : new String[]{ipAddress6, ipAddress}; - - gatewayConfigMinApiv3(transportType, stringBuilder, ipAddresses); + if (transport == null) { + throw new NullPointerException("Transport is not allowed to be null in APIv3+"); + } + gatewayConfigMinApiv3(transport, stringBuilder, ipAddresses); break; } - } catch (JSONException e) { + } catch (JSONException | NullPointerException e) { // TODO Auto-generated catch block e.printStackTrace(); } @@ -267,12 +283,21 @@ public class VpnConfigGenerator { return configs; } - private void gatewayConfigMinApiv3(TransportType transportType, StringBuilder stringBuilder, String[] ipAddresses) throws JSONException { - if (transportType.isPluggableTransport()) { - ptGatewayConfigMinApiv3(stringBuilder, ipAddresses, transports.get(transportType)); + private void gatewayConfigMinApiv3(Transport transport, StringBuilder stringBuilder, String[] ipAddresses) throws JSONException { + if (transport.getTransportType().isPluggableTransport()) { + ptGatewayConfigMinApiv3(stringBuilder, ipAddresses, transport); } else { - ovpnGatewayConfigMinApi3(stringBuilder, ipAddresses, transports.get(OPENVPN)); + ovpnGatewayConfigMinApi3(stringBuilder, ipAddresses, transport); + } + } + + private @Nullable Transport getTransport(TransportType transportType) { + for (Transport transport : transports) { + if (transport.getTransportType() == transportType) { + return transport; + } } + return null; } private void gatewayConfigApiv1(StringBuilder stringBuilder, String ipAddress, JSONObject capabilities) throws JSONException { @@ -290,8 +315,8 @@ public class VpnConfigGenerator { } } - private void ovpnGatewayConfigMinApi3(StringBuilder stringBuilder, String[] ipAddresses, Transport transport) { - if (transport.getProtocols() == null || transport.getPorts() == null) { + private void ovpnGatewayConfigMinApi3(StringBuilder stringBuilder, String[] ipAddresses, @Nullable Transport transport) { + if (transport == null || transport.getProtocols() == null || transport.getPorts() == null) { VpnStatus.logError("Misconfigured provider: missing details for transport openvpn on gateway " + ipAddresses[0]); return; } @@ -426,7 +451,7 @@ public class VpnConfigGenerator { // configuration, so we assume yes return true; } - Transport openvpnTransport = transports.get(OPENVPN); + Transport openvpnTransport = getTransport(OPENVPN); if (openvpnTransport == null) { // the bridge seems to be to be decoupled from the gateway, we can't say if the openvpn gateway // will support this PT and hope the admins configured the gateway correctly @@ -455,6 +480,8 @@ public class VpnConfigGenerator { for (String protocol : ptProtocols) { if (isAllowedProtocol(transport.getTransportType(), protocol)) { return true; + } else { + VpnStatus.logError("Provider - client incompatibility: " + protocol + " is not an allowed transport layer protocol for " + transport.getType()); } } diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/GatewayTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/GatewayTest.java new file mode 100644 index 00000000..66c139b2 --- /dev/null +++ b/app/src/test/java/se/leap/bitmaskclient/eip/GatewayTest.java @@ -0,0 +1,154 @@ +package se.leap.bitmaskclient.eip; + +import static org.junit.Assert.*; + +import static se.leap.bitmaskclient.base.models.Constants.GATEWAYS; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; +import static se.leap.bitmaskclient.base.models.Provider.CA_CERT; +import static se.leap.bitmaskclient.testutils.TestSetupHelper.getProvider; + +import android.content.Context; +import android.content.SharedPreferences; + +import androidx.annotation.Nullable; + +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Answers; +import org.mockito.Mock; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; + +import de.blinkt.openvpn.VpnProfile; +import de.blinkt.openvpn.core.ConfigParser; +import de.blinkt.openvpn.core.connection.Connection; +import de.blinkt.openvpn.core.connection.Obfs4Connection; +import se.leap.bitmaskclient.base.models.Provider; +import se.leap.bitmaskclient.base.models.ProviderObservable; +import se.leap.bitmaskclient.base.utils.PreferenceHelper; +import se.leap.bitmaskclient.base.utils.TimezoneHelper; +import se.leap.bitmaskclient.testutils.MockSharedPreferences; +import se.leap.bitmaskclient.testutils.TestSetupHelper; + +public class GatewayTest { + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Context mockContext; + + private SharedPreferences sharedPreferences; + + @Before + public void setUp() throws IOException, JSONException { + sharedPreferences = new MockSharedPreferences(); + + PreferenceHelper preferenceHelper = new PreferenceHelper(sharedPreferences); + } + + + private Gateway createGatewayFromProvider(int nClosest, @Nullable String eipServiceJsonPath) throws ConfigParser.ConfigParseError, JSONException, IOException { + Provider provider = getProvider(null, null, null, null, null, null, eipServiceJsonPath, null); + JSONObject eipServiceJson = provider.getEipServiceJson(); + + JSONObject gatewayJson = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0); + JSONObject secrets = new JSONObject(); + try { + secrets.put(Provider.CA_CERT, provider.getCaCert()); + secrets.put(PROVIDER_VPN_CERTIFICATE, provider.getVpnCertificate()); + } catch (JSONException e) { + e.printStackTrace(); + } + + + return new Gateway(eipServiceJson, secrets, gatewayJson); + } + @Test + public void testGetProfile_OpenVPN_obfuscationProtocols_ignored_OpenVPNfound() throws ConfigParser.ConfigParseError, JSONException, IOException { + Gateway gateway = createGatewayFromProvider(0, "ptdemo_three_mixed_gateways.json"); + VpnProfile profile = gateway.getProfile(Connection.TransportType.OPENVPN, new HashSet<>(Arrays.asList("invalid"))); + assertNotNull(profile); + } + + @Test + public void testGetProfile_obfs4_obfuscationProtocolsTakenIntoAccount_Obfs4Notfound() throws ConfigParser.ConfigParseError, JSONException, IOException { + Gateway gateway = createGatewayFromProvider(0, "ptdemo_three_mixed_gateways.json"); + VpnProfile profile = gateway.getProfile(Connection.TransportType.OBFS4, new HashSet<>(Arrays.asList("invalid"))); + assertNull(profile); + } + + @Test + public void testGetProfile_obfs4_obfuscationProtocolsTakenIntoAccount_Obfs4found() throws ConfigParser.ConfigParseError, JSONException, IOException { + Gateway gateway = createGatewayFromProvider(0, "ptdemo_three_mixed_gateways.json"); + VpnProfile profile = gateway.getProfile(Connection.TransportType.OBFS4, new HashSet<>(Arrays.asList("tcp"))); + assertNotNull(profile); + } + + @Test + public void testGetProfile_obfs4_obfuscationProtocolsTakenIntoAccount_Obfs4KCPfound() throws ConfigParser.ConfigParseError, JSONException, IOException { + Gateway gateway = createGatewayFromProvider(0, "multiple_pts_per_host_eip-service.json"); + VpnProfile profile = gateway.getProfile(Connection.TransportType.OBFS4, new HashSet<>(Arrays.asList("kcp"))); + assertNotNull(profile); + } + + @Test + public void testGetProfile_obfs4_multipleProfiles_randomlySelected() throws ConfigParser.ConfigParseError, JSONException, IOException { + Gateway gateway = createGatewayFromProvider(0, "multiple_pts_per_host_eip-service.json"); + VpnProfile profile1 = gateway.getProfile(Connection.TransportType.OBFS4, new HashSet<>(Arrays.asList("kcp", "tcp"))); + assertNotNull(profile1); + assertEquals(1, profile1.mConnections.length); + assertTrue(profile1.mConnections[0] instanceof Obfs4Connection); + String[] transportLayerProtocols = ((Obfs4Connection)profile1.mConnections[0]).getObfs4Options().transport.getProtocols(); + + boolean profileWithDifferentTransportLayerProtosFound = false; + for (int i = 0; i < 1000; i++) { + VpnProfile otherProfile = gateway.getProfile(Connection.TransportType.OBFS4, new HashSet<>(Arrays.asList("kcp", "tcp"))); + String[] otherProtocols = ((Obfs4Connection)otherProfile.mConnections[0]).getObfs4Options().transport.getProtocols(); + if (!transportLayerProtocols[0].equals(otherProtocols[0])) { + profileWithDifferentTransportLayerProtosFound = true; + System.out.println(i + 1 + " attempts"); + break; + } + } + assertTrue(profileWithDifferentTransportLayerProtosFound); + } + + @Test + public void testSupportsTransport() throws ConfigParser.ConfigParseError, JSONException, IOException { + Gateway gateway = createGatewayFromProvider(0, "multiple_pts_per_host_eip-service.json"); + assertFalse(gateway.supportsTransport(Connection.TransportType.OBFS4_HOP, null)); + assertTrue(gateway.supportsTransport(Connection.TransportType.OBFS4, null)); + assertTrue(gateway.supportsTransport(Connection.TransportType.OBFS4, new HashSet<>(Arrays.asList("kcp")))); + assertTrue(gateway.supportsTransport(Connection.TransportType.OBFS4, new HashSet<>(Arrays.asList("tcp")))); + assertFalse(gateway.supportsTransport(Connection.TransportType.OBFS4, new HashSet<>(Arrays.asList("invalid")))); + } + + @Test + public void testGetSupportedTransports() throws ConfigParser.ConfigParseError, JSONException, IOException { + Gateway gateway = createGatewayFromProvider(0, "multiple_pts_per_host_eip-service.json"); + assertEquals(2, gateway.getSupportedTransports().size()); + assertTrue(gateway.getSupportedTransports().contains(Connection.TransportType.OBFS4)); + assertTrue(gateway.getSupportedTransports().contains(Connection.TransportType.OPENVPN)); + } + + @Test + public void testHasProfile() throws ConfigParser.ConfigParseError, JSONException, IOException { + Gateway gateway = createGatewayFromProvider(0, "multiple_pts_per_host_eip-service.json"); + VpnProfile profile = gateway.getProfiles().get(0); + String profileString = profile.toJson(); + VpnProfile newProfile = VpnProfile.fromJson(profileString); + assertTrue(gateway.hasProfile(newProfile)); + + newProfile.mGatewayIp = "XXXX"; + assertFalse(gateway.hasProfile(newProfile)); + + VpnProfile newProfile2 = VpnProfile.fromJson(profileString); + newProfile2.mConnections = new Connection[0]; + assertFalse(gateway.hasProfile(newProfile2)); + } + + +}
\ No newline at end of file diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java index 9286a787..b79c34ae 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java @@ -3,6 +3,7 @@ package se.leap.bitmaskclient.eip; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNull; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; @@ -20,11 +21,12 @@ import static se.leap.bitmaskclient.testutils.TestSetupHelper.getProvider; import android.content.Context; import android.content.SharedPreferences; +import androidx.annotation.Nullable; + import org.json.JSONException; import org.json.JSONObject; import org.junit.Before; import org.junit.Test; -import org.junit.function.ThrowingRunnable; import org.mockito.Answers; import org.mockito.Mock; @@ -34,9 +36,11 @@ import java.util.List; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConfigParser; +import de.blinkt.openvpn.core.connection.Connection; import se.leap.bitmaskclient.base.models.Location; import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.models.ProviderObservable; +import se.leap.bitmaskclient.base.models.Transport; import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.base.utils.TimezoneHelper; import se.leap.bitmaskclient.testutils.MockSharedPreferences; @@ -87,6 +91,18 @@ public class GatewaysManagerTest { assertEquals(3, gatewaysManager.size()); } + @Nullable + private static VpnProfile createProfile(VpnConfigGenerator configGenerator, Connection.TransportType transportType) throws IOException, ConfigParser.ConfigParseError, JSONException { + VpnProfile profile = null; + for (Transport transport : configGenerator.transports) { + if (transport.getTransportType() == transportType) { + profile = configGenerator.createProfile(transport); + break; + } + } + return profile; + } + @Test public void TestGetPosition_VpnProfileExtistingObfs4_returnPositionZero() throws JSONException, ConfigParser.ConfigParseError, IOException { Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", null); @@ -99,9 +115,10 @@ public class GatewaysManagerTest { configuration.apiVersion = 3; configuration.remoteGatewayIP = "37.218.247.60"; VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, configuration); - VpnProfile profile = configGenerator.createProfile(OBFS4); - + VpnProfile profile = createProfile(configGenerator, OBFS4); + assertNotNull(profile); assertEquals(0, gatewaysManager.getPosition(profile)); + } @Test @@ -116,8 +133,8 @@ public class GatewaysManagerTest { configuration.apiVersion = 3; configuration.remoteGatewayIP = "37.218.247.60"; VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, configuration); - VpnProfile profile = configGenerator.createProfile(OPENVPN); - + VpnProfile profile = createProfile(configGenerator, OPENVPN); + assertNotNull(profile); assertEquals(0, gatewaysManager.getPosition(profile)); } @@ -133,7 +150,7 @@ public class GatewaysManagerTest { configuration.apiVersion = 3; configuration.remoteGatewayIP = "37.218.247.60"; VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, configuration); - assertThrows(ConfigParser.ConfigParseError.class, () -> configGenerator.createProfile(OBFS4)); + assertThrows(ConfigParser.ConfigParseError.class, () -> createProfile(configGenerator, OBFS4)); } @Test @@ -148,9 +165,9 @@ public class GatewaysManagerTest { configuration.apiVersion = 3; configuration.remoteGatewayIP = "37.218.247.60"; VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, configuration); - VpnProfile profile = configGenerator.createProfile(OBFS4); + VpnProfile profile = createProfile(configGenerator, OBFS4); - assertEquals(1, gatewaysManager.getPosition(profile)); + assertEquals(2, gatewaysManager.getPosition(profile)); } @Test @@ -165,7 +182,7 @@ public class GatewaysManagerTest { configuration.apiVersion = 3; configuration.remoteGatewayIP = "37.218.247.60"; VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, configuration); - VpnProfile profile = configGenerator.createProfile(OPENVPN); + VpnProfile profile = createProfile(configGenerator, OPENVPN); assertEquals(2, gatewaysManager.getPosition(profile)); } @@ -182,7 +199,7 @@ public class GatewaysManagerTest { configuration.apiVersion = 3; configuration.remoteGatewayIP = "37.218.247.61"; VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, configuration); - VpnProfile profile = configGenerator.createProfile(OBFS4); + VpnProfile profile = createProfile(configGenerator, OBFS4); assertEquals(-1, gatewaysManager.getPosition(profile)); } @@ -199,7 +216,7 @@ public class GatewaysManagerTest { configuration.apiVersion = 3; configuration.remoteGatewayIP = "3.21.247.89"; VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, configuration); - VpnProfile profile = configGenerator.createProfile(OBFS4); + VpnProfile profile = createProfile(configGenerator, OBFS4); assertEquals(1, gatewaysManager.getPosition(profile)); } @@ -212,7 +229,7 @@ public class GatewaysManagerTest { sharedPreferences.edit().putBoolean(USE_BRIDGES, true).commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("37.12.247.10", gatewaysManager.select(0).gateway.getRemoteIP()); + assertEquals("37.12.247.10", gatewaysManager.selectVpnProfile(0).mGatewayIp); } @Test @@ -226,11 +243,11 @@ public class GatewaysManagerTest { commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); ArrayList<String> hosts = new ArrayList<>(); - hosts.add(gatewaysManager.select(0).gateway.getHost()); - hosts.add(gatewaysManager.select(1).gateway.getHost()); + hosts.add(gatewaysManager.selectVpnProfile(0).mGatewayIp); + hosts.add(gatewaysManager.selectVpnProfile(1).mGatewayIp); - assertTrue(hosts.contains("bridge-nyc1-02.bitmask-dev.leapvpn.net")); - assertTrue(hosts.contains("bridge-nyc1-01.bitmask-dev.leapvpn.net")); + assertTrue(hosts.contains("192.81.208.164")); + assertTrue(hosts.contains("104.248.232.240")); } @@ -246,10 +263,10 @@ public class GatewaysManagerTest { GatewaysManager gatewaysManager = new GatewaysManager(mockContext); ArrayList<String> hosts = new ArrayList<>(); - hosts.add(gatewaysManager.select(0).gateway.getHost()); - hosts.add(gatewaysManager.select(1).gateway.getHost()); - assertTrue(hosts.contains("bridge-nyc1-02.bitmask-dev.leapvpn.net")); - assertTrue(hosts.contains("bridge-nyc1-01.bitmask-dev.leapvpn.net")); + hosts.add(gatewaysManager.selectVpnProfile(0).mGatewayIp); + hosts.add(gatewaysManager.selectVpnProfile(1).mGatewayIp); + assertTrue(hosts.contains("192.81.208.164")); + assertTrue(hosts.contains("104.248.232.240")); } @Test @@ -264,7 +281,7 @@ public class GatewaysManagerTest { for (int i = 0; i < 1000; i++) { GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("bridge-nyc1-01.bitmask-dev.leapvpn.net", gatewaysManager.select(0).gateway.getHost()); + assertEquals("104.248.232.240", gatewaysManager.selectVpnProfile(0).mGatewayIp); } } @@ -279,8 +296,8 @@ public class GatewaysManagerTest { commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("bridge-nyc1-01.bitmask-dev.leapvpn.net", gatewaysManager.select(0).gateway.getHost()); - assertNull(gatewaysManager.select(1)); + assertEquals("104.248.232.240", gatewaysManager.selectVpnProfile(0).mGatewayIp); + assertNull(gatewaysManager.selectVpnProfile(1)); } @Test @@ -295,11 +312,11 @@ public class GatewaysManagerTest { GatewaysManager gatewaysManager = new GatewaysManager(mockContext); ArrayList<String> hosts = new ArrayList<>(); - hosts.add(gatewaysManager.select(0).gateway.getHost()); - hosts.add(gatewaysManager.select(1).gateway.getHost()); + hosts.add(gatewaysManager.selectVpnProfile(0).mGatewayIp); + hosts.add(gatewaysManager.selectVpnProfile(1).mGatewayIp); - assertTrue(hosts.contains("pt.demo.bitmask.net")); - assertTrue(hosts.contains("manila.bitmask.net")); + assertTrue(hosts.contains("37.218.247.60")); + assertTrue(hosts.contains("37.12.247.10")); } @Test @@ -309,9 +326,9 @@ public class GatewaysManagerTest { providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("manila.bitmask.net", gatewaysManager.select(0).gateway.getHost()); - assertEquals("moscow.bitmask.net", gatewaysManager.select(1).gateway.getHost()); - assertEquals("pt.demo.bitmask.net", gatewaysManager.select(2).gateway.getHost()); + assertEquals("37.12.247.10", gatewaysManager.selectVpnProfile(0).mGatewayIp); + assertEquals("3.21.247.89", gatewaysManager.selectVpnProfile(1).mGatewayIp); + assertEquals("37.218.247.60", gatewaysManager.selectVpnProfile(2).mGatewayIp); } @Test @@ -325,9 +342,9 @@ public class GatewaysManagerTest { commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("moscow.bitmask.net", gatewaysManager.select(0).gateway.getHost()); - assertEquals("pt.demo.bitmask.net", gatewaysManager.select(1).gateway.getHost()); - assertNull(gatewaysManager.select(2)); + assertEquals("3.21.247.89", gatewaysManager.selectVpnProfile(0).mGatewayIp); + assertEquals("37.218.247.60", gatewaysManager.selectVpnProfile(1).mGatewayIp); + assertNull(gatewaysManager.selectVpnProfile(2)); } @@ -342,9 +359,9 @@ public class GatewaysManagerTest { commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("mouette.riseup.net", gatewaysManager.select(0).gateway.getHost()); - assertEquals("hoatzin.riseup.net", gatewaysManager.select(1).gateway.getHost()); - assertEquals("zarapito.riseup.net", gatewaysManager.select(2).gateway.getHost()); + assertEquals("163.172.126.44", gatewaysManager.selectVpnProfile(0).mGatewayIp); + assertEquals("212.83.143.67", gatewaysManager.selectVpnProfile(1).mGatewayIp); + assertEquals("212.129.62.247", gatewaysManager.selectVpnProfile(2).mGatewayIp); } @Test @@ -358,9 +375,9 @@ public class GatewaysManagerTest { commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("mouette.riseup.net", gatewaysManager.select(0).gateway.getHost()); - assertEquals("hoatzin.riseup.net", gatewaysManager.select(1).gateway.getHost()); - assertEquals("zarapito.riseup.net", gatewaysManager.select(2).gateway.getHost()); + assertEquals("163.172.126.44", gatewaysManager.selectVpnProfile(0).mGatewayIp); + assertEquals("212.83.143.67", gatewaysManager.selectVpnProfile(1).mGatewayIp); + assertEquals("212.129.62.247", gatewaysManager.selectVpnProfile(2).mGatewayIp); } @Test @@ -375,10 +392,10 @@ public class GatewaysManagerTest { commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("Paris", gatewaysManager.select(0).gateway.getName()); - assertEquals("Paris", gatewaysManager.select(1).gateway.getName()); - assertEquals("Paris", gatewaysManager.select(2).gateway.getName()); - assertEquals(null, gatewaysManager.select(3)); + assertEquals("Paris", gatewaysManager.selectVpnProfile(0).getName()); + assertEquals("Paris", gatewaysManager.selectVpnProfile(1).getName()); + assertEquals("Paris", gatewaysManager.selectVpnProfile(2).getName()); + assertEquals(null, gatewaysManager.selectVpnProfile(3)); } @Test @@ -388,9 +405,9 @@ public class GatewaysManagerTest { providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("mouette.riseup.net", gatewaysManager.select(0, "Paris").gateway.getHost()); - assertEquals("hoatzin.riseup.net", gatewaysManager.select(1, "Paris").gateway.getHost()); - assertEquals("zarapito.riseup.net", gatewaysManager.select(2, "Paris").gateway.getHost()); + assertEquals("163.172.126.44", gatewaysManager.selectVpnProfile(0, "Paris").mGatewayIp); + assertEquals("212.83.143.67", gatewaysManager.selectVpnProfile(1, "Paris").mGatewayIp); + assertEquals("212.129.62.247", gatewaysManager.selectVpnProfile(2, "Paris").mGatewayIp); } @Test @@ -400,9 +417,9 @@ public class GatewaysManagerTest { providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("mouette.riseup.net", gatewaysManager.select(0, "Paris").gateway.getHost()); - assertEquals("hoatzin.riseup.net", gatewaysManager.select(1, "Paris").gateway.getHost()); - assertEquals("zarapito.riseup.net", gatewaysManager.select(2, "Paris").gateway.getHost()); + assertEquals("163.172.126.44", gatewaysManager.selectVpnProfile(0, "Paris").mGatewayIp); + assertEquals("212.83.143.67", gatewaysManager.selectVpnProfile(1, "Paris").mGatewayIp); + assertEquals("212.129.62.247", gatewaysManager.selectVpnProfile(2, "Paris").mGatewayIp); } @Test @@ -413,10 +430,10 @@ public class GatewaysManagerTest { providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("Paris", gatewaysManager.select(0, "Paris").gateway.getName()); - assertEquals("Paris", gatewaysManager.select(1, "Paris").gateway.getName()); - assertEquals("Paris", gatewaysManager.select(2, "Paris").gateway.getName()); - assertEquals(null, gatewaysManager.select(3, "Paris")); + assertEquals("Paris", gatewaysManager.selectVpnProfile(0, "Paris").getName()); + assertEquals("Paris", gatewaysManager.selectVpnProfile(1, "Paris").getName()); + assertEquals("Paris", gatewaysManager.selectVpnProfile(2, "Paris").getName()); + assertEquals(null, gatewaysManager.selectVpnProfile(3, "Paris")); } @Test @@ -426,7 +443,7 @@ public class GatewaysManagerTest { provider.setGeoIpJson(new JSONObject()); providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertNull(gatewaysManager.select(0, "Stockholm")); + assertNull(gatewaysManager.selectVpnProfile(0, "Stockholm")); } @Test diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java index 547bb3df..5343c466 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java @@ -19,6 +19,7 @@ import org.junit.Test; import java.io.File; import java.util.HashMap; +import java.util.Vector; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConfigParser; @@ -1353,15 +1354,33 @@ public class VpnConfigGeneratorTest { when(context.getCacheDir()).thenReturn(new File("/data/data/se.leap.bitmask")); } + private static boolean containsKey(Vector<VpnProfile> profiles, Connection.TransportType transportType) { + for (VpnProfile profile : profiles) { + if (profile.getTransportType() == transportType) { + return true; + } + } + return false; + } + + private static VpnProfile getVpnProfile(Vector<VpnProfile> profiles, Connection.TransportType transportType) { + for (VpnProfile profile : profiles) { + if (profile.getTransportType() == transportType) { + return profile; + } + } + return null; + } + @Test public void testGenerateVpnProfile_v1_tcp_udp() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("gateway_tcp_udp.json"))); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 1; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertFalse(vpnProfiles.containsKey(OBFS4)); - assertEquals(expectedVPNConfig_v1_tcp_udp.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertFalse(containsKey(vpnProfiles, OBFS4)); + assertEquals(expectedVPNConfig_v1_tcp_udp.trim(), getVpnProfile(vpnProfiles, OPENVPN).getConfigFile(context, false).trim()); } @Test @@ -1370,9 +1389,9 @@ public class VpnConfigGeneratorTest { VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 1; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertFalse(vpnProfiles.containsKey(OBFS4)); - assertEquals(expectedVPNConfig_v1_udp_tcp.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertFalse(containsKey(vpnProfiles, OBFS4)); + assertEquals(expectedVPNConfig_v1_udp_tcp.trim(), getVpnProfile(vpnProfiles, OPENVPN).getConfigFile(context, false).trim()); } @Test @@ -1381,9 +1400,9 @@ public class VpnConfigGeneratorTest { VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 2; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertFalse(vpnProfiles.containsKey(OBFS4)); - assertEquals(expectedVPNConfig_v1_tcp_udp.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertFalse(containsKey(vpnProfiles, OBFS4)); + assertEquals(expectedVPNConfig_v1_tcp_udp.trim(), getVpnProfile(vpnProfiles, OPENVPN).getConfigFile(context, false).trim()); } @Test @@ -1392,9 +1411,9 @@ public class VpnConfigGeneratorTest { VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 2; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertFalse(vpnProfiles.containsKey(OBFS4)); - assertEquals(expectedVPNConfig_v1_udp_tcp.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertFalse(containsKey(vpnProfiles, OBFS4)); + assertEquals(expectedVPNConfig_v1_udp_tcp.trim(), getVpnProfile(vpnProfiles, OPENVPN).getConfigFile(context, false).trim()); } @@ -1405,11 +1424,11 @@ public class VpnConfigGeneratorTest { VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 3; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertTrue(vpnProfiles.containsKey(OBFS4)); - assertTrue(vpnProfiles.containsKey(OPENVPN)); - System.out.println(vpnProfiles.get(OBFS4).getConfigFile(context, false)); - assertEquals(expectedVPNConfig_v3_obfs4.trim(), vpnProfiles.get(OBFS4).getConfigFile(context, false).trim()); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(containsKey(vpnProfiles, OBFS4)); + assertTrue(containsKey(vpnProfiles, OPENVPN)); + System.out.println(getVpnProfile(vpnProfiles, OBFS4).getConfigFile(context, false)); + assertEquals(expectedVPNConfig_v3_obfs4.trim(), getVpnProfile(vpnProfiles, OBFS4).getConfigFile(context, false).trim()); } @Test @@ -1419,11 +1438,11 @@ public class VpnConfigGeneratorTest { VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 3; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertTrue(vpnProfiles.containsKey(OBFS4)); - assertTrue(vpnProfiles.containsKey(OPENVPN)); - System.out.println(vpnProfiles.get(OBFS4).getConfigFile(context, false)); - assertEquals(expectedVPNConfig_v3_obfsvpn_obfs4.trim(), vpnProfiles.get(OBFS4).getConfigFile(context, false).trim()); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(containsKey(vpnProfiles, OBFS4)); + assertTrue(containsKey(vpnProfiles, OPENVPN)); + System.out.println(getVpnProfile(vpnProfiles, OBFS4).getConfigFile(context, false)); + assertEquals(expectedVPNConfig_v3_obfsvpn_obfs4.trim(), getVpnProfile(vpnProfiles, OBFS4).getConfigFile(context, false).trim()); } @Test @@ -1432,11 +1451,11 @@ public class VpnConfigGeneratorTest { VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 3; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertTrue(vpnProfiles.containsKey(OBFS4)); - assertTrue(vpnProfiles.containsKey(OPENVPN)); - System.out.println(vpnProfiles.get(OPENVPN).getConfigFile(context, false)); - assertEquals(expectedVPNConfig_v3_ovpn_tcp_udp.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(containsKey(vpnProfiles, OBFS4)); + assertTrue(containsKey(vpnProfiles, OPENVPN)); + System.out.println(getVpnProfile(vpnProfiles, OPENVPN).getConfigFile(context, false)); + assertEquals(expectedVPNConfig_v3_ovpn_tcp_udp.trim(), getVpnProfile(vpnProfiles, OPENVPN).getConfigFile(context, false).trim()); } @Test @@ -1445,11 +1464,11 @@ public class VpnConfigGeneratorTest { VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 3; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertTrue(vpnProfiles.containsKey(OBFS4)); - assertTrue(vpnProfiles.containsKey(OPENVPN)); - System.out.println(vpnProfiles.get(OPENVPN).getConfigFile(context, false)); - assertEquals(expectedVPNConfig_v3_ovpn_udp_tcp.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(containsKey(vpnProfiles, OBFS4)); + assertTrue(containsKey(vpnProfiles, OPENVPN)); + System.out.println(getVpnProfile(vpnProfiles, OPENVPN).getConfigFile(context, false)); + assertEquals(expectedVPNConfig_v3_ovpn_udp_tcp.trim(), getVpnProfile(vpnProfiles, OPENVPN).getConfigFile(context, false).trim()); } @Test @@ -1460,11 +1479,11 @@ public class VpnConfigGeneratorTest { VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 3; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertTrue(vpnProfiles.containsKey(OBFS4)); - assertTrue(vpnProfiles.containsKey(OPENVPN)); - System.out.println(vpnProfiles.get(OPENVPN).getConfigFile(context, false)); - assertEquals(expectedVPNConfig_v3_ovpn_udp_tcp_defaultDataCiphers.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(containsKey(vpnProfiles, OBFS4)); + assertTrue(containsKey(vpnProfiles, OPENVPN)); + System.out.println(getVpnProfile(vpnProfiles, OPENVPN).getConfigFile(context, false)); + assertEquals(expectedVPNConfig_v3_ovpn_udp_tcp_defaultDataCiphers.trim(), getVpnProfile(vpnProfiles, OPENVPN).getConfigFile(context, false).trim()); } @Test @@ -1474,11 +1493,11 @@ public class VpnConfigGeneratorTest { VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 4; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertTrue(vpnProfiles.containsKey(OBFS4)); - assertTrue(vpnProfiles.containsKey(OPENVPN)); - System.out.println(vpnProfiles.get(OPENVPN).getConfigFile(context, false)); - assertEquals(expectedVPNConfig_v4_ovpn_tcp_udp.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(containsKey(vpnProfiles, OBFS4)); + assertTrue(containsKey(vpnProfiles, OPENVPN)); + System.out.println(getVpnProfile(vpnProfiles, OPENVPN).getConfigFile(context, false)); + assertEquals(expectedVPNConfig_v4_ovpn_tcp_udp.trim(), getVpnProfile(vpnProfiles, OPENVPN).getConfigFile(context, false).trim()); } @Test @@ -1488,11 +1507,11 @@ public class VpnConfigGeneratorTest { VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 4; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertTrue(vpnProfiles.containsKey(OBFS4)); - assertTrue(vpnProfiles.containsKey(OPENVPN)); - System.out.println(vpnProfiles.get(OPENVPN).getConfigFile(context, false)); - assertEquals(expectedVPNConfig_v4_ovpn_udp_tcp.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(containsKey(vpnProfiles, OBFS4)); + assertTrue(containsKey(vpnProfiles, OPENVPN)); + System.out.println(getVpnProfile(vpnProfiles, OPENVPN).getConfigFile(context, false)); + assertEquals(expectedVPNConfig_v4_ovpn_udp_tcp.trim(), getVpnProfile(vpnProfiles, OPENVPN).getConfigFile(context, false).trim()); } @Test @@ -1502,8 +1521,8 @@ public class VpnConfigGeneratorTest { VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 3; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertTrue(vpnProfiles.containsKey(OPENVPN)); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(containsKey(vpnProfiles, OPENVPN)); } @Test @@ -1513,8 +1532,8 @@ public class VpnConfigGeneratorTest { VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 3; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertFalse(vpnProfiles.containsKey(OBFS4)); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertFalse(containsKey(vpnProfiles, OBFS4)); } /** @@ -1527,11 +1546,11 @@ public class VpnConfigGeneratorTest { VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 3; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertTrue(vpnProfiles.containsKey(OBFS4)); - assertTrue(vpnProfiles.containsKey(OPENVPN)); - assertEquals(1, vpnProfiles.get(OBFS4).mConnections.length); - assertEquals("37.218.247.60/32", vpnProfiles.get(OBFS4).mExcludedRoutes.trim()); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(containsKey(vpnProfiles, OBFS4)); + assertTrue(containsKey(vpnProfiles, OPENVPN)); + assertEquals(1, getVpnProfile(vpnProfiles, OBFS4).mConnections.length); + assertEquals("37.218.247.60/32", getVpnProfile(vpnProfiles, OBFS4).mExcludedRoutes.trim()); } /** @@ -1544,9 +1563,9 @@ public class VpnConfigGeneratorTest { VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 3; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertFalse(vpnProfiles.containsKey(OBFS4)); - assertTrue(vpnProfiles.containsKey(OPENVPN)); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertFalse(containsKey(vpnProfiles, OBFS4)); + assertTrue(containsKey(vpnProfiles, OPENVPN)); } /** @@ -1559,9 +1578,9 @@ public class VpnConfigGeneratorTest { VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 3; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertFalse(vpnProfiles.containsKey(OBFS4)); - assertTrue(vpnProfiles.containsKey(OPENVPN)); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertFalse(containsKey(vpnProfiles, OBFS4)); + assertTrue(containsKey(vpnProfiles, OPENVPN)); } @Test @@ -1571,10 +1590,10 @@ public class VpnConfigGeneratorTest { VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 3; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertTrue(vpnProfiles.containsKey(OBFS4)); - assertTrue(vpnProfiles.containsKey(OPENVPN)); - assertEquals(1, vpnProfiles.get(OBFS4).mConnections.length); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(containsKey(vpnProfiles, OBFS4)); + assertTrue(containsKey(vpnProfiles, OPENVPN)); + assertEquals(1, getVpnProfile(vpnProfiles, OBFS4).mConnections.length); } @Test @@ -1585,11 +1604,11 @@ public class VpnConfigGeneratorTest { configuration.apiVersion = 3; configuration.preferUDP = true; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertTrue(vpnProfiles.containsKey(OBFS4)); - assertTrue(vpnProfiles.containsKey(OPENVPN)); - System.out.println(vpnProfiles.get(OPENVPN).getConfigFile(context, false)); - assertEquals(expectedVPNConfig_v4_ovpn_multiport_tcpudp.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(containsKey(vpnProfiles, OBFS4)); + assertTrue(containsKey(vpnProfiles, OPENVPN)); + System.out.println(getVpnProfile(vpnProfiles, OPENVPN).getConfigFile(context, false)); + assertEquals(expectedVPNConfig_v4_ovpn_multiport_tcpudp.trim(), getVpnProfile(vpnProfiles, OPENVPN).getConfigFile(context, false).trim()); } @Test @@ -1599,9 +1618,9 @@ public class VpnConfigGeneratorTest { VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 4; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - System.out.println(vpnProfiles.get(OPENVPN).getConfigFile(context, false)); - assertEquals(expectedVPNConfig_v4_ovpn_tcp_udp_new_ciphers.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + System.out.println(getVpnProfile(vpnProfiles, OPENVPN).getConfigFile(context, false)); + assertEquals(expectedVPNConfig_v4_ovpn_tcp_udp_new_ciphers.trim(), getVpnProfile(vpnProfiles, OPENVPN).getConfigFile(context, false).trim()); } @Test @@ -1613,9 +1632,9 @@ public class VpnConfigGeneratorTest { configuration.experimentalTransports = true; configuration.preferUDP = true; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertTrue(vpnProfiles.containsKey(OBFS4) && ((Obfs4Connection)vpnProfiles.get(OBFS4).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("kcp")); - assertTrue(vpnProfiles.containsKey(OPENVPN)); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(containsKey(vpnProfiles, OBFS4) && ((Obfs4Connection)getVpnProfile(vpnProfiles, OBFS4).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("kcp")); + assertTrue(containsKey(vpnProfiles, OPENVPN)); } @Test @@ -1626,9 +1645,9 @@ public class VpnConfigGeneratorTest { configuration.apiVersion = 3; configuration.experimentalTransports = true; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertFalse(vpnProfiles.containsKey(OBFS4)); - assertTrue(vpnProfiles.containsKey(OPENVPN)); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertFalse(containsKey(vpnProfiles, OBFS4)); + assertTrue(containsKey(vpnProfiles, OPENVPN)); } @Test @@ -1644,10 +1663,10 @@ public class VpnConfigGeneratorTest { configuration.obfuscationProxyKCP = true; configuration.remoteGatewayIP = "1.2.3.4"; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertTrue("has openvpn profile", vpnProfiles.containsKey(OPENVPN)); - assertTrue("has obfs4 profile", vpnProfiles.containsKey(OBFS4)); - assertTrue("bridge is running KCP", vpnProfiles.get(OBFS4).mGatewayIp.equals("1.2.3.4")); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue("has openvpn profile", containsKey(vpnProfiles, OPENVPN)); + assertTrue("has obfs4 profile", containsKey(vpnProfiles, OBFS4)); + assertTrue("bridge is running KCP", getVpnProfile(vpnProfiles, OBFS4).mGatewayIp.equals("1.2.3.4")); } @@ -1664,11 +1683,11 @@ public class VpnConfigGeneratorTest { configuration.obfuscationProxyCert = "asdfasdf"; configuration.remoteGatewayIP = "1.2.3.4"; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertFalse("has openvpn profile", vpnProfiles.containsKey(OPENVPN)); - assertTrue("has obfs4 profile", vpnProfiles.containsKey(OBFS4)); - assertTrue("bridge is pinned one", vpnProfiles.get(OBFS4).getTransportType() == OBFS4 && vpnProfiles.get(OBFS4).mConnections[0].isUseUdp()); - assertTrue("bridge is running TCP", ((Obfs4Connection) vpnProfiles.get(OBFS4).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp")); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertFalse("has openvpn profile", containsKey(vpnProfiles, OPENVPN)); + assertTrue("has obfs4 profile", containsKey(vpnProfiles, OBFS4)); + assertTrue("bridge is pinned one", getVpnProfile(vpnProfiles, OBFS4).getTransportType() == OBFS4 && getVpnProfile(vpnProfiles, OBFS4).mConnections[0].isUseUdp()); + assertTrue("bridge is running TCP", ((Obfs4Connection) getVpnProfile(vpnProfiles, OBFS4).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp")); } @Test @@ -1685,11 +1704,11 @@ public class VpnConfigGeneratorTest { configuration.remoteGatewayIP = "1.2.3.4"; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertFalse("has openvpn profile", vpnProfiles.containsKey(OPENVPN)); - assertTrue("has no obfs4 profile", vpnProfiles.containsKey(OBFS4)); - assertTrue("bridge is pinned one", vpnProfiles.get(OBFS4).getTransportType() == OBFS4 && vpnProfiles.get(OBFS4).mGatewayIp.equals("1.2.3.4")); - assertTrue("bridge is running KCP", ((Obfs4Connection) vpnProfiles.get(OBFS4).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("kcp")); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertFalse("has openvpn profile", containsKey(vpnProfiles, OPENVPN)); + assertTrue("has no obfs4 profile", containsKey(vpnProfiles, OBFS4)); + assertTrue("bridge is pinned one", getVpnProfile(vpnProfiles, OBFS4).getTransportType() == OBFS4 && getVpnProfile(vpnProfiles, OBFS4).mGatewayIp.equals("1.2.3.4")); + assertTrue("bridge is running KCP", ((Obfs4Connection) getVpnProfile(vpnProfiles, OBFS4).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("kcp")); } @Test public void testGenerateVpnProfile_obfs4hop_tcp () throws Exception { @@ -1699,9 +1718,9 @@ public class VpnConfigGeneratorTest { configuration.apiVersion = 3; configuration.experimentalTransports = true; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertTrue(vpnProfiles.containsKey(OBFS4_HOP) && ((Obfs4Connection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp")); - assertTrue(vpnProfiles.containsKey(OPENVPN)); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(containsKey(vpnProfiles, OBFS4_HOP) && ((Obfs4Connection)getVpnProfile(vpnProfiles, OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp")); + assertTrue(containsKey(vpnProfiles, OPENVPN)); } @Test @@ -1712,9 +1731,9 @@ public class VpnConfigGeneratorTest { configuration.apiVersion = 3; configuration.experimentalTransports = true; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertTrue(vpnProfiles.containsKey(OBFS4_HOP) && ((Obfs4Connection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("kcp")); - assertTrue(vpnProfiles.containsKey(OPENVPN)); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(containsKey(vpnProfiles, OBFS4_HOP) && ((Obfs4Connection)getVpnProfile(vpnProfiles, OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("kcp")); + assertTrue(containsKey(vpnProfiles, OPENVPN)); } @Test @@ -1726,9 +1745,9 @@ public class VpnConfigGeneratorTest { configuration.apiVersion = 3; configuration.experimentalTransports = true; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - System.out.println(vpnProfiles.get(OBFS4_HOP).getConfigFile(context, false)); - assertEquals(expectedVPNConfig_hopping_pt_portHopping.trim(), vpnProfiles.get(OBFS4_HOP).getConfigFile(context, false).trim()); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + System.out.println(getVpnProfile(vpnProfiles, OBFS4_HOP).getConfigFile(context, false)); + assertEquals(expectedVPNConfig_hopping_pt_portHopping.trim(), getVpnProfile(vpnProfiles, OBFS4_HOP).getConfigFile(context, false).trim()); } @Test @@ -1740,9 +1759,9 @@ public class VpnConfigGeneratorTest { configuration.apiVersion = 3; configuration.experimentalTransports = true; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - System.out.println(vpnProfiles.get(OBFS4_HOP).getConfigFile(context, false)); - assertEquals(expectedVPNConfig_hopping_pt_portHopping.trim(), vpnProfiles.get(OBFS4_HOP).getConfigFile(context, false).trim()); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + System.out.println(getVpnProfile(vpnProfiles, OBFS4_HOP).getConfigFile(context, false)); + assertEquals(expectedVPNConfig_hopping_pt_portHopping.trim(), getVpnProfile(vpnProfiles, OBFS4_HOP).getConfigFile(context, false).trim()); } @Test public void testGenerateVpnProfile_obfs4_decoupled() throws Exception { @@ -1753,10 +1772,10 @@ public class VpnConfigGeneratorTest { configuration.apiVersion = 3; configuration.experimentalTransports = true; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertTrue(vpnProfiles.containsKey(OBFS4)); - assertTrue(((Obfs4Connection)vpnProfiles.get(OBFS4).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp")); - assertFalse(vpnProfiles.containsKey(OPENVPN)); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(containsKey(vpnProfiles, OBFS4)); + assertTrue(((Obfs4Connection)getVpnProfile(vpnProfiles, OBFS4).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp")); + assertFalse(containsKey(vpnProfiles, OPENVPN)); } @Test @@ -1768,11 +1787,11 @@ public class VpnConfigGeneratorTest { configuration.apiVersion = 3; configuration.experimentalTransports = true; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertTrue(vpnProfiles.containsKey(OBFS4_HOP)); - assertTrue(((Obfs4Connection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp")); - assertFalse(vpnProfiles.containsKey(OPENVPN)); - assertFalse(vpnProfiles.containsKey(OBFS4)); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(containsKey(vpnProfiles, OBFS4_HOP)); + assertTrue(((Obfs4Connection)getVpnProfile(vpnProfiles, OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp")); + assertFalse(containsKey(vpnProfiles, OPENVPN)); + assertFalse(containsKey(vpnProfiles, OBFS4)); } @Test @@ -1802,10 +1821,10 @@ public class VpnConfigGeneratorTest { configuration.apiVersion = 3; configuration.experimentalTransports = true; vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); - HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); - assertTrue(vpnProfiles.containsKey(OBFS4_HOP)); - assertTrue(((Obfs4Connection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp")); - assertFalse(vpnProfiles.containsKey(OPENVPN)); - assertFalse(vpnProfiles.containsKey(OBFS4)); + Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(containsKey(vpnProfiles, OBFS4_HOP)); + assertTrue(((Obfs4Connection)getVpnProfile(vpnProfiles, OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp")); + assertFalse(containsKey(vpnProfiles, OPENVPN)); + assertFalse(containsKey(vpnProfiles, OBFS4)); } }
\ No newline at end of file diff --git a/app/src/test/resources/multiple_pts_per_host_eip-service.json b/app/src/test/resources/multiple_pts_per_host_eip-service.json new file mode 100644 index 00000000..2bd053d8 --- /dev/null +++ b/app/src/test/resources/multiple_pts_per_host_eip-service.json @@ -0,0 +1,132 @@ +{ + "gateways":[ + { + "capabilities":{ + "adblock":false, + "filter_dns":false, + "limited":false, + "transport":[ + { + "ports":[ + "80" + ], + "protocols":[ + "tcp", + "udp" + ], + "type":"openvpn" + }, + { + "options":{ + "cert":"XXXX", + "iatMode":"0" + }, + "ports":[ + "443" + ], + "protocols":[ + "tcp" + ], + "type":"obfs4" + }, + { + "options":{ + "cert":"XXXX", + "iatMode":"0" + }, + "ports":[ + "4431" + ], + "protocols":[ + "kcp" + ], + "type":"obfs4" + } + ] + }, + "host":"cod.demo.bitmask.net", + "ip_address":"37.218.245.94", + "location":"North Brabant" + }, + { + "capabilities":{ + "adblock":false, + "filter_dns":false, + "limited":false, + "transport":[ + { + "ports":[ + "80" + ], + "protocols":[ + "tcp", + "udp" + ], + "type":"openvpn" + }, + { + "options":{ + "cert":"XXXX", + "iatMode":"0" + }, + "ports":[ + "443" + ], + "protocols":[ + "udp" + ], + "type":"obfs4" + }, + { + "options":{ + "cert":"XXXX", + "iatMode":"0" + }, + "ports":[ + "4431" + ], + "protocols":[ + "kcp" + ], + "type":"obfs4" + } + ] + }, + "host":"mullet.demo.bitmask.net", + "ip_address":"37.218.241.208", + "location":"Florida" + } + ], + "locations":{ + "Florida":{ + "country_code":"US", + "hemisphere":"N", + "name":"United States", + "timezone":"-6" + }, + "North Brabant":{ + "country_code":"NL", + "hemisphere":"N", + "name":"Netherlands", + "timezone":"+2" + } + }, + "openvpn_configuration":{ + "auth":"SHA512", + "cipher":"AES-256-GCM", + "data-ciphers":"AES-256-GCM", + "dev":"tun", + "float":"", + "keepalive":"10 30", + "key-direction":"1", + "nobind":true, + "persist-key":true, + "rcvbuf":"0", + "sndbuf":"0", + "tls-cipher":"TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", + "tls-version-min":"1.2", + "verb":"3" + }, + "serial":3, + "version":3 +}
\ No newline at end of file |