summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/build.gradle6
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java25
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/GatewayJson.java61
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java8
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java24
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java6
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java62
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java82
-rw-r--r--app/src/main/res/layout/d_obfuscation_proxy.xml18
-rw-r--r--app/src/main/res/values/strings.xml1
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/base/models/GatewayJsonTest.java29
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java6
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));
}