From 31dcd6366378c9a813fbadd4a1620189a2edfe74 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 30 May 2022 00:46:15 +0200 Subject: update bitmaskcore, integrating obfsvpn --- bitmaskcore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bitmaskcore b/bitmaskcore index 5e5b3ebe..a82335ae 160000 --- a/bitmaskcore +++ b/bitmaskcore @@ -1 +1 @@ -Subproject commit 5e5b3ebebc5437e83f3bc5f0afce46b6b4aa4655 +Subproject commit a82335aef6cdd2bd0499d8828d6d479f2ded0876 -- cgit v1.2.3 From 778128e94fc3f6601986b5943122e499a318b8cd Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 30 May 2022 23:43:58 +0200 Subject: implement ObfsVpnClient, wrapping go jni bindings --- .../pluggableTransports/ObfsVpnClient.java | 68 ++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java 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..c871c708 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java @@ -0,0 +1,68 @@ +package se.leap.bitmaskclient.pluggableTransports; + +import android.util.Log; + +import java.util.Observable; +import java.util.Observer; + +import client.Client_; +import de.blinkt.openvpn.core.ConnectionStatus; +import se.leap.bitmaskclient.eip.EipStatus; + +public class ObfsVpnClient implements Observer { + + public static final String SOCKS_PORT = "4430"; + public static final String SOCKS_IP = "127.0.0.1"; + + private static final String TAG = ObfsVpnClient.class.getSimpleName(); + private boolean noNetwork; + // TODO: implement error signaling go->java + private boolean isErrorHandling; + + private final client.Client_ obfsVpnClient; + private final Object LOCK = new Object(); + + public ObfsVpnClient(Obfs4Options options) { + obfsVpnClient = new Client_(options.udp, SOCKS_IP+":"+SOCKS_PORT, options.cert); + } + + public void start() { + new Thread(() -> { + synchronized (LOCK) { + Log.d(TAG, "aquired LOCK"); + new Thread(obfsVpnClient::start).start(); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + Log.d(TAG, "returning LOCK after 500 ms"); + } + }).start(); + } + + public void stop() { + synchronized (LOCK) { + Log.d(TAG, "stopping obfsVpnClient..."); + obfsVpnClient.stop(); + } + } + + @Override + public void update(Observable observable, Object arg) { + if (observable instanceof EipStatus) { + EipStatus status = (EipStatus) observable; + //This doesn't do anything yet, since the error handling is still missing + if (status.getLevel() == ConnectionStatus.LEVEL_NONETWORK) { + noNetwork = true; + } else { + noNetwork = false; + if (isErrorHandling) { + isErrorHandling = false; + stop(); + start(); + } + } + } + } +} -- cgit v1.2.3 From 71d1c34319b703d909c882c24a436cd74ed42cc0 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 30 May 2022 23:45:34 +0200 Subject: implement a build time config variable to prefer obfsvpn lib over shapeshifter lib --- app/build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index 5c804d75..f788f590 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -43,6 +43,8 @@ android { buildConfigField 'boolean', 'allow_manual_gateway_selection', 'true' // grey out background in EipFragment (main screen) if VPN is not running buildConfigField 'boolean', 'use_color_filter', 'true' + // decide if we use obfsvpn or shapeshifter as obfs4 lib + buildConfigField 'boolean', 'use_obfsvpn', 'true' // static update url pointing to the latest stable release apk buildConfigField "String", "update_apk_url", '"https://dl.bitmask.net/client/android/Bitmask-Android-latest.apk"' @@ -133,6 +135,8 @@ android { buildConfigField 'boolean', 'allow_manual_gateway_selection', 'true' // grey out background in EipFragment (main screen) if VPN is not running buildConfigField 'boolean', 'use_color_filter', 'false' + // decide if we use obfsvpn or shapeshifter as obfs4 lib + buildConfigField 'boolean', 'use_obfsvpn', 'true' //Build Config Fields for automatic apk update checks -- cgit v1.2.3 From 61bfc6b6d3ad830a8a7569ea31399e93f48dd38d Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 30 May 2022 23:50:50 +0200 Subject: obfuscate vpn traffic using either shapeshfiter or obfsvpn --- .../de/blinkt/openvpn/core/OpenVPNService.java | 17 ++++++++++++++- .../openvpn/core/connection/Obfs4Connection.java | 23 +++++++++++++++------ .../leap/bitmaskclient/base/models/Constants.java | 1 + .../leap/bitmaskclient/eip/VpnConfigGenerator.java | 24 +++++++++++++++++++--- .../pluggableTransports/Obfs4Options.java | 4 +++- .../java/de/blinkt/openvpn/VpnProfileTest.java | 2 +- bitmaskcore | 2 +- 7 files changed, 60 insertions(+), 13 deletions(-) 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 d624af80..6edbbab4 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -43,10 +43,12 @@ import de.blinkt.openvpn.core.VpnStatus.ByteCountListener; import de.blinkt.openvpn.core.VpnStatus.StateListener; import de.blinkt.openvpn.core.connection.Connection; import de.blinkt.openvpn.core.connection.Obfs4Connection; +import se.leap.bitmaskclient.BuildConfig; 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.ObfsVpnClient; import se.leap.bitmaskclient.pluggableTransports.Shapeshifter; import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_CONNECTED; @@ -89,6 +91,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac private Runnable mOpenVPNThread; private VpnNotificationManager notificationManager; private Shapeshifter shapeshifter; + private ObfsVpnClient obfsVpnClient; private FirewallManager firewallManager; private final IBinder mBinder = new IOpenVPNServiceInternal.Stub() { @@ -241,6 +244,9 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac if (shapeshifter != null) { shapeshifter.stop(); shapeshifter = null; + } else if (obfsVpnClient != null) { + obfsVpnClient.stop(); + obfsVpnClient = null; } VpnStatus.updateStateString("NOPROCESS", "VPN STOPPED", R.string.state_noprocess, ConnectionStatus.LEVEL_NOTCONNECTED); } @@ -412,7 +418,12 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac if (mProfile.mUsePluggableTransports && connection instanceof Obfs4Connection) { Obfs4Connection obfs4Connection = (Obfs4Connection) connection; - if (shapeshifter == null) { + if (BuildConfig.use_obfsvpn) { + if (obfsVpnClient == null) { + obfsVpnClient = new ObfsVpnClient(obfs4Connection.getDispatcherOptions()); + obfsVpnClient.start(); + } + } else if (shapeshifter == null) { shapeshifter = new Shapeshifter(obfs4Connection.getDispatcherOptions()); shapeshifter.start(); } @@ -474,6 +485,10 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac Log.d(TAG, "-> stop shapeshifter"); shapeshifter.stop(); shapeshifter = null; + } else if (obfsVpnClient != null) { + Log.d(TAG, "-> stop obfsvpnClient"); + obfsVpnClient.stop(); + obfsVpnClient = null; } try { Thread.sleep(1000); 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 82a7a6aa..393afd94 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,6 +1,8 @@ package de.blinkt.openvpn.core.connection; +import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.pluggableTransports.Obfs4Options; +import se.leap.bitmaskclient.pluggableTransports.ObfsVpnClient; import static se.leap.bitmaskclient.pluggableTransports.Shapeshifter.DISPATCHER_IP; import static se.leap.bitmaskclient.pluggableTransports.Shapeshifter.DISPATCHER_PORT; @@ -16,14 +18,23 @@ public class Obfs4Connection extends Connection { private Obfs4Options options; public Obfs4Connection(Obfs4Options options) { - setUseUdp(false); - setServerName(DISPATCHER_IP); - setServerPort(DISPATCHER_PORT); - setProxyName(""); - setProxyPort(""); + if (BuildConfig.use_obfsvpn) { + setUseUdp(options.udp); + setServerName(options.remoteIP); + setServerPort(options.remotePort); + setProxyName(ObfsVpnClient.SOCKS_IP); + setProxyPort(ObfsVpnClient.SOCKS_PORT); + setProxyType(ProxyType.SOCKS5); + } else { + setUseUdp(false); + setServerName(DISPATCHER_IP); + setServerPort(DISPATCHER_PORT); + setProxyName(""); + setProxyPort(""); + setProxyType(ProxyType.NONE); + } setProxyAuthUser(null); setProxyAuthPassword(null); - setProxyType(ProxyType.NONE); setUseProxyAuth(false); this.options = options; } 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 bde909ba..d7a54fcc 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 @@ -163,6 +163,7 @@ public interface Constants { String IP_ADDRESS = "ip_address"; String IP_ADDRESS6 = "ip_address6"; String REMOTE = "remote"; + String SOCKS_PROXY = "socks-proxy"; String PORTS = "ports"; String PROTOCOLS = "protocols"; String UDP = "udp"; 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 5ddb74ab..061c1aa3 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -31,6 +31,7 @@ import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConfigParser; import de.blinkt.openvpn.core.VpnStatus; import de.blinkt.openvpn.core.connection.Connection; +import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.utils.ConfigHelper; import se.leap.bitmaskclient.pluggableTransports.Obfs4Options; @@ -46,9 +47,12 @@ import static se.leap.bitmaskclient.base.models.Constants.PROTOCOLS; 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.REMOTE; +import static se.leap.bitmaskclient.base.models.Constants.SOCKS_PROXY; import static se.leap.bitmaskclient.base.models.Constants.TRANSPORT; import static se.leap.bitmaskclient.base.models.Constants.TYPE; import static se.leap.bitmaskclient.base.models.Constants.UDP; +import static se.leap.bitmaskclient.pluggableTransports.ObfsVpnClient.SOCKS_IP; +import static se.leap.bitmaskclient.pluggableTransports.ObfsVpnClient.SOCKS_PORT; import static se.leap.bitmaskclient.pluggableTransports.Shapeshifter.DISPATCHER_IP; import static se.leap.bitmaskclient.pluggableTransports.Shapeshifter.DISPATCHER_PORT; @@ -140,7 +144,7 @@ public class VpnConfigGenerator { String cert = transportOptions.getString("cert"); String port = obfs4Transport.getJSONArray(PORTS).getString(0); String ip = gateway.getString(IP_ADDRESS); - return new Obfs4Options(ip, port, cert, iatMode); + return new Obfs4Options(ip, port, cert, iatMode, false); } private String generalConfiguration() { @@ -321,10 +325,24 @@ public class VpnConfigGenerator { return; } + JSONArray ports = obfs4Transport.getJSONArray(PORTS); + if (ports.isNull(0)){ + VpnStatus.logError("Misconfigured provider: no ports defined in obfs4 transport JSON."); + return; + } + String route = "route " + ipAddress + " 255.255.255.255 net_gateway" + newLine; stringBuilder.append(route); - String remote = REMOTE + " " + DISPATCHER_IP + " " + DISPATCHER_PORT + " tcp" + newLine; - stringBuilder.append(remote); + if (BuildConfig.use_obfsvpn) { + String proxy = SOCKS_PROXY + " " + SOCKS_IP + " " + SOCKS_PORT + newLine; + stringBuilder.append(proxy); + + String remote = REMOTE + " " + ipAddress + " " + ports.getString(0) + newLine; + stringBuilder.append(remote); + } else { + String remote = REMOTE + " " + DISPATCHER_IP + " " + DISPATCHER_PORT + " tcp" + newLine; + stringBuilder.append(remote); + } } private String secretsConfiguration() { diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java index 2f9cb732..ab6ea445 100644 --- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java @@ -7,12 +7,14 @@ public class Obfs4Options implements Serializable { public String iatMode; public String remoteIP; public String remotePort; + public boolean udp; - public Obfs4Options(String remoteIP, String remotePort, String cert, String iatMode) { + public Obfs4Options(String remoteIP, String remotePort, String cert, String iatMode, boolean udp) { this.cert = cert; this.iatMode = iatMode; this.remoteIP = remoteIP; this.remotePort = remotePort; + this.udp = udp; } } diff --git a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java index e8a93b75..34eea5e9 100644 --- a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java +++ b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java @@ -59,7 +59,7 @@ public class VpnProfileTest { @Test public void toJson_obfs4() throws JSONException { VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4); - mockVpnProfile.mConnections[0] = new Obfs4Connection(new Obfs4Options("192.168.0.1", "1234", "CERT", "1")); + mockVpnProfile.mConnections[0] = new Obfs4Connection(new Obfs4Options("192.168.0.1", "1234", "CERT", "1", false)); mockVpnProfile.mConnections[0].setUseUdp(false); mockVpnProfile.mLastUsed = 0; String s = mockVpnProfile.toJson(); diff --git a/bitmaskcore b/bitmaskcore index a82335ae..7185b55d 160000 --- a/bitmaskcore +++ b/bitmaskcore @@ -1 +1 @@ -Subproject commit a82335aef6cdd2bd0499d8828d6d479f2ded0876 +Subproject commit 7185b55d5aebb10e2d6b18f990da58aea26c15aa -- cgit v1.2.3 From 685da9ad4a80cd42cbe4c6fcd8383bcdd843ec6d Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 30 May 2022 23:54:42 +0200 Subject: update bitmaskcore aar's --- .../bitmaskcore_arm64-sources.jar | Bin 8989 -> 10185 bytes lib-bitmask-core-arm64/bitmaskcore_arm64.aar | Bin 6241276 -> 6360485 bytes lib-bitmask-core-armv7/bitmaskcore_arm-sources.jar | Bin 8989 -> 10185 bytes lib-bitmask-core-armv7/bitmaskcore_arm.aar | Bin 6373139 -> 6419708 bytes lib-bitmask-core-web/bitmaskcore_web-sources.jar | Bin 10846 -> 12042 bytes lib-bitmask-core-web/bitmaskcore_web.aar | Bin 27274068 -> 27715085 bytes lib-bitmask-core-x86/bitmaskcore_x86-sources.jar | Bin 8989 -> 10185 bytes lib-bitmask-core-x86/bitmaskcore_x86.aar | Bin 6796676 -> 6843072 bytes .../bitmaskcore_x86_64-sources.jar | Bin 8989 -> 10185 bytes lib-bitmask-core-x86_64/bitmaskcore_x86_64.aar | Bin 7031949 -> 7307748 bytes lib-bitmask-core/bitmaskcore-sources.jar | Bin 8989 -> 10185 bytes lib-bitmask-core/bitmaskcore.aar | Bin 26405988 -> 26890543 bytes 12 files changed, 0 insertions(+), 0 deletions(-) diff --git a/lib-bitmask-core-arm64/bitmaskcore_arm64-sources.jar b/lib-bitmask-core-arm64/bitmaskcore_arm64-sources.jar index 5b475b1f..043de8ec 100644 Binary files a/lib-bitmask-core-arm64/bitmaskcore_arm64-sources.jar and b/lib-bitmask-core-arm64/bitmaskcore_arm64-sources.jar differ diff --git a/lib-bitmask-core-arm64/bitmaskcore_arm64.aar b/lib-bitmask-core-arm64/bitmaskcore_arm64.aar index 5a12115c..ebd8cca3 100644 Binary files a/lib-bitmask-core-arm64/bitmaskcore_arm64.aar and b/lib-bitmask-core-arm64/bitmaskcore_arm64.aar differ diff --git a/lib-bitmask-core-armv7/bitmaskcore_arm-sources.jar b/lib-bitmask-core-armv7/bitmaskcore_arm-sources.jar index 5b475b1f..043de8ec 100644 Binary files a/lib-bitmask-core-armv7/bitmaskcore_arm-sources.jar and b/lib-bitmask-core-armv7/bitmaskcore_arm-sources.jar differ diff --git a/lib-bitmask-core-armv7/bitmaskcore_arm.aar b/lib-bitmask-core-armv7/bitmaskcore_arm.aar index d947ed88..fcdde062 100644 Binary files a/lib-bitmask-core-armv7/bitmaskcore_arm.aar and b/lib-bitmask-core-armv7/bitmaskcore_arm.aar differ diff --git a/lib-bitmask-core-web/bitmaskcore_web-sources.jar b/lib-bitmask-core-web/bitmaskcore_web-sources.jar index 9bbe2dff..9d485a32 100644 Binary files a/lib-bitmask-core-web/bitmaskcore_web-sources.jar and b/lib-bitmask-core-web/bitmaskcore_web-sources.jar differ diff --git a/lib-bitmask-core-web/bitmaskcore_web.aar b/lib-bitmask-core-web/bitmaskcore_web.aar index b5c931d6..8e0b5472 100644 Binary files a/lib-bitmask-core-web/bitmaskcore_web.aar and b/lib-bitmask-core-web/bitmaskcore_web.aar differ diff --git a/lib-bitmask-core-x86/bitmaskcore_x86-sources.jar b/lib-bitmask-core-x86/bitmaskcore_x86-sources.jar index 5b475b1f..043de8ec 100644 Binary files a/lib-bitmask-core-x86/bitmaskcore_x86-sources.jar and b/lib-bitmask-core-x86/bitmaskcore_x86-sources.jar differ diff --git a/lib-bitmask-core-x86/bitmaskcore_x86.aar b/lib-bitmask-core-x86/bitmaskcore_x86.aar index eb0ae963..d7d00a63 100644 Binary files a/lib-bitmask-core-x86/bitmaskcore_x86.aar and b/lib-bitmask-core-x86/bitmaskcore_x86.aar differ diff --git a/lib-bitmask-core-x86_64/bitmaskcore_x86_64-sources.jar b/lib-bitmask-core-x86_64/bitmaskcore_x86_64-sources.jar index 5b475b1f..043de8ec 100644 Binary files a/lib-bitmask-core-x86_64/bitmaskcore_x86_64-sources.jar and b/lib-bitmask-core-x86_64/bitmaskcore_x86_64-sources.jar differ diff --git a/lib-bitmask-core-x86_64/bitmaskcore_x86_64.aar b/lib-bitmask-core-x86_64/bitmaskcore_x86_64.aar index 7f428f45..4bd349fe 100644 Binary files a/lib-bitmask-core-x86_64/bitmaskcore_x86_64.aar and b/lib-bitmask-core-x86_64/bitmaskcore_x86_64.aar differ diff --git a/lib-bitmask-core/bitmaskcore-sources.jar b/lib-bitmask-core/bitmaskcore-sources.jar index 5b475b1f..043de8ec 100644 Binary files a/lib-bitmask-core/bitmaskcore-sources.jar and b/lib-bitmask-core/bitmaskcore-sources.jar differ diff --git a/lib-bitmask-core/bitmaskcore.aar b/lib-bitmask-core/bitmaskcore.aar index fe28f633..6f7c6c40 100644 Binary files a/lib-bitmask-core/bitmaskcore.aar and b/lib-bitmask-core/bitmaskcore.aar differ -- cgit v1.2.3 From 0fef9e2e19ccc77456a66f4f174b1fea94c1260f Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 3 Jun 2022 18:41:59 +0200 Subject: ensure socks proxy has started before openvpn tries to use it --- .../pluggableTransports/ObfsVpnClient.java | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java index c871c708..69210881 100644 --- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java @@ -27,18 +27,16 @@ public class ObfsVpnClient implements Observer { } public void start() { - new Thread(() -> { - synchronized (LOCK) { - Log.d(TAG, "aquired LOCK"); - new Thread(obfsVpnClient::start).start(); - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - Log.d(TAG, "returning LOCK after 500 ms"); + synchronized (LOCK) { + Log.d(TAG, "aquired LOCK"); + new Thread(obfsVpnClient::start).start(); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); } - }).start(); + Log.d(TAG, "returning LOCK after 500 ms"); + } } public void stop() { -- cgit v1.2.3 From e23a3bf428ce8e99c55746a2cc267e0a3a5b96d3 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sun, 26 Jun 2022 19:10:45 +0200 Subject: restart obfsvpn proxy on reconnects or when connecting to new gateways --- app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) 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 6edbbab4..e4323b6c 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -244,7 +244,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac if (shapeshifter != null) { shapeshifter.stop(); shapeshifter = null; - } else if (obfsVpnClient != null) { + } else if (obfsVpnClient != null && obfsVpnClient.isStarted()) { obfsVpnClient.stop(); obfsVpnClient = null; } @@ -419,10 +419,11 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac if (mProfile.mUsePluggableTransports && connection instanceof Obfs4Connection) { Obfs4Connection obfs4Connection = (Obfs4Connection) connection; if (BuildConfig.use_obfsvpn) { - if (obfsVpnClient == null) { - obfsVpnClient = new ObfsVpnClient(obfs4Connection.getDispatcherOptions()); - obfsVpnClient.start(); + if (obfsVpnClient != null && obfsVpnClient.isStarted()) { + obfsVpnClient.stop(); } + obfsVpnClient = new ObfsVpnClient(obfs4Connection.getDispatcherOptions()); + obfsVpnClient.start(); } else if (shapeshifter == null) { shapeshifter = new Shapeshifter(obfs4Connection.getDispatcherOptions()); shapeshifter.start(); @@ -485,7 +486,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac Log.d(TAG, "-> stop shapeshifter"); shapeshifter.stop(); shapeshifter = null; - } else if (obfsVpnClient != null) { + } else if (obfsVpnClient != null && obfsVpnClient.isStarted()) { Log.d(TAG, "-> stop obfsvpnClient"); obfsVpnClient.stop(); obfsVpnClient = null; -- cgit v1.2.3 From bfa89faf60d1c88250745f617ff38b13e2a7e34d Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sun, 26 Jun 2022 19:19:31 +0200 Subject: update ObfsvpnClient to latest obfsvpn api: handle bubbled up errors --- .../pluggableTransports/ObfsVpnClient.java | 22 ++++++++++++++++++++-- bitmaskcore | 2 +- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java index 69210881..632dc878 100644 --- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java @@ -29,7 +29,14 @@ public class ObfsVpnClient implements Observer { public void start() { synchronized (LOCK) { Log.d(TAG, "aquired LOCK"); - new Thread(obfsVpnClient::start).start(); + new Thread(() -> { + try { + obfsVpnClient.start(); + } catch (Exception e) { + e.printStackTrace(); + } + }).start(); + try { Thread.sleep(500); } catch (InterruptedException e) { @@ -42,10 +49,21 @@ public class ObfsVpnClient implements Observer { public void stop() { synchronized (LOCK) { Log.d(TAG, "stopping obfsVpnClient..."); - obfsVpnClient.stop(); + try { + obfsVpnClient.stop(); + Thread.sleep(500); + } catch (Exception e) { + e.printStackTrace(); + VpnStatus.logError("[obfsvpn] " + e.getLocalizedMessage()); + } + Log.d(TAG, "stopping obfsVpnClient releasing LOCK ..."); } } + public boolean isStarted() { + return obfsVpnClient.isStarted(); + } + @Override public void update(Observable observable, Object arg) { if (observable instanceof EipStatus) { diff --git a/bitmaskcore b/bitmaskcore index 7185b55d..f5b935b7 160000 --- a/bitmaskcore +++ b/bitmaskcore @@ -1 +1 @@ -Subproject commit 7185b55d5aebb10e2d6b18f990da58aea26c15aa +Subproject commit f5b935b77204291ded7d7b1304dc6026e699166c -- cgit v1.2.3 From fece9e3133a39b885d014cabf62cd905b6667348 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sun, 26 Jun 2022 19:33:20 +0200 Subject: handle multi-threaded access to obfsvpn client state flags correctly --- .../bitmaskclient/pluggableTransports/ObfsVpnClient.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java index 632dc878..635f795d 100644 --- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java @@ -4,6 +4,7 @@ import android.util.Log; import java.util.Observable; import java.util.Observer; +import java.util.concurrent.atomic.AtomicBoolean; import client.Client_; import de.blinkt.openvpn.core.ConnectionStatus; @@ -15,9 +16,9 @@ public class ObfsVpnClient implements Observer { public static final String SOCKS_IP = "127.0.0.1"; private static final String TAG = ObfsVpnClient.class.getSimpleName(); - private boolean noNetwork; + private volatile boolean noNetwork; // TODO: implement error signaling go->java - private boolean isErrorHandling; + private AtomicBoolean isErrorHandling = new AtomicBoolean(false); private final client.Client_ obfsVpnClient; private final Object LOCK = new Object(); @@ -34,6 +35,9 @@ public class ObfsVpnClient implements Observer { obfsVpnClient.start(); } catch (Exception e) { e.printStackTrace(); + if (noNetwork) { + isErrorHandling.set(true); + } } }).start(); @@ -56,6 +60,7 @@ public class ObfsVpnClient implements Observer { e.printStackTrace(); VpnStatus.logError("[obfsvpn] " + e.getLocalizedMessage()); } + isErrorHandling.set(false); Log.d(TAG, "stopping obfsVpnClient releasing LOCK ..."); } } @@ -73,8 +78,7 @@ public class ObfsVpnClient implements Observer { noNetwork = true; } else { noNetwork = false; - if (isErrorHandling) { - isErrorHandling = false; + if (isErrorHandling.getAndSet(false)) { stop(); start(); } -- cgit v1.2.3 From 38e9d4afbd408b25d569e5c80cd0b288a28acd07 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sun, 26 Jun 2022 19:41:04 +0200 Subject: add BuildConfig fields to hardcode a particular obfsvpn proxy --- app/build.gradle | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index f788f590..73dfcc0c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -45,6 +45,11 @@ android { buildConfigField 'boolean', 'use_color_filter', '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 'boolean', 'obfsvpn_pinning', 'false' + buildConfigField "String", "obfsvpn_port", '""' + buildConfigField "String", "obfsvpn_ip", '""' + buildConfigField "String", "obfsvpn_cert", '""' // static update url pointing to the latest stable release apk buildConfigField "String", "update_apk_url", '"https://dl.bitmask.net/client/android/Bitmask-Android-latest.apk"' @@ -137,6 +142,11 @@ android { buildConfigField 'boolean', 'use_color_filter', 'false' // 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 'boolean', 'obfsvpn_pinning', 'false' + buildConfigField "String", "obfsvpn_port", '""' + buildConfigField "String", "obfsvpn_ip", '""' + buildConfigField "String", "obfsvpn_cert", '""' //Build Config Fields for automatic apk update checks -- cgit v1.2.3 From 5afdb3d3ed61efd547b3756e5c1c4f119e126500 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 27 Jun 2022 23:06:09 +0200 Subject: allow to pin a custom obfs4 bridge during compile time --- app/build.gradle | 2 ++ .../openvpn/core/connection/Obfs4Connection.java | 5 +++-- .../leap/bitmaskclient/eip/VpnConfigGenerator.java | 21 +++++++++++++++++---- .../pluggableTransports/Obfs4Options.java | 1 + 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 73dfcc0c..3e4f4ee2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -50,6 +50,7 @@ android { buildConfigField "String", "obfsvpn_port", '""' buildConfigField "String", "obfsvpn_ip", '""' buildConfigField "String", "obfsvpn_cert", '""' + buildConfigField 'boolean', 'obfsvpn_use_kcp', 'false' // static update url pointing to the latest stable release apk buildConfigField "String", "update_apk_url", '"https://dl.bitmask.net/client/android/Bitmask-Android-latest.apk"' @@ -147,6 +148,7 @@ android { buildConfigField "String", "obfsvpn_port", '""' buildConfigField "String", "obfsvpn_ip", '""' buildConfigField "String", "obfsvpn_cert", '""' + buildConfigField 'boolean', 'obfsvpn_use_kcp', 'false' //Build Config Fields for automatic apk update checks 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 393afd94..7cfe4988 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 @@ -19,20 +19,21 @@ public class Obfs4Connection extends Connection { public Obfs4Connection(Obfs4Options options) { if (BuildConfig.use_obfsvpn) { - setUseUdp(options.udp); setServerName(options.remoteIP); setServerPort(options.remotePort); setProxyName(ObfsVpnClient.SOCKS_IP); setProxyPort(ObfsVpnClient.SOCKS_PORT); setProxyType(ProxyType.SOCKS5); } else { - setUseUdp(false); 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); setProxyAuthUser(null); setProxyAuthPassword(null); setUseProxyAuth(false); 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 061c1aa3..695e3b50 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -56,6 +56,8 @@ import static se.leap.bitmaskclient.pluggableTransports.ObfsVpnClient.SOCKS_PORT import static se.leap.bitmaskclient.pluggableTransports.Shapeshifter.DISPATCHER_IP; import static se.leap.bitmaskclient.pluggableTransports.Shapeshifter.DISPATCHER_PORT; +import android.os.Build; + public class VpnConfigGenerator { private JSONObject generalConfiguration; private JSONObject gateway; @@ -144,7 +146,15 @@ public class VpnConfigGenerator { String cert = transportOptions.getString("cert"); String port = obfs4Transport.getJSONArray(PORTS).getString(0); String ip = gateway.getString(IP_ADDRESS); - return new Obfs4Options(ip, port, cert, iatMode, false); + boolean udp = false; + + if (BuildConfig.obfsvpn_pinning) { + cert = BuildConfig.obfsvpn_cert; + port = BuildConfig.obfsvpn_port; + ip = BuildConfig.obfsvpn_port; + udp = BuildConfig.obfsvpn_use_kcp; + } + return new Obfs4Options(ip, port, cert, iatMode, udp); } private String generalConfiguration() { @@ -334,10 +344,13 @@ public class VpnConfigGenerator { String route = "route " + ipAddress + " 255.255.255.255 net_gateway" + newLine; stringBuilder.append(route); if (BuildConfig.use_obfsvpn) { - String proxy = SOCKS_PROXY + " " + SOCKS_IP + " " + SOCKS_PORT + newLine; - stringBuilder.append(proxy); + String remote; + if (BuildConfig.obfsvpn_pinning) { + remote = REMOTE + " " + BuildConfig.obfsvpn_ip + " " + BuildConfig.obfsvpn_port + newLine; + } else { + remote = REMOTE + " " + ipAddress + " " + ports.getString(0) + newLine; + } - String remote = REMOTE + " " + ipAddress + " " + ports.getString(0) + newLine; stringBuilder.append(remote); } else { String remote = REMOTE + " " + DISPATCHER_IP + " " + DISPATCHER_PORT + " tcp" + newLine; diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java index ab6ea445..b96f88ca 100644 --- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java @@ -7,6 +7,7 @@ public class Obfs4Options implements Serializable { public String iatMode; public String remoteIP; public String remotePort; + // openvpn is still using tcp, obfs4 is wrapped in kcp, if udp == true public boolean udp; public Obfs4Options(String remoteIP, String remotePort, String cert, String iatMode, boolean udp) { -- cgit v1.2.3 From c0b1e3148dbc26417df21e90ab8e7d8338c7240a Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 27 Jun 2022 23:09:04 +0200 Subject: define logging interface for obfsvpn --- .../bitmaskclient/pluggableTransports/ObfsVpnClient.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java index 635f795d..5b8b7326 100644 --- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java @@ -8,9 +8,10 @@ import java.util.concurrent.atomic.AtomicBoolean; 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 Observer { +public class ObfsVpnClient implements Observer, client.EventLogger { public static final String SOCKS_PORT = "4430"; public static final String SOCKS_IP = "127.0.0.1"; @@ -25,6 +26,7 @@ public class ObfsVpnClient implements Observer { public ObfsVpnClient(Obfs4Options options) { obfsVpnClient = new Client_(options.udp, SOCKS_IP+":"+SOCKS_PORT, options.cert); + obfsVpnClient.setEventLogger(this); } public void start() { @@ -35,6 +37,7 @@ public class ObfsVpnClient implements Observer { obfsVpnClient.start(); } catch (Exception e) { e.printStackTrace(); + VpnStatus.logError("[obfsvpn] " + e.getLocalizedMessage()); if (noNetwork) { isErrorHandling.set(true); } @@ -85,4 +88,15 @@ public class ObfsVpnClient implements Observer { } } } + + @Override + public void error(String s) { + VpnStatus.logError("[obfsvpn] " + s); + } + + @Override + public void log(String state, String message) { + VpnStatus.logDebug("[obfsvpn] " + state + " " + message); + } + } -- cgit v1.2.3 From 05902206cacaba1342d312003120b10686bf4433 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 11 Jul 2022 21:52:46 +0200 Subject: move BuildConfig variable use_obfsvpn to a static method in ConfigHelper, which can be mocked for testing --- .../de/blinkt/openvpn/core/OpenVPNService.java | 14 ++++---- .../openvpn/core/connection/Obfs4Connection.java | 10 +++--- .../bitmaskclient/base/utils/ConfigHelper.java | 7 ++++ .../leap/bitmaskclient/eip/VpnConfigGenerator.java | 42 ++++++++++------------ 4 files changed, 38 insertions(+), 35 deletions(-) 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 e4323b6c..987708f4 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -5,6 +5,12 @@ package de.blinkt.openvpn.core; +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.ConfigHelper.ObfsVpnHelper.useObfsVpn; + import android.Manifest.permission; import android.annotation.TargetApi; import android.app.Notification; @@ -43,7 +49,6 @@ import de.blinkt.openvpn.core.VpnStatus.ByteCountListener; import de.blinkt.openvpn.core.VpnStatus.StateListener; import de.blinkt.openvpn.core.connection.Connection; import de.blinkt.openvpn.core.connection.Obfs4Connection; -import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.eip.EipStatus; import se.leap.bitmaskclient.eip.VpnNotificationManager; @@ -51,11 +56,6 @@ import se.leap.bitmaskclient.firewall.FirewallManager; import se.leap.bitmaskclient.pluggableTransports.ObfsVpnClient; import se.leap.bitmaskclient.pluggableTransports.Shapeshifter; -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; - public class OpenVPNService extends VpnService implements StateListener, Callback, ByteCountListener, IOpenVPNServiceInternal, VpnNotificationManager.VpnServiceCallback { public static final String TAG = OpenVPNService.class.getSimpleName(); @@ -418,7 +418,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac if (mProfile.mUsePluggableTransports && connection instanceof Obfs4Connection) { Obfs4Connection obfs4Connection = (Obfs4Connection) connection; - if (BuildConfig.use_obfsvpn) { + if (useObfsVpn()) { if (obfsVpnClient != null && obfsVpnClient.isStarted()) { obfsVpnClient.stop(); } 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 7cfe4988..d3cfdc83 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,12 @@ package de.blinkt.openvpn.core.connection; -import se.leap.bitmaskclient.BuildConfig; -import se.leap.bitmaskclient.pluggableTransports.Obfs4Options; -import se.leap.bitmaskclient.pluggableTransports.ObfsVpnClient; - +import static se.leap.bitmaskclient.base.utils.ConfigHelper.ObfsVpnHelper.useObfsVpn; import static se.leap.bitmaskclient.pluggableTransports.Shapeshifter.DISPATCHER_IP; import static se.leap.bitmaskclient.pluggableTransports.Shapeshifter.DISPATCHER_PORT; +import se.leap.bitmaskclient.pluggableTransports.Obfs4Options; +import se.leap.bitmaskclient.pluggableTransports.ObfsVpnClient; + /** * Created by cyberta on 08.03.19. @@ -18,7 +18,7 @@ public class Obfs4Connection extends Connection { private Obfs4Options options; public Obfs4Connection(Obfs4Options options) { - if (BuildConfig.use_obfsvpn) { + if (useObfsVpn()) { setServerName(options.remoteIP); setServerPort(options.remotePort); setProxyName(ObfsVpnClient.SOCKS_IP); 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 ca1261a8..8ac5baf0 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 @@ -274,4 +274,11 @@ public class ConfigHelper { return matcher.matches(); } + // ObfsVpnHelper class allows us to mock BuildConfig.use_obfsvpn while + // not mocking the whole ConfigHelper class + public static class ObfsVpnHelper { + public static boolean useObfsVpn() { + return BuildConfig.use_obfsvpn; + } + } } 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 695e3b50..62c267ac 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -16,6 +16,24 @@ */ package se.leap.bitmaskclient.eip; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; +import static se.leap.bitmaskclient.base.models.Constants.CAPABILITIES; +import static se.leap.bitmaskclient.base.models.Constants.IP_ADDRESS; +import static se.leap.bitmaskclient.base.models.Constants.IP_ADDRESS6; +import static se.leap.bitmaskclient.base.models.Constants.OPTIONS; +import static se.leap.bitmaskclient.base.models.Constants.PORTS; +import static se.leap.bitmaskclient.base.models.Constants.PROTOCOLS; +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.REMOTE; +import static se.leap.bitmaskclient.base.models.Constants.TRANSPORT; +import static se.leap.bitmaskclient.base.models.Constants.TYPE; +import static se.leap.bitmaskclient.base.models.Constants.UDP; +import static se.leap.bitmaskclient.base.utils.ConfigHelper.ObfsVpnHelper.useObfsVpn; +import static se.leap.bitmaskclient.pluggableTransports.Shapeshifter.DISPATCHER_IP; +import static se.leap.bitmaskclient.pluggableTransports.Shapeshifter.DISPATCHER_PORT; + import androidx.annotation.VisibleForTesting; import org.json.JSONArray; @@ -36,28 +54,6 @@ import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.utils.ConfigHelper; import se.leap.bitmaskclient.pluggableTransports.Obfs4Options; -import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; -import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; -import static se.leap.bitmaskclient.base.models.Constants.CAPABILITIES; -import static se.leap.bitmaskclient.base.models.Constants.IP_ADDRESS; -import static se.leap.bitmaskclient.base.models.Constants.IP_ADDRESS6; -import static se.leap.bitmaskclient.base.models.Constants.OPTIONS; -import static se.leap.bitmaskclient.base.models.Constants.PORTS; -import static se.leap.bitmaskclient.base.models.Constants.PROTOCOLS; -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.REMOTE; -import static se.leap.bitmaskclient.base.models.Constants.SOCKS_PROXY; -import static se.leap.bitmaskclient.base.models.Constants.TRANSPORT; -import static se.leap.bitmaskclient.base.models.Constants.TYPE; -import static se.leap.bitmaskclient.base.models.Constants.UDP; -import static se.leap.bitmaskclient.pluggableTransports.ObfsVpnClient.SOCKS_IP; -import static se.leap.bitmaskclient.pluggableTransports.ObfsVpnClient.SOCKS_PORT; -import static se.leap.bitmaskclient.pluggableTransports.Shapeshifter.DISPATCHER_IP; -import static se.leap.bitmaskclient.pluggableTransports.Shapeshifter.DISPATCHER_PORT; - -import android.os.Build; - public class VpnConfigGenerator { private JSONObject generalConfiguration; private JSONObject gateway; @@ -343,7 +339,7 @@ public class VpnConfigGenerator { String route = "route " + ipAddress + " 255.255.255.255 net_gateway" + newLine; stringBuilder.append(route); - if (BuildConfig.use_obfsvpn) { + if (useObfsVpn()) { String remote; if (BuildConfig.obfsvpn_pinning) { remote = REMOTE + " " + BuildConfig.obfsvpn_ip + " " + BuildConfig.obfsvpn_port + newLine; -- cgit v1.2.3 From f078acb0f084b550de48a778b8cc81f40a6f5df7 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 11 Jul 2022 22:21:37 +0200 Subject: fix and add tests for testing obfsvpn based openvpn config generation --- .../java/de/blinkt/openvpn/VpnProfileTest.java | 115 +++++++++++-- .../bitmaskclient/eip/ProviderApiManagerTest.java | 2 - .../bitmaskclient/eip/VpnConfigGeneratorTest.java | 183 +++++++++++++++++++-- .../leap/bitmaskclient/testutils/MockHelper.java | 1 - 4 files changed, 269 insertions(+), 32 deletions(-) diff --git a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java index 34eea5e9..4e51bbc1 100644 --- a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java +++ b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java @@ -1,32 +1,42 @@ package de.blinkt.openvpn; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.powermock.api.mockito.PowerMockito.mockStatic; +import static org.powermock.api.mockito.PowerMockito.when; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; + import org.json.JSONException; import org.json.JSONObject; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; import java.util.UUID; import de.blinkt.openvpn.core.connection.Obfs4Connection; import de.blinkt.openvpn.core.connection.OpenvpnConnection; +import se.leap.bitmaskclient.base.utils.ConfigHelper; import se.leap.bitmaskclient.pluggableTransports.Obfs4Options; -import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; -import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.powermock.api.mockito.PowerMockito.mockStatic; - -@PrepareForTest({UUID.class}) +@RunWith(PowerMockRunner.class) +@PrepareForTest({UUID.class, ConfigHelper.ObfsVpnHelper.class}) public class VpnProfileTest { private static final String OPENVPNCONNECTION_PROFILE = "{\"mAuthenticationType\":2,\"mName\":\"mockProfile\",\"mTLSAuthDirection\":\"\",\"mUseLzo\":false,\"mUseTLSAuth\":false,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mOverrideDNS\":false,\"mSearchDomain\":\"blinkt.de\",\"mUseDefaultRoute\":true,\"mUsePull\":true,\"mCheckRemoteCN\":true,\"mExpectTLSCert\":false,\"mRemoteCN\":\"\",\"mPassword\":\"\",\"mUsername\":\"\",\"mRoutenopull\":false,\"mUseRandomHostname\":false,\"mUseFloat\":false,\"mUseCustomConfig\":false,\"mCustomConfigOptions\":\"\",\"mVerb\":\"1\",\"mCipher\":\"\",\"mDataCiphers\":\"\",\"mNobind\":true,\"mUseDefaultRoutev6\":true,\"mCustomRoutesv6\":\"\",\"mKeyPassword\":\"\",\"mPersistTun\":false,\"mConnectRetryMax\":\"-1\",\"mConnectRetry\":\"2\",\"mConnectRetryMaxTime\":\"300\",\"mUserEditable\":true,\"mAuth\":\"\",\"mX509AuthType\":3,\"mAllowLocalLAN\":false,\"mMssFix\":0,\"mConnections\":[{\"mServerName\":\"openvpn.example.com\",\"mServerPort\":\"1194\",\"mUseUdp\":false,\"mCustomConfiguration\":\"\",\"mUseCustomConfig\":false,\"mEnabled\":true,\"mConnectTimeout\":0,\"mProxyType\":\"NONE\",\"mProxyName\":\"proxy.example.com\",\"mProxyPort\":\"8080\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.OpenvpnConnection\"}],\"mRemoteRandom\":false,\"mAllowedAppsVpn\":[],\"mAllowedAppsVpnAreDisallowed\":true,\"mAllowAppVpnBypass\":false,\"mAuthRetry\":0,\"mTunMtu\":0,\"mPushPeerInfo\":false,\"mVersion\":0,\"mLastUsed\":0,\"mServerName\":\"openvpn.example.com\",\"mServerPort\":\"1194\",\"mUseUdp\":true,\"mTemporaryProfile\":false,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mProfileVersion\":7,\"mBlockUnusedAddressFamilies\":true,\"mUsePluggableTransports\":false}"; - private static final String OBFS4CONNECTION_PROFILE = "{\"mAuthenticationType\":2,\"mName\":\"mockProfile\",\"mTLSAuthDirection\":\"\",\"mUseLzo\":false,\"mUseTLSAuth\":false,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mOverrideDNS\":false,\"mSearchDomain\":\"blinkt.de\",\"mUseDefaultRoute\":true,\"mUsePull\":true,\"mCheckRemoteCN\":true,\"mExpectTLSCert\":false,\"mRemoteCN\":\"\",\"mPassword\":\"\",\"mUsername\":\"\",\"mRoutenopull\":false,\"mUseRandomHostname\":false,\"mUseFloat\":false,\"mUseCustomConfig\":false,\"mCustomConfigOptions\":\"\",\"mVerb\":\"1\",\"mCipher\":\"\",\"mDataCiphers\":\"\",\"mNobind\":true,\"mUseDefaultRoutev6\":true,\"mCustomRoutesv6\":\"\",\"mKeyPassword\":\"\",\"mPersistTun\":false,\"mConnectRetryMax\":\"-1\",\"mConnectRetry\":\"2\",\"mConnectRetryMaxTime\":\"300\",\"mUserEditable\":true,\"mAuth\":\"\",\"mX509AuthType\":3,\"mAllowLocalLAN\":false,\"mMssFix\":0,\"mConnections\":[{\"options\":{\"cert\":\"CERT\",\"iatMode\":\"1\",\"remoteIP\":\"192.168.0.1\",\"remotePort\":\"1234\"},\"mServerName\":\"127.0.0.1\",\"mServerPort\":\"4430\",\"mUseUdp\":false,\"mCustomConfiguration\":\"\",\"mUseCustomConfig\":false,\"mEnabled\":true,\"mConnectTimeout\":0,\"mProxyType\":\"NONE\",\"mProxyName\":\"\",\"mProxyPort\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\"}],\"mRemoteRandom\":false,\"mAllowedAppsVpn\":[],\"mAllowedAppsVpnAreDisallowed\":true,\"mAllowAppVpnBypass\":false,\"mAuthRetry\":0,\"mTunMtu\":0,\"mPushPeerInfo\":false,\"mVersion\":0,\"mLastUsed\":0,\"mServerName\":\"openvpn.example.com\",\"mServerPort\":\"1194\",\"mUseUdp\":true,\"mTemporaryProfile\":false,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mProfileVersion\":7,\"mBlockUnusedAddressFamilies\":true,\"mUsePluggableTransports\":true}"; + private static final String OBFS4CONNECTION_PROFILE = "{\"mAuthenticationType\":2,\"mName\":\"mockProfile\",\"mTLSAuthDirection\":\"\",\"mUseLzo\":false,\"mUseTLSAuth\":false,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mOverrideDNS\":false,\"mSearchDomain\":\"blinkt.de\",\"mUseDefaultRoute\":true,\"mUsePull\":true,\"mCheckRemoteCN\":true,\"mExpectTLSCert\":false,\"mRemoteCN\":\"\",\"mPassword\":\"\",\"mUsername\":\"\",\"mRoutenopull\":false,\"mUseRandomHostname\":false,\"mUseFloat\":false,\"mUseCustomConfig\":false,\"mCustomConfigOptions\":\"\",\"mVerb\":\"1\",\"mCipher\":\"\",\"mDataCiphers\":\"\",\"mNobind\":true,\"mUseDefaultRoutev6\":true,\"mCustomRoutesv6\":\"\",\"mKeyPassword\":\"\",\"mPersistTun\":false,\"mConnectRetryMax\":\"-1\",\"mConnectRetry\":\"2\",\"mConnectRetryMaxTime\":\"300\",\"mUserEditable\":true,\"mAuth\":\"\",\"mX509AuthType\":3,\"mAllowLocalLAN\":false,\"mMssFix\":0,\"mConnections\":[{\"options\":{\"udp\":false,\"cert\":\"CERT\",\"iatMode\":\"1\",\"remoteIP\":\"192.168.0.1\",\"remotePort\":\"1234\"},\"mServerName\":\"127.0.0.1\",\"mServerPort\":\"4430\",\"mUseUdp\":false,\"mCustomConfiguration\":\"\",\"mUseCustomConfig\":false,\"mEnabled\":true,\"mConnectTimeout\":0,\"mProxyType\":\"NONE\",\"mProxyName\":\"\",\"mProxyPort\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\"}],\"mRemoteRandom\":false,\"mAllowedAppsVpn\":[],\"mAllowedAppsVpnAreDisallowed\":true,\"mAllowAppVpnBypass\":false,\"mAuthRetry\":0,\"mTunMtu\":0,\"mPushPeerInfo\":false,\"mVersion\":0,\"mLastUsed\":0,\"mServerName\":\"openvpn.example.com\",\"mServerPort\":\"1194\",\"mUseUdp\":true,\"mTemporaryProfile\":false,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mProfileVersion\":7,\"mBlockUnusedAddressFamilies\":true,\"mUsePluggableTransports\":true}"; + private static final String OBFS4CONNECTION_PROFILE_OBFSVPN = "{\"mAuthenticationType\":2,\"mName\":\"mockProfile\",\"mTLSAuthDirection\":\"\",\"mUseLzo\":false,\"mUseTLSAuth\":false,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mOverrideDNS\":false,\"mSearchDomain\":\"blinkt.de\",\"mUseDefaultRoute\":true,\"mUsePull\":true,\"mCheckRemoteCN\":true,\"mExpectTLSCert\":false,\"mRemoteCN\":\"\",\"mPassword\":\"\",\"mUsername\":\"\",\"mRoutenopull\":false,\"mUseRandomHostname\":false,\"mUseFloat\":false,\"mUseCustomConfig\":false,\"mCustomConfigOptions\":\"\",\"mVerb\":\"1\",\"mCipher\":\"\",\"mDataCiphers\":\"\",\"mNobind\":true,\"mUseDefaultRoutev6\":true,\"mCustomRoutesv6\":\"\",\"mKeyPassword\":\"\",\"mPersistTun\":false,\"mConnectRetryMax\":\"-1\",\"mConnectRetry\":\"2\",\"mConnectRetryMaxTime\":\"300\",\"mUserEditable\":true,\"mAuth\":\"\",\"mX509AuthType\":3,\"mAllowLocalLAN\":false,\"mMssFix\":0,\"mConnections\":[{\"options\":{\"udp\":false,\"cert\":\"CERT\",\"iatMode\":\"1\",\"remoteIP\":\"192.168.0.1\",\"remotePort\":\"1234\"},\"mServerName\":\"192.168.0.1\",\"mServerPort\":\"1234\",\"mUseUdp\":false,\"mCustomConfiguration\":\"\",\"mUseCustomConfig\":false,\"mEnabled\":true,\"mConnectTimeout\":0,\"mProxyType\":\"SOCKS5\",\"mProxyName\":\"127.0.0.1\",\"mProxyPort\":\"4430\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\"}],\"mRemoteRandom\":false,\"mAllowedAppsVpn\":[],\"mAllowedAppsVpnAreDisallowed\":true,\"mAllowAppVpnBypass\":false,\"mAuthRetry\":0,\"mTunMtu\":0,\"mPushPeerInfo\":false,\"mVersion\":0,\"mLastUsed\":0,\"mServerName\":\"openvpn.example.com\",\"mServerPort\":\"1194\",\"mUseUdp\":true,\"mTemporaryProfile\":false,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mProfileVersion\":7,\"mBlockUnusedAddressFamilies\":true,\"mUsePluggableTransports\":true}"; + private static final String OBFS4CONNECTION_PROFILE_OBFSVPN_KCP = "{\"mAuthenticationType\":2,\"mName\":\"mockProfile\",\"mTLSAuthDirection\":\"\",\"mUseLzo\":false,\"mUseTLSAuth\":false,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mOverrideDNS\":false,\"mSearchDomain\":\"blinkt.de\",\"mUseDefaultRoute\":true,\"mUsePull\":true,\"mCheckRemoteCN\":true,\"mExpectTLSCert\":false,\"mRemoteCN\":\"\",\"mPassword\":\"\",\"mUsername\":\"\",\"mRoutenopull\":false,\"mUseRandomHostname\":false,\"mUseFloat\":false,\"mUseCustomConfig\":false,\"mCustomConfigOptions\":\"\",\"mVerb\":\"1\",\"mCipher\":\"\",\"mDataCiphers\":\"\",\"mNobind\":true,\"mUseDefaultRoutev6\":true,\"mCustomRoutesv6\":\"\",\"mKeyPassword\":\"\",\"mPersistTun\":false,\"mConnectRetryMax\":\"-1\",\"mConnectRetry\":\"2\",\"mConnectRetryMaxTime\":\"300\",\"mUserEditable\":true,\"mAuth\":\"\",\"mX509AuthType\":3,\"mAllowLocalLAN\":false,\"mMssFix\":0,\"mConnections\":[{\"options\":{\"udp\":true,\"cert\":\"CERT\",\"iatMode\":\"1\",\"remoteIP\":\"192.168.0.1\",\"remotePort\":\"1234\"},\"mServerName\":\"192.168.0.1\",\"mServerPort\":\"1234\",\"mUseUdp\":false,\"mCustomConfiguration\":\"\",\"mUseCustomConfig\":false,\"mEnabled\":true,\"mConnectTimeout\":0,\"mProxyType\":\"SOCKS5\",\"mProxyName\":\"127.0.0.1\",\"mProxyPort\":\"4430\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\"}],\"mRemoteRandom\":false,\"mAllowedAppsVpn\":[],\"mAllowedAppsVpnAreDisallowed\":true,\"mAllowAppVpnBypass\":false,\"mAuthRetry\":0,\"mTunMtu\":0,\"mPushPeerInfo\":false,\"mVersion\":0,\"mLastUsed\":0,\"mServerName\":\"openvpn.example.com\",\"mServerPort\":\"1194\",\"mUseUdp\":true,\"mTemporaryProfile\":false,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mProfileVersion\":7,\"mBlockUnusedAddressFamilies\":true,\"mUsePluggableTransports\":true}"; + @Before public void setup() { mockStatic(UUID.class); + mockStatic(ConfigHelper.ObfsVpnHelper.class); } @Test @@ -58,9 +68,10 @@ public class VpnProfileTest { @Test public void toJson_obfs4() throws JSONException { + when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(false); + VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4); mockVpnProfile.mConnections[0] = new Obfs4Connection(new Obfs4Options("192.168.0.1", "1234", "CERT", "1", false)); - mockVpnProfile.mConnections[0].setUseUdp(false); mockVpnProfile.mLastUsed = 0; String s = mockVpnProfile.toJson(); System.out.println(s); @@ -73,18 +84,92 @@ public class VpnProfileTest { assertEquals(expectation.toString(),actual.toString()); } + @Test + public void toJson_obfs4_obfsvpn() throws JSONException { + when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4); + mockVpnProfile.mConnections[0] = new Obfs4Connection(new Obfs4Options("192.168.0.1", "1234", "CERT", "1", false)); + mockVpnProfile.mLastUsed = 0; + String s = mockVpnProfile.toJson(); + System.out.println(s); + + //ignore UUID in comparison -> set it to fixed value + JSONObject actual = new JSONObject(s); + actual.put("mUuid", "9d295ca2-3789-48dd-996e-f731dbf50fdc"); + JSONObject expectation = new JSONObject(OBFS4CONNECTION_PROFILE_OBFSVPN); + + assertEquals(expectation.toString(),actual.toString()); + } + + @Test + public void toJson_obfs4_obfsvpn_kcp() throws JSONException { + when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + + VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4); + mockVpnProfile.mConnections[0] = new Obfs4Connection(new Obfs4Options("192.168.0.1", "1234", "CERT", "1", true)); + mockVpnProfile.mLastUsed = 0; + String s = mockVpnProfile.toJson(); + System.out.println(s); + + //ignore UUID in comparison -> set it to fixed value + JSONObject actual = new JSONObject(s); + actual.put("mUuid", "9d295ca2-3789-48dd-996e-f731dbf50fdc"); + JSONObject expectation = new JSONObject(OBFS4CONNECTION_PROFILE_OBFSVPN_KCP); + + assertEquals(expectation.toString(),actual.toString()); + } + @Test public void fromJson_obfs4() { + when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(false); + VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE); assertNotNull(mockVpnProfile); assertNotNull(mockVpnProfile.mConnections); assertNotNull(mockVpnProfile.mConnections[0]); assertFalse(mockVpnProfile.mConnections[0].isUseUdp()); Obfs4Connection obfs4Connection = (Obfs4Connection) mockVpnProfile.mConnections[0]; - assertEquals(obfs4Connection.getTransportType(), OBFS4); - assertEquals(obfs4Connection.getDispatcherOptions().cert, "CERT"); - assertEquals(obfs4Connection.getDispatcherOptions().iatMode, "1"); - assertEquals(obfs4Connection.getDispatcherOptions().remoteIP, "192.168.0.1"); - assertEquals(obfs4Connection.getDispatcherOptions().remotePort, "1234"); + assertEquals(OBFS4, obfs4Connection.getTransportType()); + assertFalse(obfs4Connection.getDispatcherOptions().udp); + assertEquals("CERT", obfs4Connection.getDispatcherOptions().cert); + assertEquals("1", obfs4Connection.getDispatcherOptions().iatMode); + assertEquals("192.168.0.1", obfs4Connection.getDispatcherOptions().remoteIP); + assertEquals("1234", obfs4Connection.getDispatcherOptions().remotePort); + } + + @Test + public void fromJson_obfs4_obfsvpn() { + when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + + VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE_OBFSVPN); + assertNotNull(mockVpnProfile); + assertNotNull(mockVpnProfile.mConnections); + assertNotNull(mockVpnProfile.mConnections[0]); + assertFalse(mockVpnProfile.mConnections[0].isUseUdp()); + Obfs4Connection obfs4Connection = (Obfs4Connection) mockVpnProfile.mConnections[0]; + assertEquals(OBFS4, obfs4Connection.getTransportType()); + assertFalse(obfs4Connection.getDispatcherOptions().udp); + assertEquals("CERT", obfs4Connection.getDispatcherOptions().cert); + assertEquals("1", obfs4Connection.getDispatcherOptions().iatMode); + assertEquals("192.168.0.1", obfs4Connection.getDispatcherOptions().remoteIP); + assertEquals("1234", obfs4Connection.getDispatcherOptions().remotePort); + } + + @Test + public void fromJson_obfs4_obfsvpn_kcp() { + when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + + VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE_OBFSVPN_KCP); + assertNotNull(mockVpnProfile); + assertNotNull(mockVpnProfile.mConnections); + assertNotNull(mockVpnProfile.mConnections[0]); + assertFalse(mockVpnProfile.mConnections[0].isUseUdp()); + Obfs4Connection obfs4Connection = (Obfs4Connection) mockVpnProfile.mConnections[0]; + assertEquals(OBFS4, obfs4Connection.getTransportType()); + assertTrue(obfs4Connection.getDispatcherOptions().udp); + assertEquals("CERT", obfs4Connection.getDispatcherOptions().cert); + assertEquals("1", obfs4Connection.getDispatcherOptions().iatMode); + assertEquals("192.168.0.1", obfs4Connection.getDispatcherOptions().remoteIP); + assertEquals("1234", obfs4Connection.getDispatcherOptions().remotePort); } } \ No newline at end of file diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java index 2b1615da..45a20b1c 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java @@ -65,7 +65,6 @@ import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_DOWNLOAD import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE; import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS; import static se.leap.bitmaskclient.providersetup.ProviderAPI.INCORRECTLY_DOWNLOADED_GEOIP_JSON; -import static se.leap.bitmaskclient.providersetup.ProviderAPI.INCORRECTLY_DOWNLOADED_VPN_CERTIFICATE; import static se.leap.bitmaskclient.providersetup.ProviderAPI.INCORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE; import static se.leap.bitmaskclient.providersetup.ProviderAPI.MISSING_NETWORK_CONNECTION; import static se.leap.bitmaskclient.providersetup.ProviderAPI.PARAMETERS; @@ -85,7 +84,6 @@ import static se.leap.bitmaskclient.testutils.MockHelper.mockBase64; import static se.leap.bitmaskclient.testutils.MockHelper.mockBundle; import static se.leap.bitmaskclient.testutils.MockHelper.mockClientGenerator; import static se.leap.bitmaskclient.testutils.MockHelper.mockConfigHelper; -import static se.leap.bitmaskclient.testutils.MockHelper.mockConfigHelper; import static se.leap.bitmaskclient.testutils.MockHelper.mockIntent; import static se.leap.bitmaskclient.testutils.MockHelper.mockPreferenceHelper; import static se.leap.bitmaskclient.testutils.MockHelper.mockProviderApiConnector; 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 0fd07858..2431542f 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java @@ -1,5 +1,18 @@ package se.leap.bitmaskclient.eip; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.mock; +import static org.powermock.api.mockito.PowerMockito.mockStatic; +import static org.powermock.api.mockito.PowerMockito.when; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; +import static se.leap.bitmaskclient.base.models.Constants.OPENVPN_CONFIGURATION; +import static se.leap.bitmaskclient.testutils.MockHelper.mockTextUtils; + import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; @@ -20,27 +33,15 @@ import java.util.HashMap; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.connection.Connection; +import se.leap.bitmaskclient.base.utils.ConfigHelper; import se.leap.bitmaskclient.testutils.MockHelper; import se.leap.bitmaskclient.testutils.TestSetupHelper; -import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; -import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.RETURNS_DEEP_STUBS; -import static org.mockito.Mockito.mock; -import static org.powermock.api.mockito.PowerMockito.mockStatic; -import static org.powermock.api.mockito.PowerMockito.when; -import static se.leap.bitmaskclient.base.models.Constants.OPENVPN_CONFIGURATION; -import static se.leap.bitmaskclient.testutils.MockHelper.mockTextUtils; - /** * Created by cyberta on 03.10.17. */ @RunWith(PowerMockRunner.class) -@PrepareForTest({Log.class, TextUtils.class, PreferenceManager.class}) +@PrepareForTest({Log.class, TextUtils.class, PreferenceManager.class, ConfigHelper.ObfsVpnHelper.class}) public class VpnConfigGeneratorTest { @Mock(answer = Answers.RETURNS_DEEP_STUBS) @@ -164,6 +165,8 @@ public class VpnConfigGeneratorTest { "persist-tun\n" + "# persist-tun also enables pre resolving to avoid DNS resolve problem\n" + "preresolve\n" + + "# Use system proxy setting\n" + + "management-query-proxy\n" + "# Custom configuration options\n" + "# You are on your on own here :)\n" + "# These options found in the config file do not map to config settings:\n" + @@ -283,6 +286,8 @@ public class VpnConfigGeneratorTest { "persist-tun\n" + "# persist-tun also enables pre resolving to avoid DNS resolve problem\n" + "preresolve\n" + + "# Use system proxy setting\n" + + "management-query-proxy\n" + "# Custom configuration options\n" + "# You are on your on own here :)\n" + "# These options found in the config file do not map to config settings:\n" + @@ -402,6 +407,129 @@ public class VpnConfigGeneratorTest { "persist-tun\n" + "# persist-tun also enables pre resolving to avoid DNS resolve problem\n" + "preresolve\n" + + "# Use system proxy setting\n" + + "management-query-proxy\n" + + "# Custom configuration options\n" + + "# You are on your on own here :)\n" + + "# These options found in the config file do not map to config settings:\n" + + "keepalive 10 30 \n" + + "tls-cipher DHE-RSA-AES128-SHA \n"; + + String expectedVPNConfig_v3_obfsvpn_obfs4 = "# Config for OpenVPN 2.x\n" + + "# Enables connection to GUI\n" + + "management /data/data/se.leap.bitmask/mgmtsocket unix\n" + + "management-client\n" + + "management-query-passwords\n" + + "management-hold\n" + + "\n" + + "setenv IV_GUI_VER \"se.leap.bitmaskclient 0.9.10\" \n" + + "setenv IV_PLAT_VER \"0 null JUNIT null null null\"\n" + + "machine-readable-output\n" + + "allow-recursive-routing\n" + + "ifconfig-nowarn\n" + + "client\n" + + "verb 4\n" + + "connect-retry 2 300\n" + + "resolv-retry 60\n" + + "dev tun\n" + + "remote 37.218.247.60 23049 tcp-client\n" + + "\n" + + "-----BEGIN CERTIFICATE-----\n" + + "MIIFbzCCA1egAwIBAgIBATANBgkqhkiG9w0BAQ0FADBKMRgwFgYDVQQDDA9CaXRt\n" + + "YXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNVBAsME2h0dHBzOi8v\n" + + "Yml0bWFzay5uZXQwHhcNMTIxMTA2MDAwMDAwWhcNMjIxMTA2MDAwMDAwWjBKMRgw\n" + + "FgYDVQQDDA9CaXRtYXNrIFJvb3QgQ0ExEDAOBgNVBAoMB0JpdG1hc2sxHDAaBgNV\n" + + "BAsME2h0dHBzOi8vYml0bWFzay5uZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw\n" + + "ggIKAoICAQC1eV4YvayaU+maJbWrD4OHo3d7S1BtDlcvkIRS1Fw3iYDjsyDkZxai\n" + + "dHp4EUasfNQ+EVtXUvtk6170EmLco6Elg8SJBQ27trE6nielPRPCfX3fQzETRfvB\n" + + "7tNvGw4Jn2YKiYoMD79kkjgyZjkJ2r/bEHUSevmR09BRp86syHZerdNGpXYhcQ84\n" + + "CA1+V+603GFIHnrP+uQDdssW93rgDNYu+exT+Wj6STfnUkugyjmPRPjL7wh0tzy+\n" + + "znCeLl4xiV3g9sjPnc7r2EQKd5uaTe3j71sDPF92KRk0SSUndREz+B1+Dbe/RGk4\n" + + "MEqGFuOzrtsgEhPIX0hplhb0Tgz/rtug+yTT7oJjBa3u20AAOQ38/M99EfdeJvc4\n" + + "lPFF1XBBLh6X9UKF72an2NuANiX6XPySnJgZ7nZ09RiYZqVwu/qt3DfvLfhboq+0\n" + + "bQvLUPXrVDr70onv5UDjpmEA/cLmaIqqrduuTkFZOym65/PfAPvpGnt7crQj/Ibl\n" + + "DEDYZQmP7AS+6zBjoOzNjUGE5r40zWAR1RSi7zliXTu+yfsjXUIhUAWmYR6J3KxB\n" + + "lfsiHBQ+8dn9kC3YrUexWoOqBiqJOAJzZh5Y1tqgzfh+2nmHSB2dsQRs7rDRRlyy\n" + + "YMbkpzL9ZsOUO2eTP1mmar6YjCN+rggYjRrX71K2SpBG6b1zZxOG+wIDAQABo2Aw\n" + + "XjAdBgNVHQ4EFgQUuYGDLL2sswnYpHHvProt1JU+D48wDgYDVR0PAQH/BAQDAgIE\n" + + "MAwGA1UdEwQFMAMBAf8wHwYDVR0jBBgwFoAUuYGDLL2sswnYpHHvProt1JU+D48w\n" + + "DQYJKoZIhvcNAQENBQADggIBADeG67vaFcbITGpi51264kHPYPEWaXUa5XYbtmBl\n" + + "cXYyB6hY5hv/YNuVGJ1gWsDmdeXEyj0j2icGQjYdHRfwhrbEri+h1EZOm1cSBDuY\n" + + "k/P5+ctHyOXx8IE79DBsZ6IL61UKIaKhqZBfLGYcWu17DVV6+LT+AKtHhOrv3TSj\n" + + "RnAcKnCbKqXLhUPXpK0eTjPYS2zQGQGIhIy9sQXVXJJJsGrPgMxna1Xw2JikBOCG\n" + + "htD/JKwt6xBmNwktH0GI/LVtVgSp82Clbn9C4eZN9E5YbVYjLkIEDhpByeC71QhX\n" + + "EIQ0ZR56bFuJA/CwValBqV/G9gscTPQqd+iETp8yrFpAVHOW+YzSFbxjTEkBte1J\n" + + "aF0vmbqdMAWLk+LEFPQRptZh0B88igtx6tV5oVd+p5IVRM49poLhuPNJGPvMj99l\n" + + "mlZ4+AeRUnbOOeAEuvpLJbel4rhwFzmUiGoeTVoPZyMevWcVFq6BMkS+jRR2w0jK\n" + + "G6b0v5XDHlcFYPOgUrtsOBFJVwbutLvxdk6q37kIFnWCd8L3kmES5q4wjyFK47Co\n" + + "Ja8zlx64jmMZPg/t3wWqkZgXZ14qnbyG5/lGsj5CwVtfDljrhN0oCWK1FZaUmW3d\n" + + "69db12/g4f6phldhxiWuGC/W6fCW5kre7nmhshcltqAJJuU47iX+DarBFiIj816e\n" + + "yV8e\n" + + "-----END CERTIFICATE-----\n" + + "\n" + + "\n" + + "\n" + + "-----BEGIN RSA PRIVATE KEY-----\n" + + "MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDUTYWeGgsHS+fjijmziniNqw6h\n" + + "MBpyK4S/cM6PxV28C33VuOWPTMcIYesctjZANWFCggfFTQSjV5Qaxq9UK4i27tayLbCdlVS6hpbl\n" + + "Vf4DuI3Gj1Pv1rtITBShtvCf3T7yBnjW4wVpOpsUAAOViKUSvUU3kPPMFWhiGQw8yHYr82ts6XMo\n" + + "jwMoonW5Ml4e7C7Cr22QesC63q7emNcpUd0pZGT9C33RgDAHZDMrlyjo4HEp1JbUfB0gbmXElJbE\n" + + "1TNdZ62HhgmMjzTUN1GGrQ1t91AEoEQwaK65o4YSj+yFv6KXZZz5OWaz94tKiN9v26EXtBFmRlyb\n" + + "6+D9ynSd9LghAgMBAAECggEBANPHLRXkhsHVj1EkzqBx7gXr8CEMmiTvknFh9zvltrZhhDoRQjWr\n" + + "chPDkcRHY2Cznvy4N0YyqQDD2ULIlZdSAgPxxothFoBruWSD47yMBmLx08ORsDpcqt/YvPAATJI8\n" + + "IpFNsXcyaXBp/M57oRemgnxp/8UJPJmFdWX99H4hvffh/jdj7POgYiWUaAl37XTYZKZ4nzKU2wpL\n" + + "EDLj9RKPz9gG7CYp2zrLC9LaAsrXVrKwPBw6g+XwbClaqFj97db3mrY4lr6mTo89qmus1AU+fBDH\n" + + "3Xlpmc8JwB+30TvhRNKrpLx9cEjuEj7K1gm8Y4dWCjPi+lNbtAyUBcgPJFa/81ECgYEA7pLoBU/Y\n" + + "ZYjyHFca8FvDBcBh6haHfqJr9doXWtgjDrbi3o2n5wHqfKhFWOH6vPEQozkOVeX1ze6HOiRmGBpW\n" + + "r+r7x8TD25L7I6HJw3M351RWOAfkF0w/RTVdetcTgduQtfN1u6BDhYSVceXMjyQYx7MhfETWI8Gh\n" + + "KSYm8OEDYiUCgYEA489fmbrCcUnXzpTsbswJ5NmSoEXbcX8cLxnQuzE0z9GHhQdrMjOpXR76reTW\n" + + "6jcuudarNcwRUYSWWhjCDKHhpx4HhasWPaHgr7jIzcRw8yZSJRSxKr8sl1qh6g7s47JcmfXOMWLt\n" + + "yuyE933XrT19Th4ODZHY40Uv35mPjMi9d00CgYEAyRNAQtndBRa7GG/B4Ls2T+6pl+aNJIo4e+no\n" + + "rURlp800wWabEPRocdBRQmyULBLxduBr2LIMzhgwGSz8b2wji/l9ZA3PFY135bxClVzSzUIjuO3N\n" + + "rGUzHl2wAAyuAFDSUshzfkPBJRNt8aVBF5PQ3t93ZYmPAmv8LPZe875yX5ECgYEAsUEcwK/ZNW7g\n" + + "dQPZR4iJNkC4Xu6cBZ6Cnn92swBheEYvLSoNlX0vDZ7aLE3/jzQqrjzC8NP8sbH5jtbuvgeDXZX3\n" + + "AmGRp5j6C6A61ihAPmEVz3ZfN8SSfJ3vl//PAIg6lyz0J+cy4Q7RkwSeuVQ72Hl4M8TEvmmKC3Af\n" + + "ispy6Y0CgYEAgl1o2lo+ACyk+oVQPaaPqK3d7WOBFp4eR2nXFor/vsx9igQOlZUgzRDQsR8jo1o9\n" + + "efOSBf87igrZGgssys89pWa2dnXnz5PMmzkKr6bw4D9Ez6u6Puc9UZhGw/8wDYg6fSosdB9utspm\n" + + "M698ycef7jBNMDgmhpSvfw5GctoNQ4s=\n" + + "-----END RSA PRIVATE KEY-----\n" + + "\n" + + "\n" + + "-----BEGIN CERTIFICATE-----\n" + + "MIIEjDCCAnSgAwIBAgIQG6MBp/cd9DlY+7cdvp3R3jANBgkqhkiG9w0BAQsFADBmMRAwDgYDVQQK\n" + + "DAdCaXRtYXNrMRwwGgYDVQQLDBNodHRwczovL2JpdG1hc2submV0MTQwMgYDVQQDDCtCaXRtYXNr\n" + + "IFJvb3QgQ0EgKGNsaWVudCBjZXJ0aWZpY2F0ZXMgb25seSEpMB4XDTE0MTIwNTAwMDAwMFoXDTE1\n" + + "MDMwNTAwMDAwMFowLTErMCkGA1UEAwwiVU5MSU1JVEVEZDBwZDdkMzE4eTNtOHNkeXllaTFqYmZl\n" + + "eDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANRNhZ4aCwdL5+OKObOKeI2rDqEwGnIr\n" + + "hL9wzo/FXbwLfdW45Y9Mxwhh6xy2NkA1YUKCB8VNBKNXlBrGr1QriLbu1rItsJ2VVLqGluVV/gO4\n" + + "jcaPU+/Wu0hMFKG28J/dPvIGeNbjBWk6mxQAA5WIpRK9RTeQ88wVaGIZDDzIdivza2zpcyiPAyii\n" + + "dbkyXh7sLsKvbZB6wLrert6Y1ylR3SlkZP0LfdGAMAdkMyuXKOjgcSnUltR8HSBuZcSUlsTVM11n\n" + + "rYeGCYyPNNQ3UYatDW33UASgRDBorrmjhhKP7IW/opdlnPk5ZrP3i0qI32/boRe0EWZGXJvr4P3K\n" + + "dJ30uCECAwEAAaNvMG0wHQYDVR0OBBYEFK8bMVAM4GBB5sHptoIOAaIvlYueMAsGA1UdDwQEAwIH\n" + + "gDATBgNVHSUEDDAKBggrBgEFBQcDAjAJBgNVHRMEAjAAMB8GA1UdIwQYMBaAFId+E7bsWFsUWah9\n" + + "vZuPvZ7O+aJsMA0GCSqGSIb3DQEBCwUAA4ICAQAQOX81csVhvP422NKkZH7+g3npBpl+sEHedaGR\n" + + "xYPOu4HrA4TVF9h44sljRoRJyenGNdBZCXcLKHg889eePTf8Z5K3lTojp6hvwyA6tgxOMHT1kESW\n" + + "PfqnRw8mHfHJuE3g+4YNUMwggzwc/VZATdV/7M33sarVN9AUOHou9n9BizgCC+UnYlS+F2POumE3\n" + + "FbOhKo5uubI02MwBYlN2JVO2TBt1Q20w8wc6cU07Xi5Epp+1mkgFiOShkNtPcJmEyBWJhxDtSDOW\n" + + "2doqWYNqH2kq7B5R/kyyfcpFJqAnBTV7xs+C5rTS1mW7LpxfdCUMbYuLCpyxpO3A/DhAm8n47tUH\n" + + "lBtmo8Avdb8VdFpYiGBpB0o9kTFcsWFb2GkWFBduGfSEB8jUI7QtqhgZqocAKK/cweSRV8FwyUcn\n" + + "R0prRm3QEi9fbXqEddzjSY9y/lqWYzT7u+IOAQpKroeZ4wzgYperDNOUFuYk1rP7yuvjP2pV5rcN\n" + + "yPoBP60TPVWMRM4WJm6nTogAz2qBrFsf/XwT/ajzbsjT6HNB7QbRE+wkFkqspoXG5Agp7KQ8lW3L\n" + + "SKCDGOQJz7VIE85pD0tg7QEXBEw8oaRZtMjQ0Gvs25mxXAKka4wGasaWfYH6d0E+iKYcWn86V1rH\n" + + "K2ZoknT+Nno5jgjFuUR3fZseNizEfx7BteooKQ==\n" + + "-----END CERTIFICATE-----\n" + + "\n" + + "crl-verify file missing in config profile\n" + + "route 37.218.247.60 255.255.255.255 net_gateway\n"+ + "remote-cert-tls server\n" + + "data-ciphers AES-128-CBC\n" + + "cipher AES-128-CBC\n" + + "auth SHA1\n" + + "persist-tun\n" + + "# persist-tun also enables pre resolving to avoid DNS resolve problem\n" + + "preresolve\n" + + "# Use system proxy setting\n" + + "management-query-proxy\n" + "# Custom configuration options\n" + "# You are on your on own here :)\n" + "# These options found in the config file do not map to config settings:\n" + @@ -521,6 +649,8 @@ public class VpnConfigGeneratorTest { "persist-tun\n" + "# persist-tun also enables pre resolving to avoid DNS resolve problem\n" + "preresolve\n" + + "# Use system proxy setting\n" + + "management-query-proxy\n" + "# Custom configuration options\n" + "# You are on your on own here :)\n" + "# These options found in the config file do not map to config settings:\n" + @@ -640,6 +770,8 @@ public class VpnConfigGeneratorTest { "persist-tun\n" + "# persist-tun also enables pre resolving to avoid DNS resolve problem\n" + "preresolve\n" + + "# Use system proxy setting\n" + + "management-query-proxy\n" + "# Custom configuration options\n" + "# You are on your on own here :)\n" + "# These options found in the config file do not map to config settings:\n" + @@ -759,6 +891,8 @@ public class VpnConfigGeneratorTest { "persist-tun\n" + "# persist-tun also enables pre resolving to avoid DNS resolve problem\n" + "preresolve\n" + + "# Use system proxy setting\n" + + "management-query-proxy\n" + "# Custom configuration options\n" + "# You are on your on own here :)\n" + "# These options found in the config file do not map to config settings:\n" + @@ -882,6 +1016,8 @@ public class VpnConfigGeneratorTest { "persist-tun\n" + "# persist-tun also enables pre resolving to avoid DNS resolve problem\n" + "preresolve\n" + + "# Use system proxy setting\n" + + "management-query-proxy\n" + "# Custom configuration options\n" + "# You are on your on own here :)\n" + "# These options found in the config file do not map to config settings:\n" + @@ -1007,6 +1143,8 @@ public class VpnConfigGeneratorTest { "persist-tun\n" + "# persist-tun also enables pre resolving to avoid DNS resolve problem\n" + "preresolve\n" + + "# Use system proxy setting\n" + + "management-query-proxy\n" + "# Custom configuration options\n" + "# You are on your on own here :)\n" + "# These options found in the config file do not map to config settings:\n" + @@ -1140,6 +1278,8 @@ public class VpnConfigGeneratorTest { "persist-tun\n" + "# persist-tun also enables pre resolving to avoid DNS resolve problem\n" + "preresolve\n" + + "# Use system proxy setting\n" + + "management-query-proxy\n" + "# Custom configuration options\n" + "# You are on your on own here :)\n" + "# These options found in the config file do not map to config settings:\n" + @@ -1286,7 +1426,9 @@ public class VpnConfigGeneratorTest { mockStatic(PreferenceManager.class); SharedPreferences preferences = mock(SharedPreferences.class, RETURNS_DEEP_STUBS); when(PreferenceManager.getDefaultSharedPreferences(any(Context.class))).thenReturn(preferences); + when(preferences.getBoolean("usesystemproxy", true)).thenReturn(true); when(context.getCacheDir()).thenReturn(new File("/data/data/se.leap.bitmask")); + mockStatic(ConfigHelper.ObfsVpnHelper.class); } @@ -1329,6 +1471,7 @@ public class VpnConfigGeneratorTest { @Test public void testGenerateVpnProfile_v3_obfs4() throws Exception { + when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(false); gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo.bitmask.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); @@ -1338,6 +1481,18 @@ public class VpnConfigGeneratorTest { assertTrue(vpnProfiles.get(OBFS4).getConfigFile(context, false).trim().equals(expectedVPNConfig_v3_obfs4.trim())); } + @Test + public void testGenerateVpnProfile_v3_obfs4_obfsvpn() throws Exception { + when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo.bitmask.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false); + HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(vpnProfiles.containsKey(OBFS4)); + assertTrue(vpnProfiles.containsKey(OPENVPN)); + System.out.println(vpnProfiles.get(OBFS4).getConfigFile(context, false)); + assertTrue(vpnProfiles.get(OBFS4).getConfigFile(context, false).trim().equals(expectedVPNConfig_v3_obfsvpn_obfs4.trim())); + } + @Test public void testGenerateVpnProfile_v3_ovpn_tcp_udp() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_pt_tcp_udp.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); 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 61d42f58..a455a4bf 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java @@ -36,7 +36,6 @@ import org.json.JSONException; import org.json.JSONObject; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import org.powermock.api.mockito.PowerMockito; import java.io.File; import java.io.FileNotFoundException; -- cgit v1.2.3 From 909eb3b6c7063468c603dd2228ca2a01e4b034e0 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 11 Jul 2022 22:22:09 +0200 Subject: make member variable final --- .../java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java index 5b8b7326..8e2afc7d 100644 --- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java @@ -19,7 +19,7 @@ public class ObfsVpnClient implements Observer, client.EventLogger { private static final String TAG = ObfsVpnClient.class.getSimpleName(); private volatile boolean noNetwork; // TODO: implement error signaling go->java - private AtomicBoolean isErrorHandling = new AtomicBoolean(false); + private final AtomicBoolean isErrorHandling = new AtomicBoolean(false); private final client.Client_ obfsVpnClient; private final Object LOCK = new Object(); -- cgit v1.2.3 From 35c3173690032a1c852001107a4cb6ca3f9bcc83 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 11 Jul 2022 22:22:22 +0200 Subject: cleanup --- .../se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java index 1c859d65..c5593bf7 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java @@ -32,7 +32,6 @@ import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; -import androidx.annotation.StringRes; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBarDrawerToggle; import androidx.appcompat.app.AlertDialog; -- cgit v1.2.3 From 1f12d1b99a88bf62f29798a30135473299978234 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Tue, 12 Jul 2022 16:15:58 +0200 Subject: implement error handling for socks port binding --- .../de/blinkt/openvpn/core/OpenVPNService.java | 3 +- .../openvpn/core/connection/Obfs4Connection.java | 2 +- .../pluggableTransports/ObfsVpnClient.java | 69 +++++++++++++++------- bitmaskcore | 2 +- 4 files changed, 51 insertions(+), 25 deletions(-) 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 987708f4..94922ed5 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -423,7 +423,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac obfsVpnClient.stop(); } obfsVpnClient = new ObfsVpnClient(obfs4Connection.getDispatcherOptions()); - obfsVpnClient.start(); + int runningSocksPort = obfsVpnClient.start(); + connection.setProxyPort(String.valueOf(runningSocksPort)); } else if (shapeshifter == null) { shapeshifter = new Shapeshifter(obfs4Connection.getDispatcherOptions()); shapeshifter.start(); 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 d3cfdc83..5189afcc 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 @@ -22,7 +22,7 @@ public class Obfs4Connection extends Connection { setServerName(options.remoteIP); setServerPort(options.remotePort); setProxyName(ObfsVpnClient.SOCKS_IP); - setProxyPort(ObfsVpnClient.SOCKS_PORT); + setProxyPort(String.valueOf(ObfsVpnClient.SOCKS_PORT.get())); setProxyType(ProxyType.SOCKS5); } else { setServerName(DISPATCHER_IP); diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java index 8e2afc7d..76e361d7 100644 --- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java @@ -5,6 +5,7 @@ import android.util.Log; 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; @@ -13,43 +14,66 @@ import se.leap.bitmaskclient.eip.EipStatus; public class ObfsVpnClient implements Observer, client.EventLogger { - public static final String SOCKS_PORT = "4430"; + 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; - // TODO: implement error signaling go->java private final AtomicBoolean isErrorHandling = 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) { - obfsVpnClient = new Client_(options.udp, SOCKS_IP+":"+SOCKS_PORT, options.cert); + obfsVpnClient = new Client_(options.udp, SOCKS_IP+":"+SOCKS_PORT.get(), options.cert); obfsVpnClient.setEventLogger(this); } - public void start() { + /** + * starts the client + * @return the port ObfsVpn is running on + */ + public int start() { synchronized (LOCK) { Log.d(TAG, "aquired LOCK"); - new Thread(() -> { - try { - obfsVpnClient.start(); - } catch (Exception e) { - e.printStackTrace(); - VpnStatus.logError("[obfsvpn] " + e.getLocalizedMessage()); - if (noNetwork) { - isErrorHandling.set(true); - } - } - }).start(); + new Thread(this::startSync).start(); + waitUntilStarted(); + Log.d(TAG, "returning LOCK after " + (reconnectRetry.get() + 1) * 200 +" ms"); + } + return SOCKS_PORT.get(); + } - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); + 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) { + isErrorHandling.set(true); } - Log.d(TAG, "returning LOCK after 500 ms"); } } @@ -58,7 +82,9 @@ public class ObfsVpnClient implements Observer, client.EventLogger { Log.d(TAG, "stopping obfsVpnClient..."); try { obfsVpnClient.stop(); - Thread.sleep(500); + reconnectRetry.set(0); + SOCKS_PORT.set(4430); + Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); VpnStatus.logError("[obfsvpn] " + e.getLocalizedMessage()); @@ -76,7 +102,6 @@ public class ObfsVpnClient implements Observer, client.EventLogger { public void update(Observable observable, Object arg) { if (observable instanceof EipStatus) { EipStatus status = (EipStatus) observable; - //This doesn't do anything yet, since the error handling is still missing if (status.getLevel() == ConnectionStatus.LEVEL_NONETWORK) { noNetwork = true; } else { diff --git a/bitmaskcore b/bitmaskcore index f5b935b7..a63cd6b2 160000 --- a/bitmaskcore +++ b/bitmaskcore @@ -1 +1 @@ -Subproject commit f5b935b77204291ded7d7b1304dc6026e699166c +Subproject commit a63cd6b2c573edb1de3119f4a158f840e4c4a9b2 -- cgit v1.2.3 From 95c923f2850ac409e8413cc4902c69848c64d7c8 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 15 Jul 2022 16:31:48 +0200 Subject: Parse different obfs4 flavors from eip-service.json. In the gateway load / gateway selection UI all pluggable transports flavors will be summed up and handled the same way. A gateway can support both obfs4 and the kcp flavor. --- .../main/java/de/blinkt/openvpn/VpnProfile.java | 27 +++++-- .../de/blinkt/openvpn/core/OpenVPNService.java | 10 +-- .../java/de/blinkt/openvpn/core/VpnStatus.java | 2 +- .../blinkt/openvpn/core/connection/Connection.java | 16 ++++- .../base/fragments/GatewaySelectionFragment.java | 6 +- .../leap/bitmaskclient/base/models/Constants.java | 1 + .../leap/bitmaskclient/base/models/Location.java | 19 +++-- .../se/leap/bitmaskclient/base/models/Pair.java | 57 +++++++++++++++ .../bitmaskclient/base/utils/PreferenceHelper.java | 46 +++++++----- .../base/views/SelectLocationEntry.java | 3 +- .../main/java/se/leap/bitmaskclient/eip/EIP.java | 83 +++++++++++----------- .../java/se/leap/bitmaskclient/eip/Gateway.java | 37 ++++++---- .../se/leap/bitmaskclient/eip/GatewaysManager.java | 58 ++++++++------- .../leap/bitmaskclient/eip/VpnConfigGenerator.java | 44 ++++++++---- 14 files changed, 272 insertions(+), 137 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/base/models/Pair.java diff --git a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java index c010ef54..7dd75432 100644 --- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java +++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java @@ -70,6 +70,8 @@ import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.R; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4_KCP; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PROFILE; import static se.leap.bitmaskclient.base.utils.ConfigHelper.stringEqual; @@ -191,7 +193,8 @@ public class VpnProfile implements Serializable, Cloneable { private int mProfileVersion; public boolean mBlockUnusedAddressFamilies = true; public String mGatewayIp; - public boolean mUsePluggableTransports; + private boolean mUseObfs4; + private boolean mUseObfs4Kcp; public VpnProfile(String name, Connection.TransportType transportType) { mUuid = UUID.randomUUID(); @@ -200,7 +203,8 @@ public class VpnProfile implements Serializable, Cloneable { mConnections = new Connection[1]; mLastUsed = System.currentTimeMillis(); - mUsePluggableTransports = transportType == OBFS4; + mUseObfs4 = transportType == OBFS4; + mUseObfs4Kcp = transportType == OBFS4_KCP; } public static String openVpnEscape(String unescaped) { @@ -266,7 +270,8 @@ public class VpnProfile implements Serializable, Cloneable { if (obj instanceof VpnProfile) { VpnProfile vp = (VpnProfile) obj; return stringEqual(vp.mGatewayIp, mGatewayIp) && - vp.mUsePluggableTransports == mUsePluggableTransports; + vp.mUseObfs4 == mUseObfs4 && + vp.mUseObfs4Kcp == mUseObfs4Kcp; } return false; } @@ -296,6 +301,20 @@ public class VpnProfile implements Serializable, Cloneable { mUuid = uuid; } + public boolean usePluggableTransports() { + return mUseObfs4Kcp || mUseObfs4; + } + + public Connection.TransportType getTransportType() { + if (mUseObfs4) { + return OBFS4; + } else if (mUseObfs4Kcp) { + return OBFS4_KCP; + } else { + return OPENVPN; + } + } + public String getName() { if (TextUtils.isEmpty(mName)) return "No profile name"; @@ -478,7 +497,7 @@ public class VpnProfile implements Serializable, Cloneable { cfg.append(insertFileData("crl-verify", mCrlFilename)); // compression does not work in conjunction with shapeshifter-dispatcher so far - if (mUseLzo && !mUsePluggableTransports) { + if (mUseLzo && !usePluggableTransports()) { cfg.append("comp-lzo\n"); } 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 94922ed5..4b394136 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -317,7 +317,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac VpnStatus.updateStateString("VPN_GENERATE_CONFIG", "", R.string.building_configration, ConnectionStatus.LEVEL_START); notificationManager.buildOpenVpnNotification( mProfile != null ? mProfile.mName : "", - mProfile != null && mProfile.mUsePluggableTransports, + mProfile != null && mProfile.usePluggableTransports(), VpnStatus.getLastCleanLogMessage(this), VpnStatus.getLastCleanLogMessage(this), ConnectionStatus.LEVEL_START, @@ -416,7 +416,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac // An old running VPN should now be exited mStarting = false; - if (mProfile.mUsePluggableTransports && connection instanceof Obfs4Connection) { + if (mProfile.usePluggableTransports() && connection instanceof Obfs4Connection) { Obfs4Connection obfs4Connection = (Obfs4Connection) connection; if (useObfsVpn()) { if (obfsVpnClient != null && obfsVpnClient.isStarted()) { @@ -1033,7 +1033,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac notificationManager.buildOpenVpnNotification( mProfile != null ? mProfile.mName : "", - mProfile != null && mProfile.mUsePluggableTransports, + mProfile != null && mProfile.usePluggableTransports(), VpnStatus.getLastCleanLogMessage(this), VpnStatus.getLastCleanLogMessage(this), level, @@ -1064,7 +1064,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac humanReadableByteCount(diffOut / OpenVPNManagement.mBytecountInterval, true, getResources())); notificationManager.buildOpenVpnNotification( mProfile != null ? mProfile.mName : "", - mProfile != null && mProfile.mUsePluggableTransports, + mProfile != null && mProfile.usePluggableTransports(), netstat, null, LEVEL_CONNECTED, @@ -1108,7 +1108,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac VpnStatus.updateStateString("NEED", "need " + needed, resid, LEVEL_WAITING_FOR_USER_INPUT); notificationManager.buildOpenVpnNotification( mProfile != null ? mProfile.mName : "", - mProfile != null && mProfile.mUsePluggableTransports, + mProfile != null && mProfile.usePluggableTransports(), getString(resid), getString(resid), LEVEL_WAITING_FOR_USER_INPUT, 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 4fa5a7b6..f28651f3 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java +++ b/app/src/main/java/de/blinkt/openvpn/core/VpnStatus.java @@ -543,6 +543,6 @@ public class VpnStatus { } public static boolean isUsingBridges() { - return lastConnectedProfile != null && lastConnectedProfile.mUsePluggableTransports; + return lastConnectedProfile != null && lastConnectedProfile.usePluggableTransports(); } } diff --git a/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java b/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java index 4cb9c0c7..f60e7333 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java +++ b/app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java @@ -39,7 +39,10 @@ public abstract class Connection implements Serializable, Cloneable { public enum TransportType { OBFS4("obfs4"), - OPENVPN("openvpn"); + OPENVPN("openvpn"), + OBFS4_KCP("obfs4-1"), + + PT("metaTransport"); String transport; @@ -51,6 +54,17 @@ public abstract class Connection implements Serializable, Cloneable { public String toString() { return transport; } + + public boolean isPluggableTransport() { + return this == OBFS4 || this == OBFS4_KCP || this == PT; + } + + public TransportType getMetaType() { + if (this == OBFS4 || this == OBFS4_KCP || this == PT) { + return PT; + } + return OPENVPN; + } } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java index f2c3b2d6..a2bfff7c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java @@ -51,10 +51,10 @@ import se.leap.bitmaskclient.eip.GatewaysManager; import static android.content.Context.MODE_PRIVATE; import static android.view.View.GONE; -import static android.view.View.INVISIBLE; import static android.view.View.VISIBLE; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.PT; import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT; import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES; @@ -92,7 +92,7 @@ public class GatewaySelectionFragment extends Fragment implements Observer, Loca eipStatus = EipStatus.getInstance(); eipStatus.addObserver(this); preferences = getContext().getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE); - selectedTransport = getUseBridges(preferences) ? OBFS4 : OPENVPN; + selectedTransport = getUseBridges(preferences) ? PT : OPENVPN; preferences.registerOnSharedPreferenceChangeListener(this); } @@ -211,7 +211,7 @@ public class GatewaySelectionFragment extends Fragment implements Observer, Loca public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (key.equals(USE_BRIDGES)) { boolean showBridges = getUseBridges(sharedPreferences); - selectedTransport = showBridges ? OBFS4 : OPENVPN; + selectedTransport = showBridges ? PT : OPENVPN; gatewaysManager.updateTransport(selectedTransport); locationListAdapter.updateTransport(selectedTransport, gatewaysManager); bridgesHint.setVisibility(showBridges ? VISIBLE : GONE); 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 d7a54fcc..b34a31eb 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 @@ -44,6 +44,7 @@ public interface Constants { String USE_SNOWFLAKE = "use_snowflake"; String PREFER_UDP = "prefer_UDP"; String GATEWAY_PINNING = "gateway_pinning"; + String ALLOW_EXPERIMENTAL_TRANSPORTS = "allow_experimental_transports"; ////////////////////////////////////////////// diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Location.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Location.java index 064f25c0..26f6b14a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/models/Location.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Location.java @@ -21,10 +21,7 @@ import androidx.annotation.NonNull; import java.util.Comparator; import java.util.HashMap; -import java.util.HashSet; -import java.util.function.ToDoubleFunction; -import de.blinkt.openvpn.core.connection.Connection; import de.blinkt.openvpn.core.connection.Connection.TransportType; public class Location implements Cloneable { @@ -50,27 +47,27 @@ public class Location implements Cloneable { } public boolean supportsTransport(TransportType transportType) { - return numberOfGateways.containsKey(transportType); + return numberOfGateways.containsKey(transportType.getMetaType()); } public void setAverageLoad(TransportType transportType, double load) { - averageLoad.put(transportType, load); + averageLoad.put(transportType.getMetaType(), load); } public double getAverageLoad(TransportType transportType) { - if (averageLoad.containsKey(transportType)) { - return averageLoad.get(transportType); + if (averageLoad.containsKey(transportType.getMetaType())) { + return averageLoad.get(transportType.getMetaType()); } return 0; } public void setNumberOfGateways(TransportType transportType, int numbers) { - numberOfGateways.put(transportType, numbers); + numberOfGateways.put(transportType.getMetaType(), numbers); } public int getNumberOfGateways(TransportType transportType) { - if (numberOfGateways.containsKey(transportType)) { - return numberOfGateways.get(transportType); + if (numberOfGateways.containsKey(transportType.getMetaType())) { + return numberOfGateways.get(transportType.getMetaType()); } return 0; } @@ -112,7 +109,7 @@ public class Location implements Cloneable { public static class SortByAverageLoad implements Comparator { TransportType transportType; public SortByAverageLoad(TransportType transportType) { - this.transportType = transportType; + this.transportType = transportType.getMetaType(); } @Override diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Pair.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Pair.java new file mode 100644 index 00000000..e2ef4622 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Pair.java @@ -0,0 +1,57 @@ +package se.leap.bitmaskclient.base.models; + +import java.util.Objects; + +/** + * Container to ease passing around a tuple of two objects. This object provides a sensible + * implementation of equals(), returning true if equals() is true on each of the contained + * objects. + */ +public class Pair { + public final F first; + public final S second; + + /** + * Constructor for a Pair. + * + * @param first the first object in the Pair + * @param second the second object in the pair + */ + public Pair(F first, S second) { + this.first = first; + this.second = second; + } + + /** + * Checks the two objects for equality by delegating to their respective + * {@link Object#equals(Object)} methods. + * + * @param o the {@link Pair} to which this one is to be checked for equality + * @return true if the underlying objects of the Pair are both considered + * equal + */ + @Override + public boolean equals(Object o) { + if (!(o instanceof Pair)) { + return false; + } + Pair p = (Pair) o; + return Objects.equals(p.first, first) && Objects.equals(p.second, second); + } + + /** + * Compute a hash code using the hash codes of the underlying objects + * + * @return a hashcode of the Pair + */ + @Override + public int hashCode() { + return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode()); + } + + @Override + public String toString() { + return "Pair{" + String.valueOf(first) + " " + String.valueOf(second) + "}"; + } + +} 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 08bfbdc3..3a2cf754 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 @@ -1,25 +1,7 @@ package se.leap.bitmaskclient.base.utils; -import android.content.Context; -import android.content.SharedPreferences; -import android.preference.Preference; - -import androidx.annotation.NonNull; -import androidx.annotation.WorkerThread; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.HashSet; -import java.util.Set; - -import de.blinkt.openvpn.VpnProfile; -import se.leap.bitmaskclient.base.models.Provider; -import se.leap.bitmaskclient.tor.TorStatusObservable; - import static android.content.Context.MODE_PRIVATE; +import static se.leap.bitmaskclient.base.models.Constants.ALLOW_EXPERIMENTAL_TRANSPORTS; import static se.leap.bitmaskclient.base.models.Constants.ALLOW_TETHERING_BLUETOOTH; import static se.leap.bitmaskclient.base.models.Constants.ALLOW_TETHERING_USB; import static se.leap.bitmaskclient.base.models.Constants.ALLOW_TETHERING_WIFI; @@ -42,6 +24,24 @@ 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_SNOWFLAKE; +import android.content.Context; +import android.content.SharedPreferences; + +import androidx.annotation.NonNull; +import androidx.annotation.WorkerThread; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashSet; +import java.util.Set; + +import de.blinkt.openvpn.VpnProfile; +import se.leap.bitmaskclient.base.models.Provider; +import se.leap.bitmaskclient.tor.TorStatusObservable; + /** * Created by cyberta on 18.03.18. */ @@ -238,6 +238,14 @@ public class PreferenceHelper { return getBoolean(context, SHOW_EXPERIMENTAL, false); } + public static void setAllowExperimentalTransports(Context context, boolean show) { + putBoolean(context, ALLOW_EXPERIMENTAL_TRANSPORTS, show); + } + + public static boolean allowExperimentalTransports(Context context) { + return getBoolean(context, ALLOW_EXPERIMENTAL_TRANSPORTS, false); + } + public static void setUseIPv6Firewall(Context context, boolean useFirewall) { putBoolean(context, USE_IPv6_FIREWALL, useFirewall); } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/views/SelectLocationEntry.java b/app/src/main/java/se/leap/bitmaskclient/base/views/SelectLocationEntry.java index 3d4f93ff..554fe958 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/views/SelectLocationEntry.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/views/SelectLocationEntry.java @@ -6,7 +6,6 @@ import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.LinearLayout; -import android.widget.RelativeLayout; import androidx.appcompat.widget.AppCompatImageView; import androidx.appcompat.widget.AppCompatTextView; @@ -71,7 +70,7 @@ public class SelectLocationEntry extends LinearLayout { boolean supportsSelectedTransport = location.supportsTransport(transportType); locationText.setVisibility(hasData ? VISIBLE : GONE); locationIndicator.setVisibility(hasData ? VISIBLE : GONE); - bridgesView.setVisibility(transportType == OBFS4 && supportsSelectedTransport ? VISIBLE : GONE); + bridgesView.setVisibility(transportType.isPluggableTransport() && supportsSelectedTransport ? VISIBLE : GONE); locationText.setText(location.getName()); locationIndicator.setLoad(Load.getLoadByValue(location.getAverageLoad(transportType))); selectedView.setChecked(location.selected); diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java index 46f91781..b3efd21f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -16,6 +16,36 @@ */ package se.leap.bitmaskclient.eip; +import static android.app.Activity.RESULT_CANCELED; +import static android.app.Activity.RESULT_OK; +import static se.leap.bitmaskclient.R.string.vpn_certificate_is_invalid; +import static se.leap.bitmaskclient.R.string.warning_client_parsing_error_gateways; +import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_GATEWAY_SETUP_OBSERVER_EVENT; +import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_KEY; +import static se.leap.bitmaskclient.base.models.Constants.CLEARLOG; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_CHECK_CERT_VALIDITY; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_IS_RUNNING; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_LAUNCH_VPN; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START_ALWAYS_ON_VPN; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START_BLOCKING_VPN; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_STOP; +import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_STOP_BLOCKING_VPN; +import static se.leap.bitmaskclient.base.models.Constants.EIP_EARLY_ROUTES; +import static se.leap.bitmaskclient.base.models.Constants.EIP_N_CLOSEST_GATEWAY; +import static se.leap.bitmaskclient.base.models.Constants.EIP_RECEIVER; +import static se.leap.bitmaskclient.base.models.Constants.EIP_RESTART_ON_BOOT; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PROFILE; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; +import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; +import static se.leap.bitmaskclient.base.utils.ConfigHelper.ensureNotOnMainThread; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferredCity; +import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_INVALID_PROFILE; +import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_INVALID_VPN_CERTIFICATE; +import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_VPN_PREPARE; +import static se.leap.bitmaskclient.eip.EIP.EIPErrors.NO_MORE_GATEWAYS; +import static se.leap.bitmaskclient.eip.EipResultBroadcast.tellToReceiverOrBroadcast; + import android.annotation.SuppressLint; import android.content.ComponentName; import android.content.Context; @@ -31,6 +61,7 @@ import android.os.ResultReceiver; import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.StringRes; import androidx.annotation.WorkerThread; import androidx.core.app.JobIntentService; @@ -57,42 +88,10 @@ import de.blinkt.openvpn.core.connection.Connection; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.OnBootReceiver; import se.leap.bitmaskclient.base.models.Provider; +import se.leap.bitmaskclient.base.models.Pair; import se.leap.bitmaskclient.base.models.ProviderObservable; import se.leap.bitmaskclient.base.utils.PreferenceHelper; -import static android.app.Activity.RESULT_CANCELED; -import static android.app.Activity.RESULT_OK; -import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; -import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; -import static se.leap.bitmaskclient.R.string.vpn_certificate_is_invalid; -import static se.leap.bitmaskclient.R.string.warning_client_parsing_error_gateways; -import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_GATEWAY_SETUP_OBSERVER_EVENT; -import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_KEY; -import static se.leap.bitmaskclient.base.models.Constants.CLEARLOG; -import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_CHECK_CERT_VALIDITY; -import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_IS_RUNNING; -import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_LAUNCH_VPN; -import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START; -import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START_ALWAYS_ON_VPN; -import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START_BLOCKING_VPN; -import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_STOP; -import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_STOP_BLOCKING_VPN; -import static se.leap.bitmaskclient.base.models.Constants.EIP_EARLY_ROUTES; -import static se.leap.bitmaskclient.base.models.Constants.EIP_N_CLOSEST_GATEWAY; -import static se.leap.bitmaskclient.base.models.Constants.EIP_RECEIVER; -import static se.leap.bitmaskclient.base.models.Constants.EIP_RESTART_ON_BOOT; -import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PROFILE; -import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.ensureNotOnMainThread; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferredCity; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseBridges; -import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_INVALID_PROFILE; -import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_INVALID_VPN_CERTIFICATE; -import static se.leap.bitmaskclient.eip.EIP.EIPErrors.ERROR_VPN_PREPARE; -import static se.leap.bitmaskclient.eip.EIP.EIPErrors.NO_MORE_GATEWAYS; -import static se.leap.bitmaskclient.eip.EipResultBroadcast.tellToReceiverOrBroadcast; - /** * EIP is the abstract base class for interacting with and managing the Encrypted * Internet Proxy connection. Connections are started, stopped, and queried through @@ -256,8 +255,8 @@ public final class EIP extends JobIntentService implements Observer { return; } - Gateway gateway = gatewaysManager.select(nClosestGateway); - launchActiveGateway(gateway, nClosestGateway, result); + Pair gatewayTransportTypePair = gatewaysManager.select(nClosestGateway); + launchActiveGateway(gatewayTransportTypePair, nClosestGateway, result); if (result.containsKey(BROADCAST_RESULT_KEY) && !result.getBoolean(BROADCAST_RESULT_KEY)) { tellToReceiverOrBroadcast(this, EIP_ACTION_START, RESULT_CANCELED, result); } else { @@ -271,7 +270,7 @@ public final class EIP extends JobIntentService implements Observer { */ private void startEIPAlwaysOnVpn() { GatewaysManager gatewaysManager = new GatewaysManager(getApplicationContext()); - Gateway gateway = gatewaysManager.select(0); + Pair gatewayTransportTypePair = gatewaysManager.select(0); Bundle result = new Bundle(); if (shouldUpdateVPNCertificate()) { @@ -280,7 +279,7 @@ public final class EIP extends JobIntentService implements Observer { ProviderObservable.getInstance().updateProvider(p); } - launchActiveGateway(gateway, 0, result); + launchActiveGateway(gatewayTransportTypePair, 0, result); if (result.containsKey(BROADCAST_RESULT_KEY) && !result.getBoolean(BROADCAST_RESULT_KEY)){ VpnStatus.logWarning("ALWAYS-ON VPN: " + getString(R.string.no_vpn_profiles_defined)); } @@ -324,13 +323,13 @@ public final class EIP extends JobIntentService implements Observer { /** * starts the VPN and connects to the given gateway * - * @param gateway to connect to + * @param gatewayTransportTypePair Pair of Gateway and associated transport used to connect */ - private void launchActiveGateway(Gateway gateway, int nClosestGateway, Bundle result) { + private void launchActiveGateway(@Nullable Pair gatewayTransportTypePair, int nClosestGateway, Bundle result) { VpnProfile profile; - Connection.TransportType transportType = getUseBridges(this) ? OBFS4 : OPENVPN; - if (gateway == null || - (profile = gateway.getProfile(transportType)) == null) { + + if (gatewayTransportTypePair == null || gatewayTransportTypePair.first == null || + (profile = gatewayTransportTypePair.first.getProfile(gatewayTransportTypePair.second)) == null) { String preferredLocation = getPreferredCity(getApplicationContext()); if (preferredLocation != null) { setErrorResult(result, NO_MORE_GATEWAYS.toString(), getStringResourceForNoMoreGateways(), getString(R.string.app_name), preferredLocation); 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 60507363..e9281609 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java @@ -16,6 +16,17 @@ */ package se.leap.bitmaskclient.eip; +import static se.leap.bitmaskclient.base.models.Constants.FULLNESS; +import static se.leap.bitmaskclient.base.models.Constants.HOST; +import static se.leap.bitmaskclient.base.models.Constants.IP_ADDRESS; +import static se.leap.bitmaskclient.base.models.Constants.LOCATION; +import static se.leap.bitmaskclient.base.models.Constants.LOCATIONS; +import static se.leap.bitmaskclient.base.models.Constants.NAME; +import static se.leap.bitmaskclient.base.models.Constants.OPENVPN_CONFIGURATION; +import static se.leap.bitmaskclient.base.models.Constants.OVERLOAD; +import static se.leap.bitmaskclient.base.models.Constants.TIMEZONE; +import static se.leap.bitmaskclient.base.models.Constants.VERSION; + import android.content.Context; import androidx.annotation.NonNull; @@ -36,17 +47,6 @@ import de.blinkt.openvpn.core.connection.Connection; import se.leap.bitmaskclient.base.utils.ConfigHelper; import se.leap.bitmaskclient.base.utils.PreferenceHelper; -import static se.leap.bitmaskclient.base.models.Constants.FULLNESS; -import static se.leap.bitmaskclient.base.models.Constants.HOST; -import static se.leap.bitmaskclient.base.models.Constants.IP_ADDRESS; -import static se.leap.bitmaskclient.base.models.Constants.LOCATION; -import static se.leap.bitmaskclient.base.models.Constants.LOCATIONS; -import static se.leap.bitmaskclient.base.models.Constants.NAME; -import static se.leap.bitmaskclient.base.models.Constants.OPENVPN_CONFIGURATION; -import static se.leap.bitmaskclient.base.models.Constants.OVERLOAD; -import static se.leap.bitmaskclient.base.models.Constants.TIMEZONE; -import static se.leap.bitmaskclient.base.models.Constants.VERSION; - /** * Gateway provides objects defining gateways and their metadata. * Each instance contains a VpnProfile for OpenVPN specific data and member @@ -175,7 +175,8 @@ public class Gateway { private @NonNull HashMap createVPNProfiles(Context context) throws ConfigParser.ConfigParseError, IOException, JSONException { boolean preferUDP = PreferenceHelper.getPreferUDP(context); - VpnConfigGenerator vpnConfigurationGenerator = new VpnConfigGenerator(generalConfiguration, secrets, gateway, apiVersion, preferUDP); + boolean allowExperimentalTransports = PreferenceHelper.allowExperimentalTransports(context); + VpnConfigGenerator vpnConfigurationGenerator = new VpnConfigGenerator(generalConfiguration, secrets, gateway, apiVersion, preferUDP, allowExperimentalTransports); HashMap profiles = vpnConfigurationGenerator.generateVpnProfiles(); addProfileInfos(context, profiles); return profiles; @@ -194,6 +195,9 @@ public class Gateway { } public boolean supportsTransport(Connection.TransportType transportType) { + if (transportType == Connection.TransportType.PT) { + return supportsPluggableTransports(); + } return vpnProfiles.get(transportType) != null; } @@ -201,6 +205,15 @@ public class Gateway { return new HashSet<>(vpnProfiles.keySet()); } + public boolean supportsPluggableTransports() { + for (Connection.TransportType transportType : vpnProfiles.keySet()) { + if (transportType.isPluggableTransport() && vpnProfiles.get(transportType) != null) { + return true; + } + } + return false; + } + public int getTimezone() { return timezone; } 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 a11c7e34..db7dd38c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -43,12 +43,15 @@ import de.blinkt.openvpn.core.connection.Connection; import de.blinkt.openvpn.core.connection.Connection.TransportType; import se.leap.bitmaskclient.BuildConfig; 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.utils.PreferenceHelper; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4_KCP; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.PT; import static se.leap.bitmaskclient.base.models.Constants.GATEWAYS; import static se.leap.bitmaskclient.base.models.Constants.HOST; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY; @@ -111,18 +114,18 @@ public class GatewaysManager { * select closest Gateway * @return the n closest Gateway */ - public Gateway select(int nClosest) { + public Pair select(int nClosest) { String selectedCity = getPreferredCity(context); return select(nClosest, selectedCity); } - public Gateway select(int nClosest, String city) { - TransportType transportType = getUseBridges(context) ? OBFS4 : OPENVPN; + public Pair select(int nClosest, String city) { + TransportType[] transportTypes = getUseBridges(context) ? new TransportType[]{OBFS4, OBFS4_KCP} : new TransportType[]{OPENVPN}; if (presortedList.size() > 0) { - return getGatewayFromPresortedList(nClosest, transportType, city); + return getGatewayFromPresortedList(nClosest, transportTypes, city); } - return getGatewayFromTimezoneCalculation(nClosest, transportType, city); + return getGatewayFromTimezoneCalculation(nClosest, transportTypes, city); } public void updateTransport(TransportType transportType) { @@ -158,7 +161,7 @@ public class GatewaysManager { } else { int index = locationNames.get(gateway.getName()); Location location = locations.get(index); - updateLocation(location, gateway, OBFS4); + updateLocation(location, gateway, PT); updateLocation(location, gateway, OPENVPN); locations.set(index, location); } @@ -173,9 +176,9 @@ public class GatewaysManager { private Location initLocation(String name, Gateway gateway, String preferredCity) { HashMap averageLoadMap = new HashMap<>(); HashMap numberOfGatewaysMap = new HashMap<>(); - if (gateway.getSupportedTransports().contains(OBFS4)) { - averageLoadMap.put(OBFS4, gateway.getFullness()); - numberOfGatewaysMap.put(OBFS4, 1); + if (gateway.supportsPluggableTransports()) { + averageLoadMap.put(PT, gateway.getFullness()); + numberOfGatewaysMap.put(PT, 1); } if (gateway.getSupportedTransports().contains(OPENVPN)) { averageLoadMap.put(OPENVPN, gateway.getFullness()); @@ -189,7 +192,7 @@ public class GatewaysManager { } private void updateLocation(Location location, Gateway gateway, Connection.TransportType transportType) { - if (gateway.getSupportedTransports().contains(transportType)) { + if (gateway.supportsTransport(transportType)) { double averageLoad = location.getAverageLoad(transportType); int numberOfGateways = location.getNumberOfGateways(transportType); averageLoad = (numberOfGateways * averageLoad + gateway.getFullness()) / (numberOfGateways + 1); @@ -218,35 +221,40 @@ public class GatewaysManager { return Load.getLoadByValue(location.getAverageLoad(transportType)); } - private Gateway getGatewayFromTimezoneCalculation(int nClosest, TransportType transportType, @Nullable String city) { + private Pair getGatewayFromTimezoneCalculation(int nClosest, TransportType[] transportTypes, @Nullable String city) { List list = new ArrayList<>(gateways.values()); GatewaySelector gatewaySelector = new GatewaySelector(list); Gateway gateway; int found = 0; int i = 0; while ((gateway = gatewaySelector.select(i)) != null) { - if ((city == null && gateway.supportsTransport(transportType)) || - (gateway.getName().equals(city) && gateway.supportsTransport(transportType))) { - if (found == nClosest) { - return gateway; + for (TransportType transportType : transportTypes) { + if ((city == null && gateway.supportsTransport(transportType)) || + (gateway.getName().equals(city) && gateway.supportsTransport(transportType))) { + if (found == nClosest) { + return new Pair<>(gateway, transportType); + } + found++; } - found++; } i++; } return null; } - private Gateway getGatewayFromPresortedList(int nClosest, TransportType transportType, @Nullable String city) { + private Pair getGatewayFromPresortedList(int nClosest, TransportType[] transportTypes, @Nullable String city) { int found = 0; for (Gateway gateway : presortedList) { - if ((city == null && gateway.supportsTransport(transportType)) || - (gateway.getName().equals(city) && gateway.supportsTransport(transportType))) { - if (found == nClosest) { - return gateway; + for (TransportType transportType : transportTypes) { + if ((city == null && gateway.supportsTransport(transportType)) || + (gateway.getName().equals(city) && gateway.supportsTransport(transportType))) { + if (found == nClosest) { + return new Pair<>(gateway, transportType); + } + found++; } - found++; } + } return null; } @@ -265,7 +273,7 @@ public class GatewaysManager { } private int getPositionFromPresortedList(VpnProfile profile) { - TransportType transportType = profile.mUsePluggableTransports ? OBFS4 : OPENVPN; + TransportType transportType = profile.getTransportType(); int nClosest = 0; for (Gateway gateway : presortedList) { if (gateway.supportsTransport(transportType)) { @@ -277,9 +285,9 @@ public class GatewaysManager { } return -1; } - + private int getPositionFromTimezoneCalculatedList(VpnProfile profile) { - TransportType transportType = profile.mUsePluggableTransports ? OBFS4 : OPENVPN; + TransportType transportType = profile.getTransportType(); GatewaySelector gatewaySelector = new GatewaySelector(new ArrayList<>(gateways.values())); Gateway gateway; int nClosest = 0; 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 62c267ac..58732713 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -17,6 +17,7 @@ package se.leap.bitmaskclient.eip; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4_KCP; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; import static se.leap.bitmaskclient.base.models.Constants.CAPABILITIES; import static se.leap.bitmaskclient.base.models.Constants.IP_ADDRESS; @@ -55,28 +56,30 @@ import se.leap.bitmaskclient.base.utils.ConfigHelper; import se.leap.bitmaskclient.pluggableTransports.Obfs4Options; public class VpnConfigGenerator { - private JSONObject generalConfiguration; - private JSONObject gateway; - private JSONObject secrets; + private final JSONObject generalConfiguration; + private final JSONObject gateway; + private final JSONObject secrets; private JSONObject obfs4Transport; - private int apiVersion; - private boolean preferUDP; + private JSONObject obfs4TKcpTransport; + private final int apiVersion; + private final boolean preferUDP; + private final boolean experimentalTransports; public final static String TAG = VpnConfigGenerator.class.getSimpleName(); private final String newLine = System.getProperty("line.separator"); // Platform new line - public VpnConfigGenerator(JSONObject generalConfiguration, JSONObject secrets, JSONObject gateway, int apiVersion, boolean preferUDP) throws ConfigParser.ConfigParseError { + public VpnConfigGenerator(JSONObject generalConfiguration, JSONObject secrets, JSONObject gateway, int apiVersion, boolean preferUDP, boolean experimentalTransports) throws ConfigParser.ConfigParseError { this.generalConfiguration = generalConfiguration; this.gateway = gateway; this.secrets = secrets; this.apiVersion = apiVersion; this.preferUDP = preferUDP; + this.experimentalTransports = experimentalTransports; checkCapabilities(); } public void checkCapabilities() throws ConfigParser.ConfigParseError { - try { if (apiVersion >= 3) { JSONArray supportedTransports = gateway.getJSONObject(CAPABILITIES).getJSONArray(TRANSPORT); @@ -84,7 +87,11 @@ public class VpnConfigGenerator { JSONObject transport = supportedTransports.getJSONObject(i); if (transport.getString(TYPE).equals(OBFS4.toString())) { obfs4Transport = transport; - break; + if (!experimentalTransports) { + break; + } + } else if (experimentalTransports && transport.getString(TYPE).equals(OBFS4_KCP.toString())) { + obfs4TKcpTransport = transport; } } } @@ -108,6 +115,13 @@ public class VpnConfigGenerator { e.printStackTrace(); } } + if (supportsObfs4Kcp()) { + try { + profiles.put(OBFS4_KCP, createProfile(OBFS4_KCP)); + } catch (ConfigParser.ConfigParseError | NumberFormatException | JSONException | IOException e) { + e.printStackTrace(); + } + } return profiles; } @@ -115,6 +129,10 @@ public class VpnConfigGenerator { return obfs4Transport != null; } + private boolean supportsObfs4Kcp() { + return obfs4TKcpTransport != null; + } + private String getConfigurationString(Connection.TransportType transportType) { return generalConfiguration() + newLine @@ -131,18 +149,20 @@ public class VpnConfigGenerator { ConfigParser icsOpenvpnConfigParser = new ConfigParser(); icsOpenvpnConfigParser.parseConfig(new StringReader(configuration)); if (transportType == OBFS4) { - icsOpenvpnConfigParser.setObfs4Options(getObfs4Options()); + icsOpenvpnConfigParser.setObfs4Options(getObfs4Options(obfs4Transport, false)); + } else if (transportType == OBFS4_KCP) { + icsOpenvpnConfigParser.setObfs4Options(getObfs4Options(obfs4TKcpTransport, true)); } return icsOpenvpnConfigParser.convertProfile(transportType); } - private Obfs4Options getObfs4Options() throws JSONException { - JSONObject transportOptions = obfs4Transport.getJSONObject(OPTIONS); + private Obfs4Options getObfs4Options(JSONObject transportJson, boolean useUdp) throws JSONException { + JSONObject transportOptions = transportJson.getJSONObject(OPTIONS); String iatMode = transportOptions.getString("iatMode"); String cert = transportOptions.getString("cert"); String port = obfs4Transport.getJSONArray(PORTS).getString(0); String ip = gateway.getString(IP_ADDRESS); - boolean udp = false; + boolean udp = useUdp; if (BuildConfig.obfsvpn_pinning) { cert = BuildConfig.obfsvpn_cert; -- cgit v1.2.3 From 573ecb07e250baef999711e339008dc0f0d3bb0b Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 15 Jul 2022 16:35:13 +0200 Subject: fix tests --- .../java/de/blinkt/openvpn/VpnProfileTest.java | 11 ++-- .../bitmaskclient/eip/GatewaysManagerTest.java | 61 +++++++++++----------- .../bitmaskclient/eip/VpnConfigGeneratorTest.java | 34 ++++++------ 3 files changed, 54 insertions(+), 52 deletions(-) diff --git a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java index 4e51bbc1..9675c877 100644 --- a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java +++ b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java @@ -7,6 +7,7 @@ import static org.junit.Assert.assertTrue; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4_KCP; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; import org.json.JSONException; @@ -28,10 +29,10 @@ import se.leap.bitmaskclient.pluggableTransports.Obfs4Options; @PrepareForTest({UUID.class, ConfigHelper.ObfsVpnHelper.class}) public class VpnProfileTest { - private static final String OPENVPNCONNECTION_PROFILE = "{\"mAuthenticationType\":2,\"mName\":\"mockProfile\",\"mTLSAuthDirection\":\"\",\"mUseLzo\":false,\"mUseTLSAuth\":false,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mOverrideDNS\":false,\"mSearchDomain\":\"blinkt.de\",\"mUseDefaultRoute\":true,\"mUsePull\":true,\"mCheckRemoteCN\":true,\"mExpectTLSCert\":false,\"mRemoteCN\":\"\",\"mPassword\":\"\",\"mUsername\":\"\",\"mRoutenopull\":false,\"mUseRandomHostname\":false,\"mUseFloat\":false,\"mUseCustomConfig\":false,\"mCustomConfigOptions\":\"\",\"mVerb\":\"1\",\"mCipher\":\"\",\"mDataCiphers\":\"\",\"mNobind\":true,\"mUseDefaultRoutev6\":true,\"mCustomRoutesv6\":\"\",\"mKeyPassword\":\"\",\"mPersistTun\":false,\"mConnectRetryMax\":\"-1\",\"mConnectRetry\":\"2\",\"mConnectRetryMaxTime\":\"300\",\"mUserEditable\":true,\"mAuth\":\"\",\"mX509AuthType\":3,\"mAllowLocalLAN\":false,\"mMssFix\":0,\"mConnections\":[{\"mServerName\":\"openvpn.example.com\",\"mServerPort\":\"1194\",\"mUseUdp\":false,\"mCustomConfiguration\":\"\",\"mUseCustomConfig\":false,\"mEnabled\":true,\"mConnectTimeout\":0,\"mProxyType\":\"NONE\",\"mProxyName\":\"proxy.example.com\",\"mProxyPort\":\"8080\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.OpenvpnConnection\"}],\"mRemoteRandom\":false,\"mAllowedAppsVpn\":[],\"mAllowedAppsVpnAreDisallowed\":true,\"mAllowAppVpnBypass\":false,\"mAuthRetry\":0,\"mTunMtu\":0,\"mPushPeerInfo\":false,\"mVersion\":0,\"mLastUsed\":0,\"mServerName\":\"openvpn.example.com\",\"mServerPort\":\"1194\",\"mUseUdp\":true,\"mTemporaryProfile\":false,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mProfileVersion\":7,\"mBlockUnusedAddressFamilies\":true,\"mUsePluggableTransports\":false}"; - private static final String OBFS4CONNECTION_PROFILE = "{\"mAuthenticationType\":2,\"mName\":\"mockProfile\",\"mTLSAuthDirection\":\"\",\"mUseLzo\":false,\"mUseTLSAuth\":false,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mOverrideDNS\":false,\"mSearchDomain\":\"blinkt.de\",\"mUseDefaultRoute\":true,\"mUsePull\":true,\"mCheckRemoteCN\":true,\"mExpectTLSCert\":false,\"mRemoteCN\":\"\",\"mPassword\":\"\",\"mUsername\":\"\",\"mRoutenopull\":false,\"mUseRandomHostname\":false,\"mUseFloat\":false,\"mUseCustomConfig\":false,\"mCustomConfigOptions\":\"\",\"mVerb\":\"1\",\"mCipher\":\"\",\"mDataCiphers\":\"\",\"mNobind\":true,\"mUseDefaultRoutev6\":true,\"mCustomRoutesv6\":\"\",\"mKeyPassword\":\"\",\"mPersistTun\":false,\"mConnectRetryMax\":\"-1\",\"mConnectRetry\":\"2\",\"mConnectRetryMaxTime\":\"300\",\"mUserEditable\":true,\"mAuth\":\"\",\"mX509AuthType\":3,\"mAllowLocalLAN\":false,\"mMssFix\":0,\"mConnections\":[{\"options\":{\"udp\":false,\"cert\":\"CERT\",\"iatMode\":\"1\",\"remoteIP\":\"192.168.0.1\",\"remotePort\":\"1234\"},\"mServerName\":\"127.0.0.1\",\"mServerPort\":\"4430\",\"mUseUdp\":false,\"mCustomConfiguration\":\"\",\"mUseCustomConfig\":false,\"mEnabled\":true,\"mConnectTimeout\":0,\"mProxyType\":\"NONE\",\"mProxyName\":\"\",\"mProxyPort\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\"}],\"mRemoteRandom\":false,\"mAllowedAppsVpn\":[],\"mAllowedAppsVpnAreDisallowed\":true,\"mAllowAppVpnBypass\":false,\"mAuthRetry\":0,\"mTunMtu\":0,\"mPushPeerInfo\":false,\"mVersion\":0,\"mLastUsed\":0,\"mServerName\":\"openvpn.example.com\",\"mServerPort\":\"1194\",\"mUseUdp\":true,\"mTemporaryProfile\":false,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mProfileVersion\":7,\"mBlockUnusedAddressFamilies\":true,\"mUsePluggableTransports\":true}"; - private static final String OBFS4CONNECTION_PROFILE_OBFSVPN = "{\"mAuthenticationType\":2,\"mName\":\"mockProfile\",\"mTLSAuthDirection\":\"\",\"mUseLzo\":false,\"mUseTLSAuth\":false,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mOverrideDNS\":false,\"mSearchDomain\":\"blinkt.de\",\"mUseDefaultRoute\":true,\"mUsePull\":true,\"mCheckRemoteCN\":true,\"mExpectTLSCert\":false,\"mRemoteCN\":\"\",\"mPassword\":\"\",\"mUsername\":\"\",\"mRoutenopull\":false,\"mUseRandomHostname\":false,\"mUseFloat\":false,\"mUseCustomConfig\":false,\"mCustomConfigOptions\":\"\",\"mVerb\":\"1\",\"mCipher\":\"\",\"mDataCiphers\":\"\",\"mNobind\":true,\"mUseDefaultRoutev6\":true,\"mCustomRoutesv6\":\"\",\"mKeyPassword\":\"\",\"mPersistTun\":false,\"mConnectRetryMax\":\"-1\",\"mConnectRetry\":\"2\",\"mConnectRetryMaxTime\":\"300\",\"mUserEditable\":true,\"mAuth\":\"\",\"mX509AuthType\":3,\"mAllowLocalLAN\":false,\"mMssFix\":0,\"mConnections\":[{\"options\":{\"udp\":false,\"cert\":\"CERT\",\"iatMode\":\"1\",\"remoteIP\":\"192.168.0.1\",\"remotePort\":\"1234\"},\"mServerName\":\"192.168.0.1\",\"mServerPort\":\"1234\",\"mUseUdp\":false,\"mCustomConfiguration\":\"\",\"mUseCustomConfig\":false,\"mEnabled\":true,\"mConnectTimeout\":0,\"mProxyType\":\"SOCKS5\",\"mProxyName\":\"127.0.0.1\",\"mProxyPort\":\"4430\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\"}],\"mRemoteRandom\":false,\"mAllowedAppsVpn\":[],\"mAllowedAppsVpnAreDisallowed\":true,\"mAllowAppVpnBypass\":false,\"mAuthRetry\":0,\"mTunMtu\":0,\"mPushPeerInfo\":false,\"mVersion\":0,\"mLastUsed\":0,\"mServerName\":\"openvpn.example.com\",\"mServerPort\":\"1194\",\"mUseUdp\":true,\"mTemporaryProfile\":false,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mProfileVersion\":7,\"mBlockUnusedAddressFamilies\":true,\"mUsePluggableTransports\":true}"; - private static final String OBFS4CONNECTION_PROFILE_OBFSVPN_KCP = "{\"mAuthenticationType\":2,\"mName\":\"mockProfile\",\"mTLSAuthDirection\":\"\",\"mUseLzo\":false,\"mUseTLSAuth\":false,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mOverrideDNS\":false,\"mSearchDomain\":\"blinkt.de\",\"mUseDefaultRoute\":true,\"mUsePull\":true,\"mCheckRemoteCN\":true,\"mExpectTLSCert\":false,\"mRemoteCN\":\"\",\"mPassword\":\"\",\"mUsername\":\"\",\"mRoutenopull\":false,\"mUseRandomHostname\":false,\"mUseFloat\":false,\"mUseCustomConfig\":false,\"mCustomConfigOptions\":\"\",\"mVerb\":\"1\",\"mCipher\":\"\",\"mDataCiphers\":\"\",\"mNobind\":true,\"mUseDefaultRoutev6\":true,\"mCustomRoutesv6\":\"\",\"mKeyPassword\":\"\",\"mPersistTun\":false,\"mConnectRetryMax\":\"-1\",\"mConnectRetry\":\"2\",\"mConnectRetryMaxTime\":\"300\",\"mUserEditable\":true,\"mAuth\":\"\",\"mX509AuthType\":3,\"mAllowLocalLAN\":false,\"mMssFix\":0,\"mConnections\":[{\"options\":{\"udp\":true,\"cert\":\"CERT\",\"iatMode\":\"1\",\"remoteIP\":\"192.168.0.1\",\"remotePort\":\"1234\"},\"mServerName\":\"192.168.0.1\",\"mServerPort\":\"1234\",\"mUseUdp\":false,\"mCustomConfiguration\":\"\",\"mUseCustomConfig\":false,\"mEnabled\":true,\"mConnectTimeout\":0,\"mProxyType\":\"SOCKS5\",\"mProxyName\":\"127.0.0.1\",\"mProxyPort\":\"4430\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\"}],\"mRemoteRandom\":false,\"mAllowedAppsVpn\":[],\"mAllowedAppsVpnAreDisallowed\":true,\"mAllowAppVpnBypass\":false,\"mAuthRetry\":0,\"mTunMtu\":0,\"mPushPeerInfo\":false,\"mVersion\":0,\"mLastUsed\":0,\"mServerName\":\"openvpn.example.com\",\"mServerPort\":\"1194\",\"mUseUdp\":true,\"mTemporaryProfile\":false,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mProfileVersion\":7,\"mBlockUnusedAddressFamilies\":true,\"mUsePluggableTransports\":true}"; + private static final String OPENVPNCONNECTION_PROFILE = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mUseObfs4\":false,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mUseObfs4Kcp\":false,\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mUseUdp\":false,\"mServerName\":\"openvpn.example.com\",\"mProxyType\":\"NONE\",\"mProxyPort\":\"8080\",\"mUseCustomConfig\":false,\"mConnectTimeout\":0,\"mProxyName\":\"proxy.example.com\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.OpenvpnConnection\",\"mServerPort\":\"1194\",\"mEnabled\":true}],\"mUseLzo\":false,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}"; + private static final String OBFS4CONNECTION_PROFILE = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mUseObfs4\":true,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mUseObfs4Kcp\":false,\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mServerName\":\"127.0.0.1\",\"mProxyType\":\"NONE\",\"mConnectTimeout\":0,\"mServerPort\":\"4430\",\"mUseUdp\":false,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"udp\":false,\"remoteIP\":\"192.168.0.1\",\"iatMode\":\"1\",\"remotePort\":\"1234\",\"cert\":\"CERT\"},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}"; + private static final String OBFS4CONNECTION_PROFILE_OBFSVPN = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mUseObfs4\":true,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mUseObfs4Kcp\":false,\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mServerName\":\"192.168.0.1\",\"mProxyType\":\"SOCKS5\",\"mConnectTimeout\":0,\"mServerPort\":\"1234\",\"mUseUdp\":false,\"mProxyPort\":\"4430\",\"mUseCustomConfig\":false,\"options\":{\"udp\":false,\"remoteIP\":\"192.168.0.1\",\"iatMode\":\"1\",\"remotePort\":\"1234\",\"cert\":\"CERT\"},\"mProxyName\":\"127.0.0.1\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}"; + private static final String OBFS4CONNECTION_PROFILE_OBFSVPN_KCP = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mUseObfs4\":false,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mUseObfs4Kcp\":true,\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mServerName\":\"192.168.0.1\",\"mProxyType\":\"SOCKS5\",\"mConnectTimeout\":0,\"mServerPort\":\"1234\",\"mUseUdp\":false,\"mProxyPort\":\"4430\",\"mUseCustomConfig\":false,\"options\":{\"udp\":true,\"remoteIP\":\"192.168.0.1\",\"iatMode\":\"1\",\"remotePort\":\"1234\",\"cert\":\"CERT\"},\"mProxyName\":\"127.0.0.1\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}\n"; @Before public void setup() { @@ -105,7 +106,7 @@ public class VpnProfileTest { public void toJson_obfs4_obfsvpn_kcp() throws JSONException { when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); - VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4); + VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4_KCP); mockVpnProfile.mConnections[0] = new Obfs4Connection(new Obfs4Options("192.168.0.1", "1234", "CERT", "1", true)); mockVpnProfile.mLastUsed = 0; String s = mockVpnProfile.toJson(); diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java index 729abcdf..ec57dfac 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java @@ -22,6 +22,7 @@ import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConfigParser; import de.blinkt.openvpn.core.connection.Connection; import se.leap.bitmaskclient.base.models.Location; +import se.leap.bitmaskclient.base.models.Pair; import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.models.ProviderObservable; import se.leap.bitmaskclient.base.utils.ConfigHelper; @@ -115,7 +116,7 @@ public class GatewaysManagerTest { MockHelper.mockProviderObservable(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3, false); + VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3, false, false); VpnProfile profile = configGenerator.createProfile(OBFS4); profile.mGatewayIp = "37.218.247.60"; @@ -130,7 +131,7 @@ public class GatewaysManagerTest { MockHelper.mockProviderObservable(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3, false); + VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3, false, false); VpnProfile profile = configGenerator.createProfile(OPENVPN); profile.mGatewayIp = "37.218.247.60"; @@ -145,7 +146,7 @@ public class GatewaysManagerTest { MockHelper.mockProviderObservable(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3, false); + VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3, false, false); VpnProfile profile = configGenerator.createProfile(OBFS4); profile.mGatewayIp = "37.218.247.60"; @@ -160,7 +161,7 @@ public class GatewaysManagerTest { MockHelper.mockProviderObservable(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3, false); + VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3, false, false); VpnProfile profile = configGenerator.createProfile(OPENVPN); profile.mGatewayIp = "37.218.247.60"; @@ -175,7 +176,7 @@ public class GatewaysManagerTest { MockHelper.mockProviderObservable(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3, false); + VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3, false, false); VpnProfile profile = configGenerator.createProfile(OBFS4); profile.mGatewayIp = "37.218.247.61"; @@ -190,7 +191,7 @@ public class GatewaysManagerTest { MockHelper.mockProviderObservable(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3, false); + VpnConfigGenerator configGenerator = new VpnConfigGenerator(provider.getDefinition(), secrets, gateway1, 3, false, false); VpnProfile profile = configGenerator.createProfile(OBFS4); profile.mGatewayIp = "3.21.247.89"; @@ -206,7 +207,7 @@ public class GatewaysManagerTest { when(PreferenceHelper.getUseBridges(any(Context.class))).thenReturn(true); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("37.12.247.10", gatewaysManager.select(0).getRemoteIP()); + assertEquals("37.12.247.10", gatewaysManager.select(0).first.getRemoteIP()); } @Test @@ -219,9 +220,9 @@ public class GatewaysManagerTest { when(PreferenceHelper.getUseBridges(any(Context.class))).thenReturn(false); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("manila.bitmask.net", gatewaysManager.select(0).getHost()); - assertEquals("moscow.bitmask.net", gatewaysManager.select(1).getHost()); - assertEquals("pt.demo.bitmask.net", gatewaysManager.select(2).getHost()); + assertEquals("manila.bitmask.net", gatewaysManager.select(0).first.getHost()); + assertEquals("moscow.bitmask.net", gatewaysManager.select(1).first.getHost()); + assertEquals("pt.demo.bitmask.net", gatewaysManager.select(2).first.getHost()); } @Test @@ -234,8 +235,8 @@ public class GatewaysManagerTest { when(PreferenceHelper.getUseBridges(any(Context.class))).thenReturn(true); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("moscow.bitmask.net", gatewaysManager.select(0).getHost()); - assertEquals("pt.demo.bitmask.net", gatewaysManager.select(1).getHost()); + assertEquals("moscow.bitmask.net", gatewaysManager.select(0).first.getHost()); + assertEquals("pt.demo.bitmask.net", gatewaysManager.select(1).first.getHost()); assertNull(gatewaysManager.select(2)); } @@ -251,9 +252,9 @@ public class GatewaysManagerTest { when(PreferenceHelper.getPreferredCity(any(Context.class))).thenReturn("Paris"); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("mouette.riseup.net", gatewaysManager.select(0).getHost()); - assertEquals("hoatzin.riseup.net", gatewaysManager.select(1).getHost()); - assertEquals("zarapito.riseup.net", gatewaysManager.select(2).getHost()); + assertEquals("mouette.riseup.net", gatewaysManager.select(0).first.getHost()); + assertEquals("hoatzin.riseup.net", gatewaysManager.select(1).first.getHost()); + assertEquals("zarapito.riseup.net", gatewaysManager.select(2).first.getHost()); } @Test @@ -267,9 +268,9 @@ public class GatewaysManagerTest { when(PreferenceHelper.getPreferredCity(any(Context.class))).thenReturn("Paris"); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("mouette.riseup.net", gatewaysManager.select(0).getHost()); - assertEquals("hoatzin.riseup.net", gatewaysManager.select(1).getHost()); - assertEquals("zarapito.riseup.net", gatewaysManager.select(2).getHost()); + assertEquals("mouette.riseup.net", gatewaysManager.select(0).first.getHost()); + assertEquals("hoatzin.riseup.net", gatewaysManager.select(1).first.getHost()); + assertEquals("zarapito.riseup.net", gatewaysManager.select(2).first.getHost()); } @Test @@ -284,9 +285,9 @@ public class GatewaysManagerTest { when(PreferenceHelper.getPreferredCity(any(Context.class))).thenReturn("Paris"); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("Paris", gatewaysManager.select(0).getName()); - assertEquals("Paris", gatewaysManager.select(1).getName()); - assertEquals("Paris", gatewaysManager.select(2).getName()); + assertEquals("Paris", gatewaysManager.select(0).first.getName()); + assertEquals("Paris", gatewaysManager.select(1).first.getName()); + assertEquals("Paris", gatewaysManager.select(2).first.getName()); assertEquals(null, gatewaysManager.select(3)); } @@ -300,9 +301,9 @@ public class GatewaysManagerTest { when(PreferenceHelper.getUseBridges(any(Context.class))).thenReturn(false); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("mouette.riseup.net", gatewaysManager.select(0, "Paris").getHost()); - assertEquals("hoatzin.riseup.net", gatewaysManager.select(1, "Paris").getHost()); - assertEquals("zarapito.riseup.net", gatewaysManager.select(2, "Paris").getHost()); + assertEquals("mouette.riseup.net", gatewaysManager.select(0, "Paris").first.getHost()); + assertEquals("hoatzin.riseup.net", gatewaysManager.select(1, "Paris").first.getHost()); + assertEquals("zarapito.riseup.net", gatewaysManager.select(2, "Paris").first.getHost()); } @Test @@ -315,9 +316,9 @@ public class GatewaysManagerTest { when(PreferenceHelper.getUseBridges(any(Context.class))).thenReturn(false); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("mouette.riseup.net", gatewaysManager.select(0, "Paris").getHost()); - assertEquals("hoatzin.riseup.net", gatewaysManager.select(1, "Paris").getHost()); - assertEquals("zarapito.riseup.net", gatewaysManager.select(2, "Paris").getHost()); + assertEquals("mouette.riseup.net", gatewaysManager.select(0, "Paris").first.getHost()); + assertEquals("hoatzin.riseup.net", gatewaysManager.select(1, "Paris").first.getHost()); + assertEquals("zarapito.riseup.net", gatewaysManager.select(2, "Paris").first.getHost()); } @Test @@ -331,9 +332,9 @@ public class GatewaysManagerTest { when(PreferenceHelper.getUseBridges(any(Context.class))).thenReturn(false); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); - assertEquals("Paris", gatewaysManager.select(0, "Paris").getName()); - assertEquals("Paris", gatewaysManager.select(1, "Paris").getName()); - assertEquals("Paris", gatewaysManager.select(2, "Paris").getName()); + assertEquals("Paris", gatewaysManager.select(0, "Paris").first.getName()); + assertEquals("Paris", gatewaysManager.select(1, "Paris").first.getName()); + assertEquals("Paris", gatewaysManager.select(2, "Paris").first.getName()); assertEquals(null, gatewaysManager.select(3, "Paris")); } 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 2431542f..1bd7894b 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java @@ -1435,7 +1435,7 @@ public class VpnConfigGeneratorTest { @Test public void testGenerateVpnProfile_v1_tcp_udp() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("gateway_tcp_udp.json"))); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 1, false); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 1, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertFalse(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v1_tcp_udp.trim())); @@ -1444,7 +1444,7 @@ public class VpnConfigGeneratorTest { @Test public void testGenerateVpnProfile_v1_udp_tcp() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("gateway_udp_tcp.json"))); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 1, false); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 1, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertFalse(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v1_udp_tcp.trim())); @@ -1453,7 +1453,7 @@ public class VpnConfigGeneratorTest { @Test public void testGenerateVpnProfile_v2_tcp_udp() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("gateway_tcp_udp.json"))); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 2, false); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 2, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertFalse(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v1_tcp_udp.trim())); @@ -1462,7 +1462,7 @@ public class VpnConfigGeneratorTest { @Test public void testGenerateVpnProfile_v2_udp_tcp() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("gateway_udp_tcp.json"))); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 2, false); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 2, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertFalse(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v1_udp_tcp.trim())); @@ -1473,7 +1473,7 @@ public class VpnConfigGeneratorTest { public void testGenerateVpnProfile_v3_obfs4() throws Exception { when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(false); gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo.bitmask.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertTrue(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.containsKey(OPENVPN)); @@ -1485,7 +1485,7 @@ public class VpnConfigGeneratorTest { public void testGenerateVpnProfile_v3_obfs4_obfsvpn() throws Exception { when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo.bitmask.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertTrue(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.containsKey(OPENVPN)); @@ -1496,7 +1496,7 @@ public class VpnConfigGeneratorTest { @Test public void testGenerateVpnProfile_v3_ovpn_tcp_udp() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_pt_tcp_udp.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertTrue(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.containsKey(OPENVPN)); @@ -1507,7 +1507,7 @@ public class VpnConfigGeneratorTest { @Test public void testGenerateVpnProfile_v3_ovpn_udp_tcp() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_pt_udp_tcp.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertTrue(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.containsKey(OPENVPN)); @@ -1520,7 +1520,7 @@ public class VpnConfigGeneratorTest { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_pt_udp_tcp.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); //delete "data-ciphers" from config to test if the resulting openvpn config file will contain the default value taken from "cipher" flag generalConfig.put("data-ciphers", null); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertTrue(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.containsKey(OPENVPN)); @@ -1532,7 +1532,7 @@ public class VpnConfigGeneratorTest { public void testGenerateVpnProfile_v4_ovpn_tcp_udp() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/ptdemo_pt_tcp_udp.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/ptdemo_pt_tcp_udp.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 4, false); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 4, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertTrue(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.containsKey(OPENVPN)); @@ -1544,7 +1544,7 @@ public class VpnConfigGeneratorTest { public void testGenerateVpnProfile_v4_ovpn_udp_tcp() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/ptdemo_pt_udp_tcp.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/ptdemo_pt_udp_tcp.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 4, false); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 4, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertTrue(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.containsKey(OPENVPN)); @@ -1557,7 +1557,7 @@ public class VpnConfigGeneratorTest { public void testGenerateVpnProfile_v3_ipv6only_allowOpenvpnIPv6Only() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_ipv6.json"))).getJSONArray("gateways").getJSONObject(0); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_ipv6.json"))).getJSONObject(OPENVPN_CONFIGURATION); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertTrue(vpnProfiles.containsKey(OPENVPN)); } @@ -1566,7 +1566,7 @@ public class VpnConfigGeneratorTest { public void testGenerateVpnProfile_v3_obfs4IPv6_skip() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_ipv6.json"))).getJSONArray("gateways").getJSONObject(0); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_ipv6.json"))).getJSONObject(OPENVPN_CONFIGURATION); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertFalse(vpnProfiles.containsKey(OBFS4)); } @@ -1578,7 +1578,7 @@ public class VpnConfigGeneratorTest { public void testGenerateVpnProfile_v3_obfs4IPv4AndIPv6_skipIPv6() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_ipv4ipv6.json"))).getJSONArray("gateways").getJSONObject(0); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_ipv4ipv6.json"))).getJSONObject(OPENVPN_CONFIGURATION); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertTrue(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.containsKey(OPENVPN)); @@ -1593,7 +1593,7 @@ public class VpnConfigGeneratorTest { public void testGenerateVpnProfile_v3_obfs4udp_skip() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_udp.json"))).getJSONArray("gateways").getJSONObject(0); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_udp.json"))).getJSONObject(OPENVPN_CONFIGURATION); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertFalse(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.containsKey(OPENVPN)); @@ -1603,7 +1603,7 @@ public class VpnConfigGeneratorTest { public void testGenerateVpnProfile_v3_obfs4UDPAndTCP_skipUDP() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_udptcp.json"))).getJSONArray("gateways").getJSONObject(0); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_misconfigured_udptcp.json"))).getJSONObject(OPENVPN_CONFIGURATION); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertTrue(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.containsKey(OPENVPN)); @@ -1615,7 +1615,7 @@ public class VpnConfigGeneratorTest { public void testGenerateVpnProfile_preferUDP_firstRemotesUDP() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/multiport_tcpudp_eip-service.json"))).getJSONArray("gateways").getJSONObject(0); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/multiport_tcpudp_eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, true); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, true, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertTrue(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.containsKey(OPENVPN)); -- cgit v1.2.3 From 93c7fd8c592a85341e8dff594ba1ec535aa103c2 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 15 Jul 2022 20:46:07 +0200 Subject: add some more tests for kcp transport handling --- .../bitmaskclient/eip/GatewaysManagerTest.java | 33 +++++ .../bitmaskclient/eip/VpnConfigGeneratorTest.java | 15 +- app/src/test/resources/ptdemo_kcp_gateways.json | 160 +++++++++++++++++++++ .../test/resources/ptdemo_kcp_gateways_geoip.json | 29 ++++ 4 files changed, 235 insertions(+), 2 deletions(-) create mode 100644 app/src/test/resources/ptdemo_kcp_gateways.json create mode 100644 app/src/test/resources/ptdemo_kcp_gateways_geoip.json diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java index ec57dfac..56242396 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java @@ -32,6 +32,7 @@ import se.leap.bitmaskclient.testutils.MockSharedPreferences; import se.leap.bitmaskclient.testutils.TestSetupHelper; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4_KCP; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNull; @@ -510,6 +511,38 @@ public class GatewaysManagerTest { assertEquals("Amsterdam", locations.get(2).getName()); } + // Currently all pluggable transports are handled the same, there's no UI to select a specific one + // when requesting a sorted list for any pluggabled transport, a sorted list of all pluiggable transports + // will be returned + @Test + public void testGetSortedLocations_obfs4kcp_generalizedAsPT() { + Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v4_bad_obfs4_gateway.json"); + + MockHelper.mockProviderObservable(provider); + mockStatic(PreferenceHelper.class); + when(PreferenceHelper.getUseBridges(any(Context.class))).thenReturn(false); + GatewaysManager gatewaysManager = new GatewaysManager(mockContext); + List locations = gatewaysManager.getSortedGatewayLocations(OBFS4_KCP); + + assertEquals(3, locations.size()); + } + + @Test + public void testgetAverageLoad_isSameForAllTransports() { + Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_kcp_gateways.json", "ptdemo_kcp_gateways_geoip.json"); + + MockHelper.mockProviderObservable(provider); + mockStatic(PreferenceHelper.class); + when(PreferenceHelper.getUseBridges(any(Context.class))).thenReturn(false); + GatewaysManager gatewaysManager = new GatewaysManager(mockContext); + + assertEquals(0.3, gatewaysManager.getLocation("Amsterdam").getAverageLoad(OBFS4_KCP)); + assertEquals(0.3, gatewaysManager.getLocation("Amsterdam").getAverageLoad(OBFS4)); + assertEquals(0.3, gatewaysManager.getLocation("Amsterdam").getAverageLoad(OPENVPN)); + } + + + @Test public void testGetLoadForLocation_() { MockHelper.mockProviderObservable(null); 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 1bd7894b..731ff1c8 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java @@ -9,6 +9,7 @@ import static org.mockito.Mockito.mock; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4_KCP; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; import static se.leap.bitmaskclient.base.models.Constants.OPENVPN_CONFIGURATION; import static se.leap.bitmaskclient.testutils.MockHelper.mockTextUtils; @@ -1429,7 +1430,6 @@ public class VpnConfigGeneratorTest { when(preferences.getBoolean("usesystemproxy", true)).thenReturn(true); when(context.getCacheDir()).thenReturn(new File("/data/data/se.leap.bitmask")); mockStatic(ConfigHelper.ObfsVpnHelper.class); - } @Test @@ -1628,10 +1628,21 @@ public class VpnConfigGeneratorTest { public void testGenerateVpnProfile_testNewCiphers() throws Exception { gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/ptdemo_pt_tcp_udp_new_ciphers.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/ptdemo_pt_tcp_udp_new_ciphers.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION); - vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 4, false); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 4, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); System.out.println(vpnProfiles.get(OPENVPN).getConfigFile(context, false)); assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v4_ovpn_tcp_udp_new_ciphers.trim())); } + public void testGenerateVpnProfileExperimentalTransportsEnabled () throws Exception { + gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_kcp_gateways.json"))).getJSONArray("gateways").getJSONObject(0); + generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_kcp_gateways.json"))).getJSONObject(OPENVPN_CONFIGURATION); + vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 3, true, true); + HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); + assertTrue(vpnProfiles.containsKey(OBFS4)); + assertTrue(vpnProfiles.containsKey(OBFS4_KCP)); + assertTrue(vpnProfiles.containsKey(OPENVPN)); + + } + } \ No newline at end of file diff --git a/app/src/test/resources/ptdemo_kcp_gateways.json b/app/src/test/resources/ptdemo_kcp_gateways.json new file mode 100644 index 00000000..332c8c11 --- /dev/null +++ b/app/src/test/resources/ptdemo_kcp_gateways.json @@ -0,0 +1,160 @@ +{ + "gateways":[ + { + "capabilities":{ + "adblock":false, + "filter_dns":false, + "limited":false, + "transport":[ + { + "type":"obfs4", + "protocols":[ + "tcp" + ], + "ports":[ + "23049" + ], + "options": { + "cert": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1", + "iatMode": "0" + } + }, + { + "type":"obfs4-1", + "protocols":[ + "tcp" + ], + "ports":[ + "23050" + ], + "options": { + "cert": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1", + "iatMode": "0" + } + }, + { + "type":"openvpn", + "protocols":[ + "tcp" + ], + "ports":[ + "1195" + ] + } + ], + "user_ips":false + }, + "host":"pt.demo.bitmask.net", + "ip_address":"37.218.247.60", + "location":"Amsterdam" + }, + { + "capabilities":{ + "adblock":false, + "filter_dns":false, + "limited":false, + "transport":[ + { + "type":"obfs4", + "protocols":[ + "tcp" + ], + "ports":[ + "443" + ], + "options": { + "cert": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX2", + "iatMode": "0" + } + }, + { + "type":"openvpn", + "protocols":[ + "tcp" + ], + "ports":[ + "1195" + ] + } + ], + "user_ips":false + }, + "host":"moscow.bitmask.net", + "ip_address":"3.21.247.89", + "location":"moscow" + }, + { + "capabilities":{ + "adblock":false, + "filter_dns":false, + "limited":false, + "transport":[ + { + "type":"openvpn", + "protocols":[ + "tcp", + "udp" + ], + + "ports":[ + "1195" + ] + }, + { + "type":"obfs4-1", + "protocols":[ + "tcp" + ], + "ports":[ + "23050" + ], + "options": { + "cert": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1", + "iatMode": "0" + } + } + ], + "user_ips":false + }, + "host":"manila.bitmask.net", + "ip_address":"37.12.247.10", + "location":"manila" + } + ], + "locations":{ + "Amsterdam":{ + "country_code":"NL", + "hemisphere":"N", + "name":"Amsterdam", + "timezone":"-1" + }, + "moscow": { + "country_code": "RU", + "hemisphere": "N", + "name": "Moscow", + "timezone": "+3" + }, + "manila": { + "country_code": "PH", + "hemisphere": "N", + "name": "Manila", + "timezone": "+8" + } + }, + "openvpn_configuration":{ + "auth":"SHA1", + "cipher":"AES-256-CBC", + "keepalive":"10 30", + "tls-cipher":"DHE-RSA-AES128-SHA", + "tun-ipv6":true, + "dev" : "tun", + "sndbuf" : "0", + "rcvbuf" : "0", + "nobind" : true, + "persist-key" : true, + "key-direction" : "1", + "verb" : "3" + }, + "serial":2, + "version":3 +} \ No newline at end of file diff --git a/app/src/test/resources/ptdemo_kcp_gateways_geoip.json b/app/src/test/resources/ptdemo_kcp_gateways_geoip.json new file mode 100644 index 00000000..9ac7257d --- /dev/null +++ b/app/src/test/resources/ptdemo_kcp_gateways_geoip.json @@ -0,0 +1,29 @@ +{ + "ip":"51.158.144.32", + "cc":"FR", + "city":"Paris", + "lat":48.8628, + "lon":2.3292, + "gateways":[ + "pt.demo.bitmask.net", + "moscow.bitmask.net", + "manila.bitmask.net" + ], + "sortedGateways": [ + { + "host": "pt.demo.bitmask.net", + "fullness": 0.3, + "overload": false + }, + { + "host": "moscow.bitmask.net", + "fullness": 0.36, + "overload": false + }, + { + "host": "manila.bitmask.net", + "fullness": 0.59, + "overload": false + } + ] +} \ No newline at end of file -- cgit v1.2.3 From 472a3fdb9c9036f5666e65b5dfd9bd91a51563f8 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 15 Jul 2022 22:08:57 +0200 Subject: add UI to enable experimental kcp transport if the client uses obfsvpn instead of shapeshifter and the provider supports the kcp variant --- .../base/fragments/SettingsFragment.java | 21 ++++ .../leap/bitmaskclient/base/models/Provider.java | 27 ++++- app/src/main/res/layout/f_settings.xml | 9 ++ .../bitmaskclient/base/models/ProviderTest.java | 83 ++++++++++++- ...demo_only_experimental_transports_gateways.json | 134 +++++++++++++++++++++ 5 files changed, 266 insertions(+), 8 deletions(-) create mode 100644 app/src/test/resources/ptdemo_only_experimental_transports_gateways.json 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 f4531ff8..94f737b4 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 @@ -9,12 +9,15 @@ import static se.leap.bitmaskclient.base.models.Constants.PREFER_UDP; import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; 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.utils.ConfigHelper.ObfsVpnHelper.useObfsVpn; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.allowExperimentalTransports; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferUDP; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getShowAlwaysOnDialog; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseBridges; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseSnowflake; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.hasSnowflakePrefs; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.preferUDP; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.setAllowExperimentalTransports; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useBridges; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useSnowflake; import static se.leap.bitmaskclient.base.utils.ViewHelper.setActionBarTitle; @@ -81,6 +84,7 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh initFirewallEntry(view); initTetheringEntry(view); initGatewayPinningEntry(view); + initExperimentalTransportsEntry(view); setActionBarTitle(this, advanced_settings); return view; } @@ -249,6 +253,23 @@ 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()) { + experimentalTransports.setVisibility(VISIBLE); + experimentalTransports.setChecked(allowExperimentalTransports(this.getContext())); + experimentalTransports.setOnCheckedChangeListener((buttonView, isChecked) -> { + if (!buttonView.isPressed()) { + return; + } + setAllowExperimentalTransports(getContext(), isChecked); + }); + } else { + experimentalTransports.setVisibility(GONE); + } + + } + public void showTetheringAlert() { try { 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 02a9694a..7b8f22af 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 @@ -30,6 +30,7 @@ import java.net.URL; import java.util.Locale; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4_KCP; import static se.leap.bitmaskclient.base.models.Constants.CAPABILITIES; import static se.leap.bitmaskclient.base.models.Constants.GATEWAYS; import static se.leap.bitmaskclient.base.models.Constants.LOCATIONS; @@ -37,8 +38,12 @@ 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.ConfigHelper.ObfsVpnHelper.useObfsVpn; import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS; +import de.blinkt.openvpn.core.connection.Connection; +import de.blinkt.openvpn.core.connection.Connection.TransportType; + /** * @author Sean Leonard * @author Parménides GV @@ -161,6 +166,17 @@ public final class Provider implements Parcelable { } public boolean supportsPluggableTransports() { + if (useObfsVpn()) { + return supportsTransports(new TransportType[]{OBFS4, OBFS4_KCP}); + } + return supportsTransports(new TransportType[]{OBFS4}); + } + + public boolean supportsExperimentalPluggableTransports() { + return supportsTransports(new TransportType[]{OBFS4_KCP}); + } + + private boolean supportsTransports(TransportType[] transportTypes) { try { JSONArray gatewayJsons = eipServiceJson.getJSONArray(GATEWAYS); for (int i = 0; i < gatewayJsons.length(); i++) { @@ -168,15 +184,18 @@ public final class Provider implements Parcelable { getJSONObject(CAPABILITIES). getJSONArray(TRANSPORT); for (int j = 0; j < transports.length(); j++) { - if (OBFS4.toString().equals(transports.getJSONObject(j).getString(TYPE))) { - return true; + String supportedTransportType = transports.getJSONObject(j).getString(TYPE); + for (TransportType transportType : transportTypes) { + if (transportType.toString().equals(supportedTransportType)) { + return true; + } } } } } catch (Exception e) { - // ignore + // ignore } - return false; + return false; } public String getIpForHostname(String host) { diff --git a/app/src/main/res/layout/f_settings.xml b/app/src/main/res/layout/f_settings.xml index 7b8733cd..f89dc956 100644 --- a/app/src/main/res/layout/f_settings.xml +++ b/app/src/main/res/layout/f_settings.xml @@ -114,5 +114,14 @@ app:subtitle="Connect to a specific Gateway for debugging purposes" /> + + \ No newline at end of file diff --git a/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java b/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java index aaf3f255..8bff690b 100644 --- a/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java @@ -1,21 +1,36 @@ package se.leap.bitmaskclient.base.models; +import static junit.framework.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; +import static org.powermock.api.mockito.PowerMockito.mockStatic; + +import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; import java.util.HashSet; import java.util.Set; -import se.leap.bitmaskclient.base.models.Provider; +import se.leap.bitmaskclient.base.utils.ConfigHelper; import se.leap.bitmaskclient.testutils.TestSetupHelper; -import static junit.framework.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - /** * Created by cyberta on 12.02.18. */ + +@RunWith(PowerMockRunner.class) +@PrepareForTest({ConfigHelper.ObfsVpnHelper.class}) public class ProviderTest { + @Before + public void setup() { + mockStatic(ConfigHelper.ObfsVpnHelper.class); + when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(false); + } + @Test public void testEquals_sameFields_returnsTrue() throws Exception { Provider p1 = TestSetupHelper.getConfiguredProvider(); @@ -84,4 +99,64 @@ public class ProviderTest { assertFalse(p1.supportsPluggableTransports()); } + @Test + public void testIsExperimentalPluggableTransportsSupported_Obfs4_returnsFalse() throws Exception { + Provider p1 = TestSetupHelper.getProvider( + "https://pt.demo.bitmask.net", + null, + null, + null, + null, + null, + "ptdemo.bitmask.eip-service.json", + null); + assertFalse(p1.supportsExperimentalPluggableTransports()); + } + + @Test + public void testIsExperimentalPluggableTransportsSupported_Obfs4Kcp_returnsTrue() throws Exception { + Provider p1 = TestSetupHelper.getProvider( + "https://pt.demo.bitmask.net", + null, + null, + null, + null, + null, + "ptdemo_kcp_gateways.json", + null); + assertTrue(p1.supportsExperimentalPluggableTransports()); + } + + @Test + public void testSupportsPluggableTransports_Obfs4Kcp_noObsvpn_returnsFalse() throws Exception { + when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(false); + + Provider p1 = TestSetupHelper.getProvider( + "https://pt.demo.bitmask.net", + null, + null, + null, + null, + null, + "ptdemo_only_experimental_transports_gateways.json", + null); + assertFalse(p1.supportsPluggableTransports()); + } + + @Test + public void testSupportsPluggableTransports_Obfs4Kcp_obsvpn_returnsTrue() throws Exception { + when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + + Provider p1 = TestSetupHelper.getProvider( + "https://pt.demo.bitmask.net", + null, + null, + null, + null, + null, + "ptdemo_only_experimental_transports_gateways.json", + null); + assertTrue(p1.supportsPluggableTransports()); + } + } diff --git a/app/src/test/resources/ptdemo_only_experimental_transports_gateways.json b/app/src/test/resources/ptdemo_only_experimental_transports_gateways.json new file mode 100644 index 00000000..31c919e7 --- /dev/null +++ b/app/src/test/resources/ptdemo_only_experimental_transports_gateways.json @@ -0,0 +1,134 @@ +{ + "gateways":[ + { + "capabilities":{ + "adblock":false, + "filter_dns":false, + "limited":false, + "transport":[ + { + "type":"obfs4-1", + "protocols":[ + "tcp" + ], + "ports":[ + "23050" + ], + "options": { + "cert": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1", + "iatMode": "0" + } + }, + { + "type":"openvpn", + "protocols":[ + "tcp" + ], + "ports":[ + "1195" + ] + } + ], + "user_ips":false + }, + "host":"pt.demo.bitmask.net", + "ip_address":"37.218.247.60", + "location":"Amsterdam" + }, + { + "capabilities":{ + "adblock":false, + "filter_dns":false, + "limited":false, + "transport":[ + { + "type":"openvpn", + "protocols":[ + "tcp" + ], + "ports":[ + "1195" + ] + } + ], + "user_ips":false + }, + "host":"moscow.bitmask.net", + "ip_address":"3.21.247.89", + "location":"moscow" + }, + { + "capabilities":{ + "adblock":false, + "filter_dns":false, + "limited":false, + "transport":[ + { + "type":"openvpn", + "protocols":[ + "tcp", + "udp" + ], + + "ports":[ + "1195" + ] + }, + { + "type":"obfs4-1", + "protocols":[ + "tcp" + ], + "ports":[ + "23050" + ], + "options": { + "cert": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1", + "iatMode": "0" + } + } + ], + "user_ips":false + }, + "host":"manila.bitmask.net", + "ip_address":"37.12.247.10", + "location":"manila" + } + ], + "locations":{ + "Amsterdam":{ + "country_code":"NL", + "hemisphere":"N", + "name":"Amsterdam", + "timezone":"-1" + }, + "moscow": { + "country_code": "RU", + "hemisphere": "N", + "name": "Moscow", + "timezone": "+3" + }, + "manila": { + "country_code": "PH", + "hemisphere": "N", + "name": "Manila", + "timezone": "+8" + } + }, + "openvpn_configuration":{ + "auth":"SHA1", + "cipher":"AES-256-CBC", + "keepalive":"10 30", + "tls-cipher":"DHE-RSA-AES128-SHA", + "tun-ipv6":true, + "dev" : "tun", + "sndbuf" : "0", + "rcvbuf" : "0", + "nobind" : true, + "persist-key" : true, + "key-direction" : "1", + "verb" : "3" + }, + "serial":2, + "version":3 +} \ No newline at end of file -- cgit v1.2.3 From d02eb80bcce8b4fbb8b06c218b5b7726c0194388 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 15 Jul 2022 22:47:38 +0200 Subject: remove compiled bitmaskcore libs, ignore bitmaskcore build folder --- .gitignore | 19 +++++++++++++++++++ lib-bitmask-core-arm64/bitmaskcore_arm64-sources.jar | Bin 10185 -> 0 bytes lib-bitmask-core-arm64/bitmaskcore_arm64.aar | Bin 6360485 -> 0 bytes lib-bitmask-core-armv7/bitmaskcore_arm-sources.jar | Bin 10185 -> 0 bytes lib-bitmask-core-armv7/bitmaskcore_arm.aar | Bin 6419708 -> 0 bytes lib-bitmask-core-web/bitmaskcore_web-sources.jar | Bin 12042 -> 0 bytes lib-bitmask-core-web/bitmaskcore_web.aar | Bin 27715085 -> 0 bytes lib-bitmask-core-x86/bitmaskcore_x86-sources.jar | Bin 10185 -> 0 bytes lib-bitmask-core-x86/bitmaskcore_x86.aar | Bin 6843072 -> 0 bytes .../bitmaskcore_x86_64-sources.jar | Bin 10185 -> 0 bytes lib-bitmask-core-x86_64/bitmaskcore_x86_64.aar | Bin 7307748 -> 0 bytes lib-bitmask-core/bitmaskcore-sources.jar | Bin 10185 -> 0 bytes lib-bitmask-core/bitmaskcore.aar | Bin 26890543 -> 0 bytes 13 files changed, 19 insertions(+) delete mode 100644 lib-bitmask-core-arm64/bitmaskcore_arm64-sources.jar delete mode 100644 lib-bitmask-core-arm64/bitmaskcore_arm64.aar delete mode 100644 lib-bitmask-core-armv7/bitmaskcore_arm-sources.jar delete mode 100644 lib-bitmask-core-armv7/bitmaskcore_arm.aar delete mode 100644 lib-bitmask-core-web/bitmaskcore_web-sources.jar delete mode 100644 lib-bitmask-core-web/bitmaskcore_web.aar delete mode 100644 lib-bitmask-core-x86/bitmaskcore_x86-sources.jar delete mode 100644 lib-bitmask-core-x86/bitmaskcore_x86.aar delete mode 100644 lib-bitmask-core-x86_64/bitmaskcore_x86_64-sources.jar delete mode 100644 lib-bitmask-core-x86_64/bitmaskcore_x86_64.aar delete mode 100644 lib-bitmask-core/bitmaskcore-sources.jar delete mode 100644 lib-bitmask-core/bitmaskcore.aar diff --git a/.gitignore b/.gitignore index 5ff581a1..fb10e3e2 100644 --- a/.gitignore +++ b/.gitignore @@ -87,3 +87,22 @@ go/lib/bitmask-core-sources.jar go/lib/bitmask-core.aar go/lib/bitmask-web-core-sources.jar go/lib/bitmask-web-core.aar + +lib-bitmask-core-arm64/build +lib-bitmask-core-armv7/build +lib-bitmask-core-web/build +lib-bitmask-core-x86/build +lib-bitmask-core-x86_64/build +lib-bitmask-core/build +lib-bitmask-core-arm64/bitmaskcore_arm64-sources.jar +lib-bitmask-core-arm64/bitmaskcore_arm64.aar +lib-bitmask-core-armv7/bitmaskcore_arm-sources.jar +lib-bitmask-core-armv7/bitmaskcore_arm.aar +lib-bitmask-core-web/bitmaskcore_web-sources.jar +lib-bitmask-core-web/bitmaskcore_web.aar +lib-bitmask-core-x86/bitmaskcore_x86-sources.jar +lib-bitmask-core-x86/bitmaskcore_x86.aar +lib-bitmask-core-x86_64/bitmaskcore_x86_64-sources.jar +lib-bitmask-core-x86_64/bitmaskcore_x86_64.aar +lib-bitmask-core/bitmaskcore-sources.jar +lib-bitmask-core/bitmaskcore.aar diff --git a/lib-bitmask-core-arm64/bitmaskcore_arm64-sources.jar b/lib-bitmask-core-arm64/bitmaskcore_arm64-sources.jar deleted file mode 100644 index 043de8ec..00000000 Binary files a/lib-bitmask-core-arm64/bitmaskcore_arm64-sources.jar and /dev/null differ diff --git a/lib-bitmask-core-arm64/bitmaskcore_arm64.aar b/lib-bitmask-core-arm64/bitmaskcore_arm64.aar deleted file mode 100644 index ebd8cca3..00000000 Binary files a/lib-bitmask-core-arm64/bitmaskcore_arm64.aar and /dev/null differ diff --git a/lib-bitmask-core-armv7/bitmaskcore_arm-sources.jar b/lib-bitmask-core-armv7/bitmaskcore_arm-sources.jar deleted file mode 100644 index 043de8ec..00000000 Binary files a/lib-bitmask-core-armv7/bitmaskcore_arm-sources.jar and /dev/null differ diff --git a/lib-bitmask-core-armv7/bitmaskcore_arm.aar b/lib-bitmask-core-armv7/bitmaskcore_arm.aar deleted file mode 100644 index fcdde062..00000000 Binary files a/lib-bitmask-core-armv7/bitmaskcore_arm.aar and /dev/null differ diff --git a/lib-bitmask-core-web/bitmaskcore_web-sources.jar b/lib-bitmask-core-web/bitmaskcore_web-sources.jar deleted file mode 100644 index 9d485a32..00000000 Binary files a/lib-bitmask-core-web/bitmaskcore_web-sources.jar and /dev/null differ diff --git a/lib-bitmask-core-web/bitmaskcore_web.aar b/lib-bitmask-core-web/bitmaskcore_web.aar deleted file mode 100644 index 8e0b5472..00000000 Binary files a/lib-bitmask-core-web/bitmaskcore_web.aar and /dev/null differ diff --git a/lib-bitmask-core-x86/bitmaskcore_x86-sources.jar b/lib-bitmask-core-x86/bitmaskcore_x86-sources.jar deleted file mode 100644 index 043de8ec..00000000 Binary files a/lib-bitmask-core-x86/bitmaskcore_x86-sources.jar and /dev/null differ diff --git a/lib-bitmask-core-x86/bitmaskcore_x86.aar b/lib-bitmask-core-x86/bitmaskcore_x86.aar deleted file mode 100644 index d7d00a63..00000000 Binary files a/lib-bitmask-core-x86/bitmaskcore_x86.aar and /dev/null differ diff --git a/lib-bitmask-core-x86_64/bitmaskcore_x86_64-sources.jar b/lib-bitmask-core-x86_64/bitmaskcore_x86_64-sources.jar deleted file mode 100644 index 043de8ec..00000000 Binary files a/lib-bitmask-core-x86_64/bitmaskcore_x86_64-sources.jar and /dev/null differ diff --git a/lib-bitmask-core-x86_64/bitmaskcore_x86_64.aar b/lib-bitmask-core-x86_64/bitmaskcore_x86_64.aar deleted file mode 100644 index 4bd349fe..00000000 Binary files a/lib-bitmask-core-x86_64/bitmaskcore_x86_64.aar and /dev/null differ diff --git a/lib-bitmask-core/bitmaskcore-sources.jar b/lib-bitmask-core/bitmaskcore-sources.jar deleted file mode 100644 index 043de8ec..00000000 Binary files a/lib-bitmask-core/bitmaskcore-sources.jar and /dev/null differ diff --git a/lib-bitmask-core/bitmaskcore.aar b/lib-bitmask-core/bitmaskcore.aar deleted file mode 100644 index 6f7c6c40..00000000 Binary files a/lib-bitmask-core/bitmaskcore.aar and /dev/null differ -- cgit v1.2.3 From 5217b70a52b6eed02b4ea73a702831afd0fe1711 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 15 Jul 2022 23:53:23 +0200 Subject: build go dependencies before running tests on the CI --- .gitlab-ci.yml | 1 + scripts/build_deps.sh | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5cc25a02..2577060e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -55,6 +55,7 @@ unit_test: image: "0xacab.org:4567/leap/bitmask_android/android-ndk:latest" stage: test script: + - BUILD_TOR=false BUILD_OPENVPN_LIBS=false ./scripts/build_deps.sh - ./gradlew testCustomProductionFatReleaseUnitTest testNormalProductionFatReleaseUnitTest artifacts: paths: diff --git a/scripts/build_deps.sh b/scripts/build_deps.sh index 83fed5e8..14d2bafc 100755 --- a/scripts/build_deps.sh +++ b/scripts/build_deps.sh @@ -15,7 +15,8 @@ DIR_GOLIBS=./bitmaskcore/lib/ DIR_TORLIBS=./tor-android/external/lib EXPECTED_NDK_VERSION="21.4.7075529" EXPECTED_ANDROID_NDK_RELEASE_VERSION="r21e" -BUILD_TOR=true +if [[ -z $BUILD_TOR ]]; then BUILD_TOR=true; fi +if [[ -z $BUILD_OPENVPN_LIBS ]]; then BUILD_OPENVPN_LIBS=true; fi # init # look for empty dir @@ -60,8 +61,9 @@ else fi # build openvpn libs -if [[ $(ls -A ${DIR_OVPNASSETS}) && $(ls -A ${DIR_OVPNLIBS}) ]] -then +if [[ ${BUILD_OPENVPN_LIBS} == false ]]; then + echo "skipping openvpn" +elif [[ $(ls -A ${DIR_OVPNASSETS}) && $(ls -A ${DIR_OVPNLIBS}) ]]; then echo "Dirty build: skipped externalNativeBuild - reusing existing libs" else echo "Clean build: starting externalNativeBuild" -- cgit v1.2.3 From 71ee3eaea9bb3ff197ec36bc3684f2db33f7944c Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sat, 16 Jul 2022 11:14:37 +0200 Subject: better naming for network error handling flag in ObfsVpnClient --- .../se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java index 76e361d7..f6c8837e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java @@ -20,7 +20,7 @@ public class ObfsVpnClient implements Observer, client.EventLogger { private static final String TAG = ObfsVpnClient.class.getSimpleName(); private volatile boolean noNetwork; - private final AtomicBoolean isErrorHandling = new AtomicBoolean(false); + private final AtomicBoolean pendingNetworkErrorHandling = new AtomicBoolean(false); private final AtomicInteger reconnectRetry = new AtomicInteger(0); private static final int MAX_RETRY = 5; @@ -72,7 +72,7 @@ public class ObfsVpnClient implements Observer, client.EventLogger { VpnStatus.logDebug("[obfsvpn] reconnecting on different port... " + SOCKS_PORT.get()); startSync(); } else if (noNetwork) { - isErrorHandling.set(true); + pendingNetworkErrorHandling.set(true); } } } @@ -89,7 +89,7 @@ public class ObfsVpnClient implements Observer, client.EventLogger { e.printStackTrace(); VpnStatus.logError("[obfsvpn] " + e.getLocalizedMessage()); } - isErrorHandling.set(false); + pendingNetworkErrorHandling.set(false); Log.d(TAG, "stopping obfsVpnClient releasing LOCK ..."); } } @@ -106,7 +106,7 @@ public class ObfsVpnClient implements Observer, client.EventLogger { noNetwork = true; } else { noNetwork = false; - if (isErrorHandling.getAndSet(false)) { + if (pendingNetworkErrorHandling.getAndSet(false)) { stop(); start(); } -- cgit v1.2.3 From fd7e5b398091ac2f110e44a2c4a594ffe721e80d Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sun, 17 Jul 2022 10:22:43 +0200 Subject: remove outdated golibs before rebuilding them and running test on CI --- .gitlab-ci.yml | 2 +- scripts/prepareForTests.sh | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100755 scripts/prepareForTests.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2577060e..286e6d45 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -55,7 +55,7 @@ unit_test: image: "0xacab.org:4567/leap/bitmask_android/android-ndk:latest" stage: test script: - - BUILD_TOR=false BUILD_OPENVPN_LIBS=false ./scripts/build_deps.sh + - ./scripts/prepareForTests.sh - ./gradlew testCustomProductionFatReleaseUnitTest testNormalProductionFatReleaseUnitTest artifacts: paths: diff --git a/scripts/prepareForTests.sh b/scripts/prepareForTests.sh new file mode 100755 index 00000000..d10a04b7 --- /dev/null +++ b/scripts/prepareForTests.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Copyright (c) 2022 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 . + +SCRIPT_DIR=$(dirname "$0") +BASE_DIR="$SCRIPT_DIR/.." + +git checkout -- \* +git checkout -- \.\* +rm -r $BASE_DIR/bitmaskcore/lib/* +git submodule foreach --recursive git reset --hard HEAD +git submodule sync --recursive +git submodule update --init --recursive + +BUILD_TOR=false BUILD_OPENVPN_LIBS=false ./scripts/build_deps.sh \ No newline at end of file -- cgit v1.2.3 From 4a95fbad79333bc1cc83b22c8122293a3d8d332f Mon Sep 17 00:00:00 2001 From: cyBerta Date: Tue, 19 Jul 2022 13:17:02 +0200 Subject: fix tests --- .../bitmaskclient/eip/VpnConfigGeneratorTest.java | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) 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 731ff1c8..f0db65d9 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java @@ -520,7 +520,7 @@ public class VpnConfigGeneratorTest { "K2ZoknT+Nno5jgjFuUR3fZseNizEfx7BteooKQ==\n" + "-----END CERTIFICATE-----\n" + "\n" + - "crl-verify file missing in config profile\n" + + "# crl-verify file missing in config profile\n" + "route 37.218.247.60 255.255.255.255 net_gateway\n"+ "remote-cert-tls server\n" + "data-ciphers AES-128-CBC\n" + @@ -1407,6 +1407,8 @@ public class VpnConfigGeneratorTest { "persist-tun\n" + "# persist-tun also enables pre resolving to avoid DNS resolve problem\n" + "preresolve\n" + + "# Use system proxy setting\n" + + "management-query-proxy\n" + "# Custom configuration options\n" + "# You are on your on own here :)\n" + "# These options found in the config file do not map to config settings:\n" + @@ -1438,7 +1440,7 @@ public class VpnConfigGeneratorTest { vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 1, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertFalse(vpnProfiles.containsKey(OBFS4)); - assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v1_tcp_udp.trim())); + assertEquals(expectedVPNConfig_v1_tcp_udp.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); } @Test @@ -1447,7 +1449,7 @@ public class VpnConfigGeneratorTest { vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 1, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertFalse(vpnProfiles.containsKey(OBFS4)); - assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v1_udp_tcp.trim())); + assertEquals(expectedVPNConfig_v1_udp_tcp.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); } @Test @@ -1456,7 +1458,7 @@ public class VpnConfigGeneratorTest { vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 2, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertFalse(vpnProfiles.containsKey(OBFS4)); - assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v1_tcp_udp.trim())); + assertEquals(expectedVPNConfig_v1_tcp_udp.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); } @Test @@ -1465,7 +1467,7 @@ public class VpnConfigGeneratorTest { vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 2, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); assertFalse(vpnProfiles.containsKey(OBFS4)); - assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v1_udp_tcp.trim())); + assertEquals(expectedVPNConfig_v1_udp_tcp.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); } @@ -1478,7 +1480,7 @@ public class VpnConfigGeneratorTest { assertTrue(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.containsKey(OPENVPN)); System.out.println(vpnProfiles.get(OBFS4).getConfigFile(context, false)); - assertTrue(vpnProfiles.get(OBFS4).getConfigFile(context, false).trim().equals(expectedVPNConfig_v3_obfs4.trim())); + assertEquals(expectedVPNConfig_v3_obfs4.trim(), vpnProfiles.get(OBFS4).getConfigFile(context, false).trim()); } @Test @@ -1490,7 +1492,7 @@ public class VpnConfigGeneratorTest { assertTrue(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.containsKey(OPENVPN)); System.out.println(vpnProfiles.get(OBFS4).getConfigFile(context, false)); - assertTrue(vpnProfiles.get(OBFS4).getConfigFile(context, false).trim().equals(expectedVPNConfig_v3_obfsvpn_obfs4.trim())); + assertEquals(expectedVPNConfig_v3_obfsvpn_obfs4.trim(), vpnProfiles.get(OBFS4).getConfigFile(context, false).trim()); } @Test @@ -1501,7 +1503,7 @@ public class VpnConfigGeneratorTest { assertTrue(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.containsKey(OPENVPN)); System.out.println(vpnProfiles.get(OPENVPN).getConfigFile(context, false)); - assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v3_ovpn_tcp_udp.trim())); + assertEquals(expectedVPNConfig_v3_ovpn_tcp_udp.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); } @Test @@ -1512,7 +1514,7 @@ public class VpnConfigGeneratorTest { assertTrue(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.containsKey(OPENVPN)); System.out.println(vpnProfiles.get(OPENVPN).getConfigFile(context, false)); - assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v3_ovpn_udp_tcp.trim())); + assertEquals(expectedVPNConfig_v3_ovpn_udp_tcp.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); } @Test @@ -1525,7 +1527,7 @@ public class VpnConfigGeneratorTest { assertTrue(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.containsKey(OPENVPN)); System.out.println(vpnProfiles.get(OPENVPN).getConfigFile(context, false)); - assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v3_ovpn_udp_tcp_defaultDataCiphers.trim())); + assertEquals(expectedVPNConfig_v3_ovpn_udp_tcp_defaultDataCiphers.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); } @Test @@ -1537,7 +1539,7 @@ public class VpnConfigGeneratorTest { assertTrue(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.containsKey(OPENVPN)); System.out.println(vpnProfiles.get(OPENVPN).getConfigFile(context, false)); - assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v4_ovpn_tcp_udp.trim())); + assertEquals(expectedVPNConfig_v4_ovpn_tcp_udp.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); } @Test @@ -1549,8 +1551,7 @@ public class VpnConfigGeneratorTest { assertTrue(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.containsKey(OPENVPN)); System.out.println(vpnProfiles.get(OPENVPN).getConfigFile(context, false)); - System.out.println(expectedVPNConfig_v4_ovpn_udp_tcp.trim()); - assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v4_ovpn_udp_tcp.trim())); + assertEquals(expectedVPNConfig_v4_ovpn_udp_tcp.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); } @Test @@ -1620,8 +1621,7 @@ public class VpnConfigGeneratorTest { assertTrue(vpnProfiles.containsKey(OBFS4)); assertTrue(vpnProfiles.containsKey(OPENVPN)); System.out.println(vpnProfiles.get(OPENVPN).getConfigFile(context, false)); - System.out.println(expectedVPNConfig_v4_ovpn_multiport_tcpudp.trim()); - assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v4_ovpn_multiport_tcpudp.trim())); + assertEquals(expectedVPNConfig_v4_ovpn_multiport_tcpudp.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); } @Test @@ -1631,7 +1631,7 @@ public class VpnConfigGeneratorTest { vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, gateway, 4, false, false); HashMap vpnProfiles = vpnConfigGenerator.generateVpnProfiles(); System.out.println(vpnProfiles.get(OPENVPN).getConfigFile(context, false)); - assertTrue(vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim().equals(expectedVPNConfig_v4_ovpn_tcp_udp_new_ciphers.trim())); + assertEquals(expectedVPNConfig_v4_ovpn_tcp_udp_new_ciphers.trim(), vpnProfiles.get(OPENVPN).getConfigFile(context, false).trim()); } public void testGenerateVpnProfileExperimentalTransportsEnabled () throws Exception { -- cgit v1.2.3