diff options
14 files changed, 185 insertions, 147 deletions
diff --git a/app/build.gradle b/app/build.gradle index 8a6f08dd..7eec00b0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -51,9 +51,8 @@ android { buildConfigField 'boolean', 'use_obfsvpn', 'true' // obfsvpn Debugging config fields to pin and configure a particular proxy buildConfigField "String", "obfsvpn_port", '"443"' - buildConfigField "String", "obfsvpn_ip", '"163.172.58.132"' - buildConfigField "String", "obfsvpn_cert", '"/ntRNI6JYP7R6kGKldibKWj0aCsv96Hdu/jSGncPy+rcverCLI7Emod+vRkz61hM7F/udA"' - buildConfigField "String", "obfsvpn_gateway_host", '"vpn03-par.float.hexacab.org"' + buildConfigField "String", "obfsvpn_ip", '"159.223.173.205"' + buildConfigField "String", "obfsvpn_cert", '"8nuAbPJwFrKc/29KcCfL5LBuEWxQrjBASYXdUbwcm9d9pKseGK4r2Tg47e23+t6WghxGGw"' buildConfigField 'boolean', 'obfsvpn_use_kcp', 'false' // static update url pointing to the latest stable release apk @@ -151,7 +150,6 @@ android { buildConfigField "String", "obfsvpn_port", '""' buildConfigField "String", "obfsvpn_ip", '""' buildConfigField "String", "obfsvpn_cert", '""' - buildConfigField "String", "obfsvpn_gateway_host", '""' buildConfigField 'boolean', 'obfsvpn_use_kcp', 'false' //Build Config Fields for automatic apk update checks diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java index d993a119..ded62fa6 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java @@ -467,7 +467,7 @@ public class EipFragment extends Fragment implements Observer { setMainButtonEnabled(true); mainButton.updateState(true, false, false); Connection.TransportType transportType = PreferenceHelper.getUseBridges(getContext()) ? Connection.TransportType.OBFS4 : Connection.TransportType.OPENVPN; - locationButton.setLocationLoad(gatewaysManager.getLoadForLocation(VpnStatus.getLastConnectedVpnName(), transportType)); + locationButton.setLocationLoad(PreferenceHelper.useObfuscationPinning(getContext()) ? GatewaysManager.Load.UNKNOWN : gatewaysManager.getLoadForLocation(VpnStatus.getLastConnectedVpnName(), transportType)); locationButton.setText(VpnStatus.getLastConnectedVpnName()); locationButton.showBridgeIndicator(VpnStatus.isUsingBridges()); locationButton.showRecommendedIndicator(getPreferredCity(getContext())== null); diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java index df78214d..6829d9f1 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java @@ -31,12 +31,10 @@ public class ObfuscationProxyDialog extends AppCompatDialogFragment { AppCompatEditText ipField; AppCompatEditText portField; AppCompatEditText certificateField; - AppCompatSpinner gatewayHost; AppCompatButton saveButton; AppCompatButton useDefaultsButton; AppCompatButton cancelButton; IconSwitchEntry kcpSwitch; - ArrayAdapter<String> gatewayHosts; @NonNull @Override @@ -49,7 +47,6 @@ public class ObfuscationProxyDialog extends AppCompatDialogFragment { ipField = binding.ipField; portField = binding.portField; certificateField = binding.certField; - gatewayHost = binding.gatewayHost; saveButton = binding.buttonSave; useDefaultsButton = binding.buttonDefaults; cancelButton = binding.buttonCancel; @@ -61,16 +58,6 @@ public class ObfuscationProxyDialog extends AppCompatDialogFragment { kcpSwitch.setChecked(PreferenceHelper.getObfuscationPinningKCP(getContext())); GatewaysManager gatewaysManager = new GatewaysManager(getContext()); - ArrayList<String> hostsList = gatewaysManager.getHosts(); - - hostsList.add(0, "Select a Gateway"); - gatewayHosts = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_item, hostsList); - gatewayHosts.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - gatewayHost.setAdapter(gatewayHosts); - String selectedHost = PreferenceHelper.getObfuscationPinningGatewayHost(getContext()); - if (selectedHost != null) { - gatewayHost.setSelection(gatewayHosts.getPosition(selectedHost)); - } saveButton.setOnClickListener(v -> { String ip = TextUtils.isEmpty(ipField.getText()) ? null : ipField.getText().toString(); @@ -79,12 +66,9 @@ public class ObfuscationProxyDialog extends AppCompatDialogFragment { PreferenceHelper.setObfuscationPinningPort(v.getContext(), port); String cert = TextUtils.isEmpty(certificateField.getText()) ? null : certificateField.getText().toString(); PreferenceHelper.setObfuscationPinningCert(v.getContext(), cert); - String gatewayHostName = gatewayHost.getSelectedItemPosition() == 0 ? null : gatewayHosts.getItem(gatewayHost.getSelectedItemPosition()); - PreferenceHelper.setObfuscationPinningGatewayHost(v.getContext(), gatewayHostName); - PreferenceHelper.setObfuscationPinningGatewayIP(v.getContext(), gatewaysManager.getIpForHost(gatewayHostName)); PreferenceHelper.setObfuscationPinningKCP(v.getContext(), kcpSwitch.isChecked()); - PreferenceHelper.setUseObfuscationPinning(v.getContext(), ip != null && port != null && cert != null && gatewayHostName != null); - PreferenceHelper.setObfuscationPinningGatewayLocation(v.getContext(), gatewaysManager.getLocationNameForHost(gatewayHostName)); + PreferenceHelper.setUseObfuscationPinning(v.getContext(), ip != null && port != null && cert != null); + PreferenceHelper.setObfuscationPinningGatewayLocation(v.getContext(), gatewaysManager.getLocationNameForIP(ip, v.getContext())); dismiss(); }); @@ -93,11 +77,6 @@ public class ObfuscationProxyDialog extends AppCompatDialogFragment { ipField.setText(ObfsVpnHelper.obfsvpnIP()); portField.setText(ObfsVpnHelper.obfsvpnPort()); certificateField.setText(ObfsVpnHelper.obfsvpnCert()); - int position = gatewayHosts.getPosition(ObfsVpnHelper.gatewayHost()); - if (position == -1) { - position = 0; - } - gatewayHost.setSelection(position); kcpSwitch.setChecked(ObfsVpnHelper.useKcp()); }); diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java index 8fbac35e..fd9f2a9b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java @@ -50,8 +50,6 @@ public interface Constants { String OBFUSCATION_PINNING_PORT = "obfuscation_pinning_port"; String OBFUSCATION_PINNING_CERT = "obfuscation_pinning_cert"; String OBFUSCATION_PINNING_KCP = "obfuscation_pinning_udp"; - String OBFUSCATION_PINNING_GW_HOST = "obfuscation_pinning_gw_host"; - String OBFUSCATION_PINNING_GW_IP = "obfuscation_pinning_gw_ip"; String OBFUSCATION_PINNING_LOCATION = "obfuscation_pinning_location"; diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/GatewayJson.java b/app/src/main/java/se/leap/bitmaskclient/base/models/GatewayJson.java new file mode 100644 index 00000000..8aca58c6 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/GatewayJson.java @@ -0,0 +1,61 @@ +package se.leap.bitmaskclient.base.models; + +import androidx.annotation.NonNull; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.annotations.SerializedName; + +import org.json.JSONObject; + +public class GatewayJson { + private String location; + @SerializedName(value = "ip_address") + private String ipAddress; + @SerializedName(value = "ip_address6") + private String ipAddress6; + private String host; + private Capabilities capabilities; + + public GatewayJson(String location, String ipAddress, String ipAddress6, String host, Capabilities capabilities) { + this.location = location; + this.ipAddress = ipAddress; + this.ipAddress6 = ipAddress6; + this.host = host; + this.capabilities = capabilities; + } + + @NonNull + @Override + public String toString() { + return new Gson().toJson(this); + } + + public static GatewayJson fromJson(JSONObject json) { + GsonBuilder builder = new GsonBuilder(); + return builder.create().fromJson(json.toString(), GatewayJson.class); + } + + public static class Capabilities { + private Boolean adblock; + @SerializedName(value = "filter_dns") + private Boolean filterDns; + private Boolean limited; + private Transport[] transport; + @SerializedName(value = "user_ips") + private Boolean userIps; + + public Capabilities(Boolean adblock, Boolean filterDns, Boolean limited, Transport[] transport, Boolean userIps) { + this.adblock = adblock; + this.filterDns = filterDns; + this.limited = limited; + this.transport = transport; + this.userIps = userIps; + } + @NonNull + @Override + public String toString() { + return new Gson().toJson(this); + } + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java index c4e2fb17..91894fb8 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java @@ -290,11 +290,9 @@ public class ConfigHelper { return BuildConfig.obfsvpn_ip != null && BuildConfig.obfsvpn_port != null && BuildConfig.obfsvpn_cert != null && - BuildConfig.obfsvpn_gateway_host != null && !BuildConfig.obfsvpn_ip.isEmpty() && !BuildConfig.obfsvpn_port.isEmpty() && - !BuildConfig.obfsvpn_cert.isEmpty() && - !BuildConfig.obfsvpn_gateway_host.isEmpty(); + !BuildConfig.obfsvpn_cert.isEmpty(); } public static String obfsvpnIP() { return BuildConfig.obfsvpn_ip; @@ -305,10 +303,6 @@ public class ConfigHelper { public static String obfsvpnCert() { return BuildConfig.obfsvpn_cert; } - public static String gatewayHost() { - return BuildConfig.obfsvpn_gateway_host; - } - public static boolean useKcp() { return BuildConfig.obfsvpn_use_kcp; } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java index d9beffd3..4abeed1a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java @@ -12,8 +12,6 @@ import static se.leap.bitmaskclient.base.models.Constants.GATEWAY_PINNING; import static se.leap.bitmaskclient.base.models.Constants.LAST_UPDATE_CHECK; import static se.leap.bitmaskclient.base.models.Constants.LAST_USED_PROFILE; import static se.leap.bitmaskclient.base.models.Constants.OBFUSCATION_PINNING_CERT; -import static se.leap.bitmaskclient.base.models.Constants.OBFUSCATION_PINNING_GW_HOST; -import static se.leap.bitmaskclient.base.models.Constants.OBFUSCATION_PINNING_GW_IP; import static se.leap.bitmaskclient.base.models.Constants.OBFUSCATION_PINNING_IP; import static se.leap.bitmaskclient.base.models.Constants.OBFUSCATION_PINNING_KCP; import static se.leap.bitmaskclient.base.models.Constants.OBFUSCATION_PINNING_LOCATION; @@ -279,8 +277,7 @@ public class PreferenceHelper { getBoolean(context, USE_OBFUSCATION_PINNING, false) && !TextUtils.isEmpty(getObfuscationPinningIP(context)) && !TextUtils.isEmpty(getObfuscationPinningCert(context)) && - !TextUtils.isEmpty(getObfuscationPinningPort(context)) && - !TextUtils.isEmpty(getObfuscationPinningGatewayHost(context)); + !TextUtils.isEmpty(getObfuscationPinningPort(context)); } public static void setObfuscationPinningIP(Context context, String ip) { @@ -307,23 +304,6 @@ public class PreferenceHelper { return getString(context, OBFUSCATION_PINNING_CERT, null); } - public static void setObfuscationPinningGatewayHost(Context context, String gatewayIP) { - putString(context, OBFUSCATION_PINNING_GW_HOST, gatewayIP); - } - - public static String getObfuscationPinningGatewayHost(Context context) { - return getString(context, OBFUSCATION_PINNING_GW_HOST, null); - } - - - public static void setObfuscationPinningGatewayIP(Context context, String ipForHost) { - putString(context, OBFUSCATION_PINNING_GW_IP, ipForHost); - } - - public static String getObfuscationPinningGatewayIP(Context context) { - return getString(context, OBFUSCATION_PINNING_GW_IP, null); - } - public static void setObfuscationPinningGatewayLocation(Context context, String location) { putString(context, OBFUSCATION_PINNING_LOCATION, location); } @@ -357,7 +337,7 @@ public class PreferenceHelper { } public static String getPreferredCity(Context context) { - return getString(context, PREFERRED_CITY, null); + return useObfuscationPinning(context) ? null : getString(context, PREFERRED_CITY, null); } @WorkerThread 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 ff1dd05e..929935eb 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java @@ -29,8 +29,6 @@ import static se.leap.bitmaskclient.base.models.Constants.VERSION; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.allowExperimentalTransports; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getExcludedApps; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningCert; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningGatewayHost; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningGatewayIP; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningGatewayLocation; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningIP; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningKCP; @@ -50,11 +48,11 @@ import org.json.JSONObject; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; -import java.util.Set; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConfigParser; import de.blinkt.openvpn.core.connection.Connection; +import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.utils.ConfigHelper; /** @@ -112,9 +110,9 @@ public class Gateway { config.experimentalTransports = allowExperimentalTransports(context); config.excludedApps = getExcludedApps(context); + config.remoteGatewayIP = config.useObfuscationPinning ? getObfuscationPinningIP(context) : gateway.optString(IP_ADDRESS); config.useObfuscationPinning = useObfuscationPinning(context); config.profileName = config.useObfuscationPinning ? getObfuscationPinningGatewayLocation(context) : locationAsName(eipDefinition); - config.remoteGatewayIP = config.useObfuscationPinning ? getObfuscationPinningGatewayIP(context) : gateway.optString(IP_ADDRESS); if (config.useObfuscationPinning) { config.obfuscationProxyIP = getObfuscationPinningIP(context); config.obfuscationProxyPort = getObfuscationPinningPort(context); 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 7bcd0def..521d095e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -25,10 +25,12 @@ import static se.leap.bitmaskclient.base.models.Constants.HOST; 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.Constants.SORTED_GATEWAYS; +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; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningPort; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferredCity; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseBridges; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useObfuscationPinning; import android.content.Context; import android.util.Log; @@ -56,10 +58,13 @@ import de.blinkt.openvpn.core.VpnStatus; import de.blinkt.openvpn.core.connection.Connection; import de.blinkt.openvpn.core.connection.Connection.TransportType; import se.leap.bitmaskclient.BuildConfig; +import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.base.models.GatewayJson; import se.leap.bitmaskclient.base.models.Location; import se.leap.bitmaskclient.base.models.Pair; 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; /** @@ -99,6 +104,7 @@ public class GatewaysManager { } private static final String TAG = GatewaysManager.class.getSimpleName(); + public static final String PINNED_OBFUSCATION_PROXY = "pinned.obfuscation.proxy"; private final Context context; private final LinkedHashMap<String, Gateway> gateways = new LinkedHashMap<>(); @@ -118,7 +124,11 @@ public class GatewaysManager { */ public Pair<Gateway, TransportType> select(int nClosest) { if (PreferenceHelper.useObfuscationPinning(context)) { - Gateway gateway = gateways.get(PreferenceHelper.getObfuscationPinningGatewayHost(context)); + if (nClosest > 2) { + // no need to try again the pinned proxy, probably configuration error + return null; + } + Gateway gateway = gateways.get(PINNED_OBFUSCATION_PROXY); if (gateway == null) { return null; } @@ -228,12 +238,13 @@ public class GatewaysManager { } } - public String getLocationNameForHost(String name) { - Gateway gateway = gateways.get(name); - if (gateway != null) { - return gateway.getName(); + public String getLocationNameForIP(String ip, Context context) { + for (Gateway gateway : gateways.values()) { + if (gateway.getRemoteIP().equals(ip)) { + return gateway.getName(); + } } - return "Unknown Location"; + return context.getString(R.string.unknown_location); } @Nullable @@ -374,18 +385,35 @@ public class GatewaysManager { e.printStackTrace(); } - for (int i = 0; i < gatewaysDefined.length(); i++) { + if (PreferenceHelper.useObfuscationPinning(context)) { try { - JSONObject gw = gatewaysDefined.getJSONObject(i); - Gateway aux = new Gateway(eipDefinition, secrets, gw, this.context); - if (gateways.get(aux.getHost()) == null) { - addGateway(aux); - } - } catch (JSONException | IOException e) { + TransportType transportType = getObfuscationPinningKCP(context) ? OBFS4_KCP : OBFS4; + Transport[] transports = new Transport[]{ + new Transport(transportType.toString(), + new String[]{"tcp"}, + new String[]{getObfuscationPinningPort(context)}, + getObfuscationPinningCert(context))}; + GatewayJson.Capabilities capabilities = new GatewayJson.Capabilities(false, false, false, transports, false); + GatewayJson gatewayJson = new GatewayJson(context.getString(R.string.unknown_location), getObfuscationPinningIP(context), null, PINNED_OBFUSCATION_PROXY, capabilities); + Gateway gateway = new Gateway(eipDefinition, secrets, new JSONObject(gatewayJson.toString()), this.context); + addGateway(gateway); + } catch (JSONException | ConfigParser.ConfigParseError | IOException e) { e.printStackTrace(); - VpnStatus.logError("Unable to parse gateway config!"); - } catch (ConfigParser.ConfigParseError e) { - VpnStatus.logError("Unable to parse gateway config: " + e.getLocalizedMessage()); + } + } else { + for (int i = 0; i < gatewaysDefined.length(); i++) { + try { + JSONObject gw = gatewaysDefined.getJSONObject(i); + Gateway aux = new Gateway(eipDefinition, secrets, gw, this.context); + if (gateways.get(aux.getHost()) == null) { + addGateway(aux); + } + } catch (JSONException | IOException e) { + e.printStackTrace(); + VpnStatus.logError("Unable to parse gateway config!"); + } catch (ConfigParser.ConfigParseError e) { + VpnStatus.logError("Unable to parse gateway config: " + e.getLocalizedMessage()); + } } } } catch (NullPointerException npe) { 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 a7df99bf..f60d89ce 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -116,16 +116,6 @@ public class VpnConfigGenerator { public void checkCapabilities() throws ConfigParser.ConfigParseError { try { - if (useObfuscationPinning) { - if (obfuscationPinningKCP) { - // the protocol TCP refers to the allowed openvpn protocol - obfs4TKcpTransport = new JSONObject(new Transport(OBFS4_KCP.toString(), new String[]{"tcp"}, new String[]{obfuscationPinningPort}, obfuscationPinningCert).toString()); - } else { - String jsonTransportString = new Transport(OBFS4.toString(), new String[]{"tcp"}, new String[]{obfuscationPinningPort}, obfuscationPinningCert).toString(); - obfs4Transport = new JSONObject(jsonTransportString); - } - return; - } if (apiVersion >= 3) { JSONArray supportedTransports = gateway.getJSONObject(CAPABILITIES).getJSONArray(TRANSPORT); @@ -133,10 +123,10 @@ public class VpnConfigGenerator { JSONObject transport = supportedTransports.getJSONObject(i); if (transport.getString(TYPE).equals(OBFS4.toString())) { obfs4Transport = transport; - if (!experimentalTransports) { + if (!experimentalTransports && !obfuscationPinningKCP) { break; } - } else if (experimentalTransports && transport.getString(TYPE).equals(OBFS4_KCP.toString())) { + } else if ((experimentalTransports || obfuscationPinningKCP) && transport.getString(TYPE).equals(OBFS4_KCP.toString())) { obfs4TKcpTransport = transport; } } @@ -149,11 +139,15 @@ public class VpnConfigGenerator { public HashMap<TransportType, VpnProfile> generateVpnProfiles() throws ConfigParser.ConfigParseError, - NumberFormatException, - JSONException, - IOException { + NumberFormatException { HashMap<Connection.TransportType, VpnProfile> profiles = new HashMap<>(); - profiles.put(OPENVPN, createProfile(OPENVPN)); + if (supportsOpenvpn()) { + try { + profiles.put(OPENVPN, createProfile(OPENVPN)); + } catch (ConfigParser.ConfigParseError | NumberFormatException | JSONException | IOException e) { + e.printStackTrace(); + } + } if (supportsObfs4()) { try { profiles.put(OBFS4, createProfile(OBFS4)); @@ -168,15 +162,21 @@ public class VpnConfigGenerator { e.printStackTrace(); } } + if (profiles.isEmpty()) { + throw new ConfigParser.ConfigParseError("No supported transports detected."); + } return profiles; } + private boolean supportsOpenvpn() { + return !useObfuscationPinning && !gatewayConfiguration(OPENVPN).isEmpty(); + } private boolean supportsObfs4(){ - return obfs4Transport != null; + return obfs4Transport != null && !(useObfuscationPinning && obfuscationPinningKCP); } private boolean supportsObfs4Kcp() { - return obfs4TKcpTransport != null; + return obfs4TKcpTransport != null && !(useObfuscationPinning && !obfuscationPinningKCP); } private String getConfigurationString(TransportType transportType) { @@ -375,22 +375,8 @@ public class VpnConfigGenerator { } private void ptGatewayConfigMinApiv3(StringBuilder stringBuilder, String[] ipAddresses, TransportType transportType, JSONArray transports) throws JSONException { - if (useObfuscationPinning) { - JSONArray pinnedTransports = new JSONArray(); - for (int i = 0; i < transports.length(); i++) { - if (OPENVPN.toString().equals(transports.getJSONObject(i).get(TYPE))) { - pinnedTransports.put(transports.getJSONObject(i)); - break; - } - } - pinnedTransports.put(supportsObfs4() ? obfs4Transport : obfs4TKcpTransport); - transports = pinnedTransports; - } - JSONObject ptTransport = getTransport(transports, transportType); JSONArray ptProtocols = ptTransport.getJSONArray(PROTOCOLS); - JSONObject openvpnTransport = getTransport(transports, OPENVPN); - JSONArray gatewayProtocols = openvpnTransport.getJSONArray(PROTOCOLS); //for now only use ipv4 gateway the syntax route remote_host 255.255.255.255 net_gateway is not yet working // https://community.openvpn.net/openvpn/ticket/1161 @@ -418,20 +404,23 @@ public class VpnConfigGenerator { return; } - // check if at least one openvpn protocol is TCP, openvpn in UDP is currently not supported for obfs4, - // however on the wire UDP might be used - boolean hasOpenvpnTcp = false; - for (int i = 0; i < gatewayProtocols.length(); i++) { - String protocol = gatewayProtocols.getString(i); - if (protocol.contains("tcp")) { - hasOpenvpnTcp = true; - break; + if (!useObfuscationPinning) { + // check if at least one openvpn protocol is TCP, openvpn in UDP is currently not supported for obfs4, + // however on the wire UDP might be used + boolean hasOpenvpnTcp = false; + JSONObject openvpnTransport = getTransport(transports, OPENVPN); + JSONArray gatewayProtocols = openvpnTransport.getJSONArray(PROTOCOLS); + for (int i = 0; i < gatewayProtocols.length(); i++) { + String protocol = gatewayProtocols.getString(i); + if (protocol.contains("tcp")) { + hasOpenvpnTcp = true; + break; + } + } + if (!hasOpenvpnTcp) { + VpnStatus.logError("obfs4 currently only allows openvpn in TCP mode! Skipping obfs4 config for ip " + ipAddress); + return; } - } - - if (!hasOpenvpnTcp) { - VpnStatus.logError("obfs4 currently only allows openvpn in TCP mode! Skipping obfs4 config for ip " + ipAddress); - return; } boolean hasAllowedPTProtocol = false; @@ -455,17 +444,18 @@ public class VpnConfigGenerator { } String route = "route " + ipAddress + " 255.255.255.255 net_gateway" + newLine; - stringBuilder.append(route); String remote; if (useObfsVpn()) { if (useObfuscationPinning) { remote = REMOTE + " " + obfuscationPinningIP + " " + obfuscationPinningPort + newLine; + route = "route " + obfuscationPinningIP + " 255.255.255.255 net_gateway" + newLine; } else { remote = REMOTE + " " + ipAddress + " " + ports.getString(0) + newLine; } } else { remote = REMOTE + " " + DISPATCHER_IP + " " + DISPATCHER_PORT + " tcp" + newLine; } + stringBuilder.append(route); stringBuilder.append(remote); } diff --git a/app/src/main/res/layout/d_obfuscation_proxy.xml b/app/src/main/res/layout/d_obfuscation_proxy.xml index e8f61ebd..92d51fec 100644 --- a/app/src/main/res/layout/d_obfuscation_proxy.xml +++ b/app/src/main/res/layout/d_obfuscation_proxy.xml @@ -57,24 +57,6 @@ android:id="@+id/cert_field" android:layout_width="match_parent" android:layout_height="wrap_content"/> - - <TextView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="Gateway Host Name" - android:textStyle="bold" - android:paddingTop="@dimen/activity_margin" - android:textAppearance="@android:style/TextAppearance.DeviceDefault" /> - <!--<androidx.appcompat.widget.AppCompatEditText - android:id="@+id/gateway_ip_field" - android:layout_width="match_parent" - android:layout_height="wrap_content"/>--> - <androidx.appcompat.widget.AppCompatSpinner - android:id="@+id/gateway_host" - android:layout_width="match_parent" - android:layout_height="wrap_content" - /> - <se.leap.bitmaskclient.base.views.IconSwitchEntry android:id="@+id/kcp_switch" android:layout_width="match_parent" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 659af92d..ab0744c4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -201,5 +201,6 @@ <string name="disabled_while_udp_on">Disabled while UDP is on.</string> <string name="advanced_settings">Advanced settings</string> <string name="cancel_connection">Disconnect</string> + <string name="unknown_location">Unknown location</string> </resources> diff --git a/app/src/test/java/se/leap/bitmaskclient/base/models/GatewayJsonTest.java b/app/src/test/java/se/leap/bitmaskclient/base/models/GatewayJsonTest.java new file mode 100644 index 00000000..61275378 --- /dev/null +++ b/app/src/test/java/se/leap/bitmaskclient/base/models/GatewayJsonTest.java @@ -0,0 +1,29 @@ +package se.leap.bitmaskclient.base.models; + +import static org.junit.Assert.assertEquals; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; +import static se.leap.bitmaskclient.eip.GatewaysManager.PINNED_OBFUSCATION_PROXY; + +import org.junit.Test; + +import de.blinkt.openvpn.core.connection.Connection; + +public class GatewayJsonTest { + + @Test + public void testToString() { + String gatewayJSON = "{\"location\":\"Unknown Location\",\"ip_address\":\"1.2.3.4\",\"host\":\"pinned.obfuscation.proxy\",\"capabilities\":{\"adblock\":false,\"filter_dns\":false,\"limited\":false,\"transport\":[{\"type\":\"obfs4\",\"protocols\":[\"tcp\"],\"ports\":[\"1194\"],\"options\":{\"cert\":\"xxxxxxx\",\"iatMode\":\"0\"}}],\"user_ips\":false}}"; + + Connection.TransportType transportType = OBFS4; + Transport[] transports = new Transport[]{ + new Transport(transportType.toString(), + new String[]{"tcp"}, + new String[]{"1194"}, + "xxxxxxx")}; + GatewayJson.Capabilities capabilities = new GatewayJson.Capabilities(false, false, false, transports, false); + GatewayJson gatewayJson = new GatewayJson("Unknown Location", "1.2.3.4", null, PINNED_OBFUSCATION_PROXY, capabilities); + + assertEquals(gatewayJSON, gatewayJson.toString()); + } + +}
\ No newline at end of file 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 86a287ad..4fb178fc 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java @@ -1726,7 +1726,7 @@ public class VpnConfigGeneratorTest { 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)); + assertFalse("has no openvpn profile", vpnProfiles.containsKey(OPENVPN)); assertTrue("has obfs4 profile", vpnProfiles.containsKey(OBFS4)); assertFalse("has no obfs4 kcp profile", vpnProfiles.containsKey(OBFS4_KCP)); } @@ -1746,7 +1746,7 @@ public class VpnConfigGeneratorTest { vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertTrue("has obfs4_kcp profile", vpnProfiles.containsKey(OBFS4_KCP)); - assertTrue("has openvpn profile", vpnProfiles.containsKey(OPENVPN)); + assertFalse("has openvpn profile", vpnProfiles.containsKey(OPENVPN)); assertFalse("has no obfs4 profile", vpnProfiles.containsKey(OBFS4)); } @@ -1766,7 +1766,7 @@ public class VpnConfigGeneratorTest { vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration); HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertTrue("has obfs4_kcp profile", vpnProfiles.containsKey(OBFS4_KCP)); - assertTrue("has openvpn profile", vpnProfiles.containsKey(OPENVPN)); + assertFalse("has openvpn profile", vpnProfiles.containsKey(OPENVPN)); assertFalse("has no obfs4 profile", vpnProfiles.containsKey(OBFS4)); } |