summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/build.gradle4
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java9
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java38
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java2
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java42
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4HopConnection.java48
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java5
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java6
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java9
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java3
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java16
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java36
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingObfsVpnClient.java66
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java144
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsvpnClient.java87
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientBuilder.java18
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientInterface.java9
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java143
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/HoppingConfig.java (renamed from app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingConfig.java)30
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/KcpConfig.java39
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/Obfs4Options.java (renamed from app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java)8
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/ObfsvpnConfig.java35
-rw-r--r--app/src/main/res/layout-xlarge/f_about.xml34
-rw-r--r--app/src/main/res/layout/f_about.xml30
-rw-r--r--app/src/main/res/values/untranslatable.xml4
-rw-r--r--app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java18
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java9
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java10
m---------bitmaskcore0
-rwxr-xr-xscripts/build_deps.sh2
30 files changed, 231 insertions, 673 deletions
diff --git a/app/build.gradle b/app/build.gradle
index 68182fa5..d9d33767 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -58,8 +58,6 @@ android {
buildConfigField 'boolean', 'priotize_anonymous_usage', 'false'
//allow manual gateway selection
buildConfigField 'boolean', 'allow_manual_gateway_selection', 'true'
- // decide if we use obfsvpn or shapeshifter as obfs4 lib
- buildConfigField 'boolean', 'use_obfsvpn', 'true'
// obfsvpn Debugging config fields to pin and configure a particular proxy
buildConfigField "String", "obfsvpn_port", '""'
buildConfigField "String", "obfsvpn_ip", '""'
@@ -141,8 +139,6 @@ android {
buildConfigField 'boolean', 'priotize_anonymous_usage', 'true'
//allow manual gateway selection
buildConfigField 'boolean', 'allow_manual_gateway_selection', 'true'
- // decide if we use obfsvpn or shapeshifter as obfs4 lib
- 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", '"159.223.173.205"'
diff --git a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
index ff27a5a2..6a5b016e 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java
@@ -5,8 +5,6 @@
package de.blinkt.openvpn.core;
-import static de.blinkt.openvpn.core.connection.Connection.TransportType.PT;
-
import android.os.Build;
import android.text.TextUtils;
@@ -27,9 +25,8 @@ import java.util.Vector;
import de.blinkt.openvpn.VpnProfile;
import de.blinkt.openvpn.core.connection.Connection;
import de.blinkt.openvpn.core.connection.Obfs4Connection;
-import de.blinkt.openvpn.core.connection.Obfs4HopConnection;
import de.blinkt.openvpn.core.connection.OpenvpnConnection;
-import se.leap.bitmaskclient.pluggableTransports.Obfs4Options;
+import se.leap.bitmaskclient.pluggableTransports.models.Obfs4Options;
//! Openvpn Config FIle Parser, probably not 100% accurate but close enough
@@ -808,12 +805,10 @@ public class ConfigParser {
}
else {
switch (transportType) {
+ case OBFS4_HOP:
case OBFS4:
conn = new Obfs4Connection(obfs4Options);
break;
- case OBFS4_HOP:
- conn = new Obfs4HopConnection(obfs4Options);
- break;
case OPENVPN:
conn = new OpenvpnConnection();
break;
diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
index 9e778fae..c8ac965f 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -10,7 +10,6 @@ import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_CONNECTED;
import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT;
import static de.blinkt.openvpn.core.NetworkSpace.IpAddress;
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PROFILE;
-import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn;
import android.Manifest.permission;
import android.app.Notification;
@@ -53,9 +52,7 @@ import se.leap.bitmaskclient.R;
import se.leap.bitmaskclient.eip.EipStatus;
import se.leap.bitmaskclient.eip.VpnNotificationManager;
import se.leap.bitmaskclient.firewall.FirewallManager;
-import se.leap.bitmaskclient.pluggableTransports.PtClientBuilder;
-import se.leap.bitmaskclient.pluggableTransports.PtClientInterface;
-import se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient;
+import se.leap.bitmaskclient.pluggableTransports.ObfsvpnClient;
public class OpenVPNService extends VpnService implements StateListener, Callback, ByteCountListener, IOpenVPNServiceInternal, VpnNotificationManager.VpnServiceCallback {
@@ -91,8 +88,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
private Toast mlastToast;
private Runnable mOpenVPNThread;
private VpnNotificationManager notificationManager;
- private ShapeshifterClient shapeshifter;
- private PtClientInterface obfsVpnClient;
+ private ObfsvpnClient obfsVpnClient;
private FirewallManager firewallManager;
private final IBinder mBinder = new IOpenVPNServiceInternal.Stub() {
@@ -239,10 +235,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
if(isVpnRunning()) {
if (getManagement() != null && getManagement().stopVPN(replaceConnection)) {
if (!replaceConnection) {
- if (shapeshifter != null) {
- shapeshifter.stop();
- shapeshifter = null;
- } else if (obfsVpnClient != null && obfsVpnClient.isStarted()) {
+ if (obfsVpnClient != null && obfsVpnClient.isStarted()) {
obfsVpnClient.stop();
obfsVpnClient = null;
}
@@ -416,21 +409,15 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
mStarting = false;
Connection.TransportType transportType = connection.getTransportType();
if (mProfile.usePluggableTransports() && transportType.isPluggableTransport()) {
- if (useObfsVpn()) {
- if (obfsVpnClient != null && obfsVpnClient.isStarted()) {
- obfsVpnClient.stop();
- }
- obfsVpnClient = PtClientBuilder.getPtClient(connection);
- int runningSocksPort = obfsVpnClient.start();
- if (connection.getTransportType() == Connection.TransportType.OBFS4) {
- connection.setProxyPort(String.valueOf(runningSocksPort));
- }
- } else if (shapeshifter == null) {
- shapeshifter = new ShapeshifterClient(((Obfs4Connection) connection).getObfs4Options());
- shapeshifter.start();
+ if (obfsVpnClient != null && obfsVpnClient.isStarted()) {
+ obfsVpnClient.stop();
}
+ obfsVpnClient = new ObfsvpnClient(((Obfs4Connection) connection).getObfs4Options());
+ obfsVpnClient.start();
+ Log.d(TAG, "obfsvpn client started");
}
+
// Start a new session by creating a new thread.
boolean useOpenVPN3 = VpnProfile.doUseOpenVPN3(this);
@@ -484,12 +471,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
if (mOpenVPNThread != null)
((OpenVPNThread) mOpenVPNThread).setReplaceConnection();
if (mManagement.stopVPN(true)) {
- // an old was asked to exit, wait 1s
- if (shapeshifter != null) {
- Log.d(TAG, "-> stop shapeshifter");
- shapeshifter.stop();
- shapeshifter = null;
- } else if (obfsVpnClient != null && obfsVpnClient.isStarted()) {
+ if (obfsVpnClient != null && obfsVpnClient.isStarted()) {
Log.d(TAG, "-> stop obfsvpnClient");
obfsVpnClient.stop();
obfsVpnClient = null;
diff --git a/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java b/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java
index ecc03a19..73616ba4 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java
@@ -223,7 +223,7 @@ public class VpnStatus {
public enum ErrorType {
UNKNOWN,
- SHAPESHIFTER
+ OBFSVPN
}
// keytool -printcert -jarfile de.blinkt.openvpn_85.apk
diff --git a/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java
index 19ea180d..c646c099 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java
@@ -1,12 +1,7 @@
package de.blinkt.openvpn.core.connection;
-import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn;
-import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_IP;
-import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_PORT;
-
-import se.leap.bitmaskclient.pluggableTransports.HoppingObfsVpnClient;
-import se.leap.bitmaskclient.pluggableTransports.Obfs4Options;
-import se.leap.bitmaskclient.pluggableTransports.ObfsVpnClient;
+import se.leap.bitmaskclient.pluggableTransports.ObfsvpnClient;
+import se.leap.bitmaskclient.pluggableTransports.models.Obfs4Options;
/**
@@ -19,33 +14,10 @@ public class Obfs4Connection extends Connection {
private Obfs4Options options;
public Obfs4Connection(Obfs4Options options) {
- if (useObfsVpn()) {
- setServerName(options.gatewayIP);
- setServerPort(options.transport.getPorts()[0]);
- setProxyName(ObfsVpnClient.SOCKS_IP);
- setProxyType(ProxyType.SOCKS5);
- switch (options.transport.getTransportType()) {
- case OBFS4:
- setUseUdp(false);
- setProxyPort(String.valueOf(ObfsVpnClient.SOCKS_PORT.get()));
- break;
- case OBFS4_HOP:
- setUseUdp(true);
- setProxyPort(String.valueOf(HoppingObfsVpnClient.PORT));
- break;
- default:break;
- }
- } else {
- setServerName(DISPATCHER_IP);
- setServerPort(DISPATCHER_PORT);
- setProxyName("");
- setProxyPort("");
- setProxyType(ProxyType.NONE);
-
- // while udp/kcp might be used on the wire,
- // we don't use udp for openvpn in case of a obfs4 connection
- setUseUdp(false);
- }
+ setServerName(ObfsvpnClient.IP);
+ setServerPort(String.valueOf(ObfsvpnClient.PORT));
+ setProxyType(ProxyType.NONE);
+ setUseUdp(true);
setProxyAuthUser(null);
setProxyAuthPassword(null);
setUseProxyAuth(false);
@@ -61,7 +33,7 @@ public class Obfs4Connection extends Connection {
@Override
public TransportType getTransportType() {
- return TransportType.OBFS4;
+ return options.transport.getTransportType();
}
diff --git a/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4HopConnection.java b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4HopConnection.java
deleted file mode 100644
index f983ae20..00000000
--- a/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4HopConnection.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package de.blinkt.openvpn.core.connection;
-
-import se.leap.bitmaskclient.pluggableTransports.HoppingObfsVpnClient;
-import se.leap.bitmaskclient.pluggableTransports.Obfs4Options;
-
-
-/**
- * Created by cyberta on 08.03.19.
- */
-
-public class Obfs4HopConnection extends Connection {
-
- private static final String TAG = Obfs4HopConnection.class.getName();
- private Obfs4Options options;
-
- public Obfs4HopConnection(Obfs4Options options) {
- setServerName(HoppingObfsVpnClient.IP);
- setServerPort(String.valueOf(HoppingObfsVpnClient.PORT));
- setProxyName("");
- setProxyPort("");
- setProxyType(ProxyType.NONE);
-
-
- setUseUdp(true);
- setProxyAuthUser(null);
- setProxyAuthPassword(null);
- setUseProxyAuth(false);
- this.options = options;
- }
-
- @Override
- public Connection clone() throws CloneNotSupportedException {
- Obfs4HopConnection connection = (Obfs4HopConnection) super.clone();
- connection.options = this.options;
- return connection;
- }
-
- @Override
- public TransportType getTransportType() {
- return TransportType.OBFS4_HOP;
- }
-
-
- public Obfs4Options getObfs4Options() {
- return options;
- }
-
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java
index d7b62de2..33c8f388 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java
@@ -8,7 +8,6 @@ import static se.leap.bitmaskclient.base.models.Constants.PREFER_UDP;
import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES;
import static se.leap.bitmaskclient.base.models.Constants.USE_IPv6_FIREWALL;
import static se.leap.bitmaskclient.base.models.Constants.USE_OBFUSCATION_PINNING;
-import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn;
import static se.leap.bitmaskclient.base.utils.ConfigHelper.isCalyxOSWithTetheringSupport;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.allowExperimentalTransports;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getExcludedApps;
@@ -261,7 +260,7 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh
public void initObfuscationPinningEntry(View rootView) {
IconSwitchEntry obfuscationPinning = rootView.findViewById(R.id.obfuscation_proxy_pinning);
- if (!BuildConfig.BUILD_TYPE.equals("debug") || !useObfsVpn()) {
+ if (!BuildConfig.BUILD_TYPE.equals("debug")) {
obfuscationPinning.setVisibility(GONE);
return;
}
@@ -302,7 +301,7 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh
public void initExperimentalTransportsEntry(View rootView) {
IconSwitchEntry experimentalTransports = rootView.findViewById(R.id.experimental_transports);
- if (useObfsVpn() && ProviderObservable.getInstance().getCurrentProvider().supportsExperimentalPluggableTransports()) {
+ if (ProviderObservable.getInstance().getCurrentProvider().supportsExperimentalPluggableTransports()) {
experimentalTransports.setVisibility(VISIBLE);
experimentalTransports.setChecked(allowExperimentalTransports());
experimentalTransports.setOnCheckedChangeListener((buttonView, isChecked) -> {
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java
index cb9bd520..64e57cda 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java
@@ -28,7 +28,6 @@ import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_ALLOWED_REGIS
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_ALLOW_ANONYMOUS;
import static se.leap.bitmaskclient.base.models.Constants.TRANSPORT;
import static se.leap.bitmaskclient.base.models.Constants.TYPE;
-import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn;
import static se.leap.bitmaskclient.base.utils.RSAHelper.parseRsaKeyFromString;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS;
@@ -190,10 +189,7 @@ public final class Provider implements Parcelable {
}
public boolean supportsPluggableTransports() {
- if (useObfsVpn()) {
- return supportsTransports(new Pair[]{new Pair<>(OBFS4, TCP), new Pair<>(OBFS4, KCP), new Pair<>(OBFS4_HOP, TCP), new Pair<>(OBFS4_HOP, KCP)});
- }
- return supportsTransports(new Pair[]{new Pair<>(OBFS4, TCP)});
+ return supportsTransports(new Pair[]{new Pair<>(OBFS4, TCP), new Pair<>(OBFS4, KCP), new Pair<>(OBFS4_HOP, TCP), new Pair<>(OBFS4_HOP, KCP)});
}
public boolean supportsExperimentalPluggableTransports() {
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java
index e1f65b5e..22af1bfb 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java
@@ -11,7 +11,6 @@ import se.leap.bitmaskclient.BuildConfig;
public class BuildConfigHelper {
public interface BuildConfigHelperInterface {
- boolean useObfsVpn();
boolean hasObfuscationPinningDefaults();
String obfsvpnIP();
String obfsvpnPort();
@@ -21,10 +20,6 @@ public class BuildConfigHelper {
}
public static class DefaultBuildConfigHelper implements BuildConfigHelperInterface {
- @Override
- public boolean useObfsVpn() {
- return BuildConfig.use_obfsvpn;
- }
@Override
public boolean hasObfuscationPinningDefaults() {
@@ -72,10 +67,6 @@ public class BuildConfigHelper {
instance = helperInterface;
}
- public static boolean useObfsVpn() {
- return instance.useObfsVpn();
- }
-
public static boolean hasObfuscationPinningDefaults() {
return instance.hasObfuscationPinningDefaults();
}
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 eee3bfb2..8d1f21e5 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
@@ -513,8 +513,7 @@ public class PreferenceHelper {
}
public static boolean useObfuscationPinning() {
- return BuildConfigHelper.useObfsVpn() &&
- getUseBridges() &&
+ return getUseBridges() &&
getBoolean(USE_OBFUSCATION_PINNING, false) &&
!TextUtils.isEmpty(getObfuscationPinningIP()) &&
!TextUtils.isEmpty(getObfuscationPinningCert()) &&
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java
index adb0fdc7..bd626ce5 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java
@@ -450,22 +450,6 @@ public class EipSetupObserver extends BroadcastReceiver implements VpnStatus.Sta
if (BuildConfig.DEBUG) {
Log.e("ERROR", logItem.getString(appContext));
}
- switch (logItem.getErrorType()) {
- case SHAPESHIFTER:
- VpnProfile profile = VpnStatus.getLastConnectedVpnProfile();
- if (profile == null) {
- EipCommand.startVPN(appContext, false, 0);
- } else {
- GatewaysManager gatewaysManager = new GatewaysManager(appContext);
- int position = gatewaysManager.getPosition(profile);
- setupNClosestGateway.set(position >= 0 ? position : 0);
- selectNextGateway();
- }
- break;
- default:
- break;
-
- }
}
}
}
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 4c8fa797..a7a6bee8 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
@@ -30,9 +30,6 @@ import static se.leap.bitmaskclient.base.models.Constants.REMOTE;
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 static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn;
-import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_IP;
-import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_PORT;
import androidx.annotation.VisibleForTesting;
@@ -52,11 +49,12 @@ 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;
-import se.leap.bitmaskclient.pluggableTransports.HoppingObfsVpnClient;
-import se.leap.bitmaskclient.pluggableTransports.Obfs4Options;
+import se.leap.bitmaskclient.pluggableTransports.ObfsvpnClient;
+import se.leap.bitmaskclient.pluggableTransports.models.Obfs4Options;
public class VpnConfigGenerator {
private final JSONObject generalConfiguration;
@@ -384,28 +382,12 @@ public class VpnConfigGenerator {
}
stringBuilder.append(getRouteString(ipAddress, transport));
- stringBuilder.append(getRemoteString(ipAddress, transport));
- stringBuilder.append(getExtraOptions(transport));
- }
-
- public String getRemoteString(String ipAddress, Transport transport) {
- if (useObfsVpn()) {
- if (useObfuscationPinning) {
- return REMOTE + " " + obfuscationPinningIP + " " + obfuscationPinningPort + " tcp" + newLine;
- }
- switch (transport.getTransportType()) {
- case OBFS4:
- return REMOTE + " " + ipAddress + " " + transport.getPorts()[0] + " tcp" + newLine;
- case OBFS4_HOP:
- return REMOTE + " " + HoppingObfsVpnClient.IP + " " + HoppingObfsVpnClient.PORT + " udp" + newLine;
- default:
- VpnStatus.logError("Unexpected pluggable transport type " + transport.getType() + " for gateway " + ipAddress);
- return "";
- }
- }
- return REMOTE + " " + DISPATCHER_IP + " " + DISPATCHER_PORT + " tcp" + newLine;
+ String transparentProxyRemote = REMOTE + " " + ObfsvpnClient.IP + " " + ObfsvpnClient.PORT + " udp" + newLine;
+ stringBuilder.append(transparentProxyRemote);
}
+ // TODO: figure out if any of these configs still make sense (
+ @Deprecated
public String getExtraOptions(Transport transport) {
if (transport.getTransportType() == OBFS4_HOP) {
return "replay-window 65535" + newLine +
@@ -437,7 +419,7 @@ public class VpnConfigGenerator {
return "";
}
- // While openvpn in TCP mode is required for obfs4, openvpn in UDP mode is required for obfs4-hop
+ // With obfsvpn 1.0.0 openvpn is always required to run in UDP to work with any obfs4 based pluggable transport.
private boolean openvpnModeSupportsPt(Transport transport, String ipAddress) {
if (useObfuscationPinning) {
// we don't know if the manually pinned bridge points to a openvpn gateway with the right
@@ -457,7 +439,7 @@ public class VpnConfigGenerator {
return false;
}
- String requiredProtocol = transport.getTransportType() == OBFS4_HOP ? UDP : TCP;
+ String requiredProtocol = UDP;
for (String protocol : protocols) {
if (protocol.equals(requiredProtocol)) {
return true;
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingObfsVpnClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingObfsVpnClient.java
deleted file mode 100644
index 751208ba..00000000
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingObfsVpnClient.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package se.leap.bitmaskclient.pluggableTransports;
-
-import client.Client;
-import client.HopClient;
-import de.blinkt.openvpn.core.VpnStatus;
-import se.leap.bitmaskclient.base.models.Constants;
-
-public class HoppingObfsVpnClient implements PtClientInterface {
-
- public static final int PORT = 8080;
- public static final String IP = "127.0.0.1";
-
- public final HopClient client;
-
- public HoppingObfsVpnClient(Obfs4Options options) throws IllegalStateException {
-
- //FIXME: use a different strategy here
- //Basically we would want to track if the more performant transport protocol (KCP?/TCP?) usage was successful
- //if so, we stick to it, otherwise we flip the flag
- boolean kcp = Constants.KCP.equals(options.transport.getProtocols()[0]);
-
- HoppingConfig hoppingConfig = new HoppingConfig(kcp,IP+":"+PORT, options, 10, 10);
- try {
- client = Client.newFFIHopClient(hoppingConfig.toString());
- } catch (Exception e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public int start() {
- try {
- client.setEventLogger(this);
- return client.start() ? PORT : 0;
- } catch (Exception e) {
- e.printStackTrace();
- return 0;
- }
- }
-
- @Override
- public void stop() {
- try {
- client.stop();
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- client.setEventLogger(null);
- }
- }
-
- @Override
- public boolean isStarted() {
- return client.isStarted();
- }
-
- @Override
- public void error(String s) {
- VpnStatus.logError("[hopping-obfs4] " + s);
- }
-
- @Override
- public void log(String state, String message) {
- VpnStatus.logDebug("[hopping-obfs4] " + state + ": " + message);
- }
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java
deleted file mode 100644
index 685349ed..00000000
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package se.leap.bitmaskclient.pluggableTransports;
-
-import static se.leap.bitmaskclient.base.models.Constants.KCP;
-
-import android.util.Log;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.util.Observable;
-import java.util.Observer;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import client.Client;
-import de.blinkt.openvpn.core.ConnectionStatus;
-import de.blinkt.openvpn.core.VpnStatus;
-import se.leap.bitmaskclient.eip.EipStatus;
-
-public class ObfsVpnClient implements PropertyChangeListener, PtClientInterface {
-
- public static final AtomicInteger SOCKS_PORT = new AtomicInteger(4430);
- public static final String SOCKS_IP = "127.0.0.1";
- private static final String ERR_BIND = "bind: address already in use";
-
- private static final String TAG = ObfsVpnClient.class.getSimpleName();
- private volatile boolean noNetwork;
- private final AtomicBoolean pendingNetworkErrorHandling = new AtomicBoolean(false);
- private final AtomicInteger reconnectRetry = new AtomicInteger(0);
- private static final int MAX_RETRY = 5;
-
- private final client.Client_ obfsVpnClient;
- private final Object LOCK = new Object();
-
- public ObfsVpnClient(Obfs4Options options) throws IllegalStateException{
- //FIXME: use a different strategy here
- //Basically we would want to track if the more performant transport protocol (KCP?/TCP?) usage was successful
- //if so, we stick to it, otherwise we flip the flag
- boolean kcp = KCP.equals(options.transport.getProtocols()[0]);
-
- if (options.transport.getOptions().getCert() == null) {
- throw new IllegalStateException("No cert found to establish a obfs4 connection");
- }
-
- obfsVpnClient = Client.newClient(kcp, SOCKS_IP+":"+SOCKS_PORT.get(), options.transport.getOptions().getCert());
- }
-
- /**
- * starts the client
- * @return the port ObfsVpn is running on
- */
- public int start() {
- synchronized (LOCK) {
- obfsVpnClient.setEventLogger(this);
- Log.d(TAG, "aquired LOCK");
- new Thread(this::startSync).start();
- waitUntilStarted();
- Log.d(TAG, "returning LOCK after " + (reconnectRetry.get() + 1) * 200 +" ms");
- }
- return SOCKS_PORT.get();
- }
-
- // We're waiting here until the obfsvpn client has found a unbound port and started
- private void waitUntilStarted() {
- int count = -1;
- try {
- while (count < reconnectRetry.get() && reconnectRetry.get() < MAX_RETRY) {
- Thread.sleep(200);
- count++;
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- private void startSync() {
- try {
- obfsVpnClient.start();
- } catch (Exception e) {
- Log.e(TAG, "[obfsvpn] exception: " + e.getLocalizedMessage());
- VpnStatus.logError("[obfsvpn] " + e.getLocalizedMessage());
- if (e.getLocalizedMessage() != null && e.getLocalizedMessage().contains(ERR_BIND) && reconnectRetry.get() < MAX_RETRY) {
- reconnectRetry.addAndGet(1);
- SOCKS_PORT.addAndGet(1);
- obfsVpnClient.setSocksAddr(SOCKS_IP+":"+SOCKS_PORT.get());
- Log.d(TAG, "[obfsvpn] reconnecting on different port... " + SOCKS_PORT.get());
- VpnStatus.logDebug("[obfsvpn] reconnecting on different port... " + SOCKS_PORT.get());
- startSync();
- } else if (noNetwork) {
- pendingNetworkErrorHandling.set(true);
- }
- }
- }
-
- public void stop() {
- synchronized (LOCK) {
- Log.d(TAG, "stopping obfsVpnClient...");
- try {
- obfsVpnClient.stop();
- reconnectRetry.set(0);
- SOCKS_PORT.set(4430);
- Thread.sleep(100);
- } catch (Exception e) {
- e.printStackTrace();
- VpnStatus.logError("[obfsvpn] " + e.getLocalizedMessage());
- } finally {
- obfsVpnClient.setEventLogger(null);
- }
- pendingNetworkErrorHandling.set(false);
- Log.d(TAG, "stopping obfsVpnClient releasing LOCK ...");
- }
- }
-
- public boolean isStarted() {
- return obfsVpnClient.isStarted();
- }
-
- // TODO: register observer!
- @Override
- public void propertyChange(PropertyChangeEvent evt) {
- if (EipStatus.PROPERTY_CHANGE.equals(evt.getPropertyName())) {
- EipStatus status = (EipStatus) evt.getNewValue();
- if (status.getLevel() == ConnectionStatus.LEVEL_NONETWORK) {
- noNetwork = true;
- } else {
- noNetwork = false;
- if (pendingNetworkErrorHandling.getAndSet(false)) {
- stop();
- start();
- }
- }
- }
- }
-
- @Override
- public void error(String s) {
- VpnStatus.logError("[obfsvpn] " + s);
- }
-
- @Override
- public void log(String state, String message) {
- VpnStatus.logDebug("[obfsvpn] " + state + " " + message);
- }
-
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsvpnClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsvpnClient.java
new file mode 100644
index 00000000..dfdfbdd5
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsvpnClient.java
@@ -0,0 +1,87 @@
+package se.leap.bitmaskclient.pluggableTransports;
+
+import android.util.Log;
+
+import client.Client;
+import client.Client_;
+import client.EventLogger;
+import de.blinkt.openvpn.core.VpnStatus;
+import de.blinkt.openvpn.core.connection.Connection;
+import se.leap.bitmaskclient.base.models.Constants;
+import se.leap.bitmaskclient.pluggableTransports.models.HoppingConfig;
+import se.leap.bitmaskclient.pluggableTransports.models.KcpConfig;
+import se.leap.bitmaskclient.pluggableTransports.models.Obfs4Options;
+import se.leap.bitmaskclient.pluggableTransports.models.ObfsvpnConfig;
+
+public class ObfsvpnClient {
+
+ public static final int PORT = 8080;
+ public static final String IP = "127.0.0.1";
+ private final Object LOCK = new Object();
+
+
+ private static final String TAG = ObfsvpnClient.class.getSimpleName();
+
+ public final Client_ client;
+
+ public ObfsvpnClient(Obfs4Options options) throws IllegalStateException {
+
+ //FIXME: use a different strategy here
+ //Basically we would want to track if the more performant transport protocol (KCP?/TCP?) usage was successful
+ //if so, we stick to it, otherwise we flip the flag
+ boolean kcpEnabled = Constants.KCP.equals(options.transport.getProtocols()[0]);
+ boolean hoppingEnabled = options.transport.getTransportType() == Connection.TransportType.OBFS4_HOP;
+ if (!hoppingEnabled && (options.transport.getPorts() == null || options.transport.getPorts().length == 0)) {
+ throw new IllegalStateException("obf4 based transport has no bridge ports configured");
+ }
+ KcpConfig kcpConfig = new KcpConfig(kcpEnabled);
+ HoppingConfig hoppingConfig = new HoppingConfig(hoppingEnabled,IP+":"+PORT, options, 10, 10);
+ ObfsvpnConfig obfsvpnConfig = new ObfsvpnConfig(IP+":"+PORT, hoppingConfig, kcpConfig, options.bridgeIP, options.transport.getPorts()[0], options.transport.getOptions().getCert() );
+ try {
+ Log.d(TAG, obfsvpnConfig.toString());
+ client = Client.newFFIClient(obfsvpnConfig.toString());
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public int start() {
+ synchronized (LOCK) {
+ new Thread(() -> {
+ try {
+ client.setEventLogger(new EventLogger() {
+ @Override
+ public void error(String s) {
+ VpnStatus.logError("[obfs4-client] " + s);
+ }
+
+ @Override
+ public void log(String state, String message) {
+ VpnStatus.logDebug("[obfs4-client] " + state + ": " + message);
+ }
+ });
+ client.start();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ });
+ return PORT;
+ }
+ }
+
+ public void stop() {
+ synchronized (LOCK) {
+ try {
+ client.stop();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ client.setEventLogger(null);
+ }
+ }
+ }
+
+ public boolean isStarted() {
+ return client.isStarted();
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientBuilder.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientBuilder.java
deleted file mode 100644
index 945e3d7a..00000000
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientBuilder.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package se.leap.bitmaskclient.pluggableTransports;
-
-import de.blinkt.openvpn.core.connection.Connection;
-import de.blinkt.openvpn.core.connection.Obfs4Connection;
-import de.blinkt.openvpn.core.connection.Obfs4HopConnection;
-
-public class PtClientBuilder {
- public static PtClientInterface getPtClient(Connection connection) throws IllegalStateException {
- switch (connection.getTransportType()) {
- case OBFS4:
- return new ObfsVpnClient(((Obfs4Connection) connection).getObfs4Options());
- case OBFS4_HOP:
- return new HoppingObfsVpnClient(((Obfs4HopConnection) connection).getObfs4Options());
- default:
- throw new IllegalStateException("Unexpected pluggable transport " + connection.getTransportType());
- }
- }
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientInterface.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientInterface.java
deleted file mode 100644
index 28d19a97..00000000
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientInterface.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package se.leap.bitmaskclient.pluggableTransports;
-
-import client.EventLogger;
-
-public interface PtClientInterface extends EventLogger {
- int start();
- void stop();
- boolean isStarted();
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java
deleted file mode 100644
index e57401f8..00000000
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/**
- * Copyright (c) 2020 LEAP Encryption Access Project and contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package se.leap.bitmaskclient.pluggableTransports;
-
-import android.os.Handler;
-import android.os.Looper;
-import android.util.Log;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-
-import de.blinkt.openvpn.core.ConnectionStatus;
-import de.blinkt.openvpn.core.VpnStatus;
-import se.leap.bitmaskclient.eip.EipStatus;
-
-public class ShapeshifterClient implements PropertyChangeListener {
-
- public static final String DISPATCHER_PORT = "4430";
- public static final String DISPATCHER_IP = "127.0.0.1";
- private static final int MAX_RETRY = 5;
- private static final int RETRY_TIME = 4000;
- private static final String TAG = ShapeshifterClient.class.getSimpleName();
-
- private final shapeshifter.Shapeshifter_ shapeShifter;
- private boolean isErrorHandling;
- private boolean noNetwork;
- private int retry = 0;
- private final Handler reconnectHandler;
-
- @Deprecated
- public class ShapeshifterLogger implements shapeshifter.Logger {
- @Override
- public void log(String s) {
- Log.e(TAG, "SHAPESHIFTER ERROR: " + s);
- VpnStatus.logError(s);
- isErrorHandling = true;
- close();
-
- if (retry < MAX_RETRY && !noNetwork) {
- retry++;
- reconnectHandler.postDelayed(ShapeshifterClient.this::reconnect, RETRY_TIME);
- } else {
- VpnStatus.logError(VpnStatus.ErrorType.SHAPESHIFTER);
- }
- }
- }
-
- public ShapeshifterClient(Obfs4Options options) {
- shapeShifter = new shapeshifter.Shapeshifter_();
- shapeShifter.setLogger(new ShapeshifterLogger());
- setup(options);
- Looper.prepare();
- reconnectHandler = new Handler();
- EipStatus.getInstance().addObserver(this);
- Log.d(TAG, "shapeshifter initialized with: \n" + shapeShifter.toString());
- }
-
- private void setup(Obfs4Options options) {
- shapeShifter.setSocksAddr(DISPATCHER_IP+":"+DISPATCHER_PORT);
- shapeShifter.setTarget(options.gatewayIP +":"+options.transport.getPorts()[0]);
- shapeShifter.setCert(options.transport.getOptions().getCert());
- }
-
- public void setOptions(Obfs4Options options) {
- setup(options);
- }
-
- public void start() {
- try {
- shapeShifter.open();
- } catch (Exception e) {
- e.printStackTrace();
- Log.e(TAG, "SHAPESHIFTER ERROR: " + e.getLocalizedMessage());
- VpnStatus.logError(VpnStatus.ErrorType.SHAPESHIFTER);
- VpnStatus.logError(e.getLocalizedMessage());
- }
- }
-
- private void close() {
- try {
- shapeShifter.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- private void reconnect() {
- try {
- shapeShifter.open();
- retry = 0;
- isErrorHandling = false;
- } catch (Exception e) {
- e.printStackTrace();
- Log.e(TAG, "SHAPESHIFTER RECONNECTION ERROR: " + e.getLocalizedMessage());
- VpnStatus.logError("Unable to reconnect shapeshifter: " + e.getLocalizedMessage());
- }
- }
-
- public boolean stop() {
- try {
- shapeShifter.close();
- return true;
- } catch (Exception e) {
- e.printStackTrace();
- VpnStatus.logError(e.getLocalizedMessage());
- }
- EipStatus.getInstance().deleteObserver(this);
- return false;
- }
-
-
- @Override
- public void propertyChange(PropertyChangeEvent evt) {
- if (EipStatus.PROPERTY_CHANGE.equals(evt.getPropertyName())) {
- EipStatus status = (EipStatus) evt.getNewValue();
- if (status.getLevel() == ConnectionStatus.LEVEL_NONETWORK) {
- noNetwork = true;
- } else {
- noNetwork = false;
- if (isErrorHandling) {
- isErrorHandling = false;
- close();
- start();
- }
- }
- }
- }
-}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingConfig.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/HoppingConfig.java
index 3780b7dc..96b8c460 100644
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingConfig.java
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/HoppingConfig.java
@@ -1,4 +1,4 @@
-package se.leap.bitmaskclient.pluggableTransports;
+package se.leap.bitmaskclient.pluggableTransports.models;
import androidx.annotation.NonNull;
@@ -9,35 +9,47 @@ import com.google.gson.GsonBuilder;
import se.leap.bitmaskclient.base.models.Transport;
public class HoppingConfig {
- final boolean kcp;
+
+ /**
+ * Enabled bool `json:"enabled"`
+ * Remotes []string `json:"remotes"`
+ * Obfs4Certs []string `json:"obfs4_certs"`
+ * PortSeed int64 `json:"port_seed"`
+ * PortCount uint `json:"port_count"`
+ * MinHopSeconds uint `json:"min_hop_seconds"`
+ * HopJitter uint `json:"hop_jitter"`
+ * }
+ */
+
+ final boolean enabled;
final String proxyAddr;
final String[] remotes;
- final String[] certs;
+ final String[] obfs4Certs;
final int portSeed;
final int portCount;
final int minHopSeconds;
final int hopJitter;
- public HoppingConfig(boolean kcp,
+ public HoppingConfig(boolean enabled,
String proxyAddr,
Obfs4Options options,
int minHopSeconds,
int hopJitter) {
- this.kcp = kcp;
+ this.enabled = enabled;
this.proxyAddr = proxyAddr;
Transport transport = options.transport;
Transport.Endpoint[] endpoints = transport.getOptions().getEndpoints();
if (endpoints == null) {
// only port hopping, we assume the gateway IP as hopping PT's IP
- this.remotes = new String[]{ options.gatewayIP };
- this.certs = new String[] { transport.getOptions().getCert() };
+ this.remotes = new String[]{ options.bridgeIP };
+ this.obfs4Certs = new String[] { transport.getOptions().getCert() };
} else {
// port+ip hopping
this.remotes = new String[endpoints.length];
- this.certs = new String[endpoints.length];
+ this.obfs4Certs = new String[endpoints.length];
for (int i = 0; i < remotes.length; i++) {
remotes[i] = endpoints[i].getIp();
- certs[i] = endpoints[i].getCert();
+ obfs4Certs[i] = endpoints[i].getCert();
}
}
this.portSeed = transport.getOptions().getPortSeed();
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/KcpConfig.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/KcpConfig.java
new file mode 100644
index 00000000..255e7dd7
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/KcpConfig.java
@@ -0,0 +1,39 @@
+package se.leap.bitmaskclient.pluggableTransports.models;
+
+import androidx.annotation.NonNull;
+
+import com.google.gson.FieldNamingPolicy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+public class KcpConfig {
+
+ // check OpenVPN's --sndbuf size and --rcvbuf size
+ public static final int DEFAULT_KCP_SEND_WINDOW_SIZE = 32;
+ public static final int DEFAULT_KCP_RECEIVE_WINDOW_SIZE = 32;
+ public static final int DEFAULT_KCP_READ_BUFFER = 16 * 1024 * 1024;
+ public static final int DEFAULT_KCP_WRITE_BUFFER = 16 * 1024 * 1024;
+
+ final boolean enabled;
+ final int sendWindowSize;
+ final int receiveWindowSize;
+ final int readBuffer;
+ final int writeBuffer;
+
+ public KcpConfig(boolean enabled) {
+ this.enabled = enabled;
+ this.sendWindowSize = DEFAULT_KCP_SEND_WINDOW_SIZE;
+ this.receiveWindowSize = DEFAULT_KCP_RECEIVE_WINDOW_SIZE;
+ this.readBuffer = DEFAULT_KCP_READ_BUFFER;
+ this.writeBuffer = DEFAULT_KCP_WRITE_BUFFER;
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ Gson gson = new GsonBuilder()
+ .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
+ .create();
+ return gson.toJson(this);
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/Obfs4Options.java
index 0dd81eb8..1eec376a 100644
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/Obfs4Options.java
@@ -1,16 +1,16 @@
-package se.leap.bitmaskclient.pluggableTransports;
+package se.leap.bitmaskclient.pluggableTransports.models;
import java.io.Serializable;
import se.leap.bitmaskclient.base.models.Transport;
public class Obfs4Options implements Serializable {
- public String gatewayIP;
+ public String bridgeIP;
public Transport transport;
- public Obfs4Options(String gatewayIP,
+ public Obfs4Options(String bridgeIP,
Transport transport) {
- this.gatewayIP = gatewayIP;
+ this.bridgeIP = bridgeIP;
this.transport = transport;
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/ObfsvpnConfig.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/ObfsvpnConfig.java
new file mode 100644
index 00000000..9f85c4a0
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/ObfsvpnConfig.java
@@ -0,0 +1,35 @@
+package se.leap.bitmaskclient.pluggableTransports.models;
+
+import androidx.annotation.NonNull;
+
+import com.google.gson.FieldNamingPolicy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+public class ObfsvpnConfig {
+
+ final String proxyAddr;
+ final HoppingConfig hoppingConfig;
+ final KcpConfig kcpConfig;
+ final String remoteIp;
+ final String remotePort;
+ final String obfs4Cert;
+
+ public ObfsvpnConfig(String proxyAddress, HoppingConfig hoppingConfig, KcpConfig kcpConfig, String remoteIP, String remotePort, String obfsv4Cert) {
+ this.proxyAddr = proxyAddress;
+ this.hoppingConfig = hoppingConfig;
+ this.kcpConfig = kcpConfig;
+ this.remoteIp = remoteIP;
+ this.remotePort = remotePort;
+ this.obfs4Cert = obfsv4Cert;
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ Gson gson = new GsonBuilder()
+ .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
+ .create();
+ return gson.toJson(this);
+ }
+}
diff --git a/app/src/main/res/layout-xlarge/f_about.xml b/app/src/main/res/layout-xlarge/f_about.xml
index 4e0d7342..cfdf2f40 100644
--- a/app/src/main/res/layout-xlarge/f_about.xml
+++ b/app/src/main/res/layout-xlarge/f_about.xml
@@ -190,23 +190,6 @@
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/shapeshifter_library"
- android:textSize="24sp"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textSize="18sp"
- android:text="@string/copyright_shapeshifter_library" />
-
- <Space
- android:layout_width="match_parent"
- android:layout_height="20dp" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
android:text="@string/obfs4"
android:textSize="24sp"
android:textAppearance="?android:attr/textAppearanceMedium" />
@@ -224,23 +207,6 @@
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/shapeshifter_transports"
- android:textSize="24sp"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textSize="18sp"
- android:text="@string/copyright_shapeshifter_transports" />
-
- <Space
- android:layout_width="match_parent"
- android:layout_height="20dp" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
android:text="@string/circleImageView"
android:textSize="24sp"
android:textAppearance="?android:attr/textAppearanceMedium" />
diff --git a/app/src/main/res/layout/f_about.xml b/app/src/main/res/layout/f_about.xml
index 28f89adf..b4d46694 100644
--- a/app/src/main/res/layout/f_about.xml
+++ b/app/src/main/res/layout/f_about.xml
@@ -186,21 +186,6 @@
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/shapeshifter_library"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/copyright_shapeshifter_library" />
-
- <Space
- android:layout_width="match_parent"
- android:layout_height="20dp" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
android:text="@string/obfs4"
android:textAppearance="?android:attr/textAppearanceMedium" />
@@ -216,21 +201,6 @@
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/shapeshifter_transports"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/copyright_shapeshifter_transports" />
-
- <Space
- android:layout_width="match_parent"
- android:layout_height="20dp" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
android:text="@string/circleImageView"
android:textAppearance="?android:attr/textAppearanceMedium" />
diff --git a/app/src/main/res/values/untranslatable.xml b/app/src/main/res/values/untranslatable.xml
index 13d0204a..80cbf7f3 100644
--- a/app/src/main/res/values/untranslatable.xml
+++ b/app/src/main/res/values/untranslatable.xml
@@ -33,10 +33,6 @@
<string name="state_user_vpn_password" translatable="false">Waiting for user VPN password</string>
<string name="state_user_vpn_password_cancelled" translatable="false">VPN password input dialog cancelled</string>
<string name="state_user_vpn_permission_cancelled" translatable="false">VPN API permission dialog cancelled</string>
- <string name="shapeshifter_library" translatable="false">Shapeshifter Library</string>
- <string name="copyright_shapeshifter_library" translatable="false">Copyright (c) 2024, LEAP Encryption Access Project (info@leap.se)</string>
- <string name="shapeshifter_transports" translatable="false">Shapeshifter Transports</string>
- <string name="copyright_shapeshifter_transports" translatable="false">Copyright (c) 2024 Operator Foundation. Distributed under MIT license.</string>
<string name="obfs4" translatable="false">obfs4 - The obfourscator</string>
<string name="copyright_obfs4" translatable="false">Copyright (c) 2014, Yawning Angel \n yawning at schwanenlied dot me \n All rights reserved.</string>
<string name="snowflake" translatable="false">Snowflake</string>
diff --git a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java
index ad42ffde..eebee891 100644
--- a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java
+++ b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java
@@ -25,7 +25,7 @@ import de.blinkt.openvpn.core.connection.Obfs4Connection;
import de.blinkt.openvpn.core.connection.OpenvpnConnection;
import se.leap.bitmaskclient.base.models.Transport;
import se.leap.bitmaskclient.base.utils.BuildConfigHelper;
-import se.leap.bitmaskclient.pluggableTransports.Obfs4Options;
+import se.leap.bitmaskclient.pluggableTransports.models.Obfs4Options;
@RunWith(PowerMockRunner.class)
@PrepareForTest({UUID.class, BuildConfigHelper.class})
@@ -77,8 +77,6 @@ public class VpnProfileTest {
@Test
public void toJson_obfs4() throws JSONException {
- when(BuildConfigHelper.useObfsVpn()).thenReturn(false);
-
VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4);
Transport transport = new Transport(OBFS4.toString(), new String[]{"tcp"}, new String[]{"1234"}, "CERT");
@@ -96,7 +94,6 @@ public class VpnProfileTest {
@Test
public void toJson_obfs4_obfsvpn() throws JSONException {
- when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4);
Transport.Options options = new Transport.Options("CERT", "1");
Transport transport = new Transport(OBFS4.toString(), new String[]{"tcp"}, new String[]{"1234"}, options);
@@ -114,7 +111,6 @@ public class VpnProfileTest {
@Test
public void toJson_obfs4_obfsvpn_kcp() throws JSONException {
- when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4);
Transport.Options options = new Transport.Options("CERT", "1");
@@ -133,7 +129,6 @@ public class VpnProfileTest {
@Test
public void toJson_obfs4hop_kcp() throws JSONException {
- when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4_HOP);
@@ -154,7 +149,6 @@ public class VpnProfileTest {
@Test
public void toJson_obfs4hop_portHopping() throws JSONException {
- when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4_HOP);
@@ -175,7 +169,6 @@ public class VpnProfileTest {
@Test
public void toJson_obfs4hop() throws JSONException {
- when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4_HOP);
Transport.Options options = new Transport.Options("1", new Transport.Endpoint[]{new Transport.Endpoint("1.1.1.1", "CERT1"), new Transport.Endpoint("2.2.2.2", "CERT2")}, 200, 100, true);
@@ -195,7 +188,6 @@ public class VpnProfileTest {
@Test
public void fromJson_obfs4() {
- when(BuildConfigHelper.useObfsVpn()).thenReturn(false);
VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE);
assertNotNull(mockVpnProfile);
@@ -210,14 +202,13 @@ public class VpnProfileTest {
}
assertEquals("CERT", obfs4Connection.getObfs4Options().transport.getOptions().getCert());
assertEquals("0", obfs4Connection.getObfs4Options().transport.getOptions().getIatMode());
- assertEquals("192.168.0.1", obfs4Connection.getObfs4Options().gatewayIP);
+ assertEquals("192.168.0.1", obfs4Connection.getObfs4Options().bridgeIP);
assertEquals("1234", obfs4Connection.getObfs4Options().transport.getPorts()[0]);
assertEquals(1, obfs4Connection.getObfs4Options().transport.getPorts().length);
}
@Test
public void fromJson_obfs4_obfsvpn() {
- when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE_OBFSVPN);
assertNotNull(mockVpnProfile);
@@ -229,14 +220,13 @@ public class VpnProfileTest {
assertEquals("tcp", obfs4Connection.getObfs4Options().transport.getProtocols()[0]);
assertEquals("CERT", obfs4Connection.getObfs4Options().transport.getOptions().getCert());
assertEquals("1", obfs4Connection.getObfs4Options().transport.getOptions().getIatMode());
- assertEquals("192.168.0.1", obfs4Connection.getObfs4Options().gatewayIP);
+ assertEquals("192.168.0.1", obfs4Connection.getObfs4Options().bridgeIP);
assertEquals("1234", obfs4Connection.getObfs4Options().transport.getPorts()[0]);
assertEquals(1, obfs4Connection.getObfs4Options().transport.getPorts().length);
}
@Test
public void fromJson_obfs4_obfsvpn_kcp() {
- when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE_OBFSVPN_KCP);
assertNotNull(mockVpnProfile);
@@ -248,7 +238,7 @@ public class VpnProfileTest {
assertEquals("kcp", obfs4Connection.getObfs4Options().transport.getProtocols()[0]);
assertEquals("CERT", obfs4Connection.getObfs4Options().transport.getOptions().getCert());
assertEquals("1", obfs4Connection.getObfs4Options().transport.getOptions().getIatMode());
- assertEquals("192.168.0.1", obfs4Connection.getObfs4Options().gatewayIP);
+ assertEquals("192.168.0.1", obfs4Connection.getObfs4Options().bridgeIP);
assertEquals("1234", obfs4Connection.getObfs4Options().transport.getPorts()[0]);
}
} \ 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 4b9e5d65..b17a51cf 100644
--- a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java
@@ -24,7 +24,6 @@ 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 de.blinkt.openvpn.core.connection.Obfs4HopConnection;
import se.leap.bitmaskclient.base.models.ProviderObservable;
import se.leap.bitmaskclient.base.utils.BuildConfigHelper;
import se.leap.bitmaskclient.base.utils.PreferenceHelper;
@@ -1709,7 +1708,7 @@ public class VpnConfigGeneratorTest {
configuration.experimentalTransports = true;
vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
- assertTrue(vpnProfiles.containsKey(OBFS4_HOP) && ((Obfs4HopConnection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp"));
+ assertTrue(vpnProfiles.containsKey(OBFS4_HOP) && ((Obfs4Connection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp"));
assertTrue(vpnProfiles.containsKey(OPENVPN));
}
@@ -1722,7 +1721,7 @@ public class VpnConfigGeneratorTest {
configuration.experimentalTransports = true;
vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
- assertTrue(vpnProfiles.containsKey(OBFS4_HOP) && ((Obfs4HopConnection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("kcp"));
+ assertTrue(vpnProfiles.containsKey(OBFS4_HOP) && ((Obfs4Connection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("kcp"));
assertTrue(vpnProfiles.containsKey(OPENVPN));
}
@@ -1779,7 +1778,7 @@ public class VpnConfigGeneratorTest {
vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertTrue(vpnProfiles.containsKey(OBFS4_HOP));
- assertTrue(((Obfs4HopConnection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp"));
+ assertTrue(((Obfs4Connection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp"));
assertFalse(vpnProfiles.containsKey(OPENVPN));
assertFalse(vpnProfiles.containsKey(OBFS4));
}
@@ -1813,7 +1812,7 @@ public class VpnConfigGeneratorTest {
vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, configuration);
HashMap<Connection.TransportType, VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
assertTrue(vpnProfiles.containsKey(OBFS4_HOP));
- assertTrue(((Obfs4HopConnection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp"));
+ assertTrue(((Obfs4Connection)vpnProfiles.get(OBFS4_HOP).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("tcp"));
assertFalse(vpnProfiles.containsKey(OPENVPN));
assertFalse(vpnProfiles.containsKey(OBFS4));
}
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java
index a7d3e19c..1b94042e 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java
@@ -190,16 +190,12 @@ public class MockHelper {
}
- public static BuildConfigHelper mockBuildConfigHelper(boolean useObfsvpn) {
- return mockBuildConfigHelper(useObfsvpn, true);
+ public static BuildConfigHelper mockBuildConfigHelper() {
+ return mockBuildConfigHelper(true);
}
- public static BuildConfigHelper mockBuildConfigHelper(boolean useObfsvpn, boolean isDefaultBitmask) {
+ public static BuildConfigHelper mockBuildConfigHelper(boolean isDefaultBitmask) {
return new BuildConfigHelper(new BuildConfigHelper.BuildConfigHelperInterface() {
- @Override
- public boolean useObfsVpn() {
- return useObfsvpn;
- }
@Override
public boolean hasObfuscationPinningDefaults() {
diff --git a/bitmaskcore b/bitmaskcore
-Subproject 8048415c2ee86e21179a39ad5937d3d5e99997c
+Subproject 1b67eff2e7fcba9a18722d2185e55e95704259c
diff --git a/scripts/build_deps.sh b/scripts/build_deps.sh
index 20ed016b..51cc926d 100755
--- a/scripts/build_deps.sh
+++ b/scripts/build_deps.sh
@@ -76,7 +76,7 @@ else
cd ..
fi
-# build bitmask core (shapeshifter, snowflake, pgpverify)
+# build bitmask core (snowflake, pgpverify)
if [[ $(ls -A ${DIR_GOLIBS}) ]]
then
echo "Dirty build: Reusing go libraries"