From f6017ab12d0c472ab4f22e81d9a768ad2510b134 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 31 Mar 2023 15:46:09 +0200 Subject: don't handle obfs4 over kcp as a separate pluggable transport, instead 'tcp' and 'kcp' become valid protocols for obfs4 --- .../main/java/de/blinkt/openvpn/VpnProfile.java | 25 ++++++++-------------- .../blinkt/openvpn/core/connection/Connection.java | 21 +++++++++++++++--- 2 files changed, 27 insertions(+), 19 deletions(-) (limited to 'app/src/main/java/de') diff --git a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java index 83cde85e..3428e0c4 100644 --- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java +++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java @@ -5,6 +5,11 @@ package de.blinkt.openvpn; +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.PROVIDER_PROFILE; +import static se.leap.bitmaskclient.base.utils.ConfigHelper.stringEqual; + import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; @@ -34,8 +39,6 @@ import java.io.FileWriter; import java.io.IOException; import java.io.Serializable; import java.io.StringWriter; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; @@ -69,12 +72,6 @@ import de.blinkt.openvpn.core.connection.ConnectionAdapter; 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; - public class VpnProfile implements Serializable, Cloneable { // Note that this class cannot be moved to core where it belongs since // the profile loading depends on it being here @@ -184,6 +181,7 @@ public class VpnProfile implements Serializable, Cloneable { /* Options no longer used in new profiles */ public String mServerName = "openvpn.example.com"; public String mServerPort = "1194"; + @Deprecated public boolean mUseUdp = true; public boolean mTemporaryProfile = false; private transient PrivateKey mPrivateKey; @@ -193,8 +191,7 @@ public class VpnProfile implements Serializable, Cloneable { private int mProfileVersion; public boolean mBlockUnusedAddressFamilies = true; public String mGatewayIp; - private boolean mUseObfs4; - private boolean mUseObfs4Kcp; + private final boolean mUseObfs4; public VpnProfile(String name, Connection.TransportType transportType) { mUuid = UUID.randomUUID(); @@ -204,7 +201,6 @@ public class VpnProfile implements Serializable, Cloneable { mConnections = new Connection[1]; mLastUsed = System.currentTimeMillis(); mUseObfs4 = transportType == OBFS4; - mUseObfs4Kcp = transportType == OBFS4_KCP; } public static String openVpnEscape(String unescaped) { @@ -270,8 +266,7 @@ public class VpnProfile implements Serializable, Cloneable { if (obj instanceof VpnProfile) { VpnProfile vp = (VpnProfile) obj; return stringEqual(vp.mGatewayIp, mGatewayIp) && - vp.mUseObfs4 == mUseObfs4 && - vp.mUseObfs4Kcp == mUseObfs4Kcp; + vp.mUseObfs4 == mUseObfs4; } return false; } @@ -302,14 +297,12 @@ public class VpnProfile implements Serializable, Cloneable { } public boolean usePluggableTransports() { - return mUseObfs4Kcp || mUseObfs4; + return mUseObfs4; } public Connection.TransportType getTransportType() { if (mUseObfs4) { return OBFS4; - } else if (mUseObfs4Kcp) { - return OBFS4_KCP; } else { return OPENVPN; } 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 f60e7333..137b3f16 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 @@ -37,10 +37,25 @@ public abstract class Connection implements Serializable, Cloneable { ORBOT } + public enum TransportProtocol { + UDP("udp"), + TCP("tcp"), + KCP("kcp"); + + String protocol; + + TransportProtocol(String transportProtocol) { + this.protocol = transportProtocol; + } + + @Override + public String toString() { + return protocol; + } + } public enum TransportType { OBFS4("obfs4"), OPENVPN("openvpn"), - OBFS4_KCP("obfs4-1"), PT("metaTransport"); @@ -56,11 +71,11 @@ public abstract class Connection implements Serializable, Cloneable { } public boolean isPluggableTransport() { - return this == OBFS4 || this == OBFS4_KCP || this == PT; + return this == OBFS4 || this == PT; } public TransportType getMetaType() { - if (this == OBFS4 || this == OBFS4_KCP || this == PT) { + if (this == OBFS4 || this == PT) { return PT; } return OPENVPN; -- cgit v1.2.3 From 939901a89abb169648423473056260335d3af639 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 6 Apr 2023 01:08:05 +0200 Subject: first pass on obfs4-hop pt integration --- .../main/java/de/blinkt/openvpn/VpnProfile.java | 17 +++---- .../java/de/blinkt/openvpn/core/ConfigParser.java | 20 +++++++- .../de/blinkt/openvpn/core/OpenVPNService.java | 20 ++++---- .../blinkt/openvpn/core/connection/Connection.java | 56 ++++++++++++++++++++-- .../openvpn/core/connection/Obfs4Connection.java | 6 +-- .../core/connection/Obfs4HopConnection.java | 48 +++++++++++++++++++ 6 files changed, 137 insertions(+), 30 deletions(-) create mode 100644 app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4HopConnection.java (limited to 'app/src/main/java/de') diff --git a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java index 3428e0c4..9baac195 100644 --- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java +++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java @@ -5,8 +5,6 @@ package de.blinkt.openvpn; -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.PROVIDER_PROFILE; import static se.leap.bitmaskclient.base.utils.ConfigHelper.stringEqual; @@ -191,7 +189,7 @@ public class VpnProfile implements Serializable, Cloneable { private int mProfileVersion; public boolean mBlockUnusedAddressFamilies = true; public String mGatewayIp; - private final boolean mUseObfs4; + private final int mTransportType; public VpnProfile(String name, Connection.TransportType transportType) { mUuid = UUID.randomUUID(); @@ -200,7 +198,7 @@ public class VpnProfile implements Serializable, Cloneable { mConnections = new Connection[1]; mLastUsed = System.currentTimeMillis(); - mUseObfs4 = transportType == OBFS4; + mTransportType = transportType.toInt(); } public static String openVpnEscape(String unescaped) { @@ -266,7 +264,7 @@ public class VpnProfile implements Serializable, Cloneable { if (obj instanceof VpnProfile) { VpnProfile vp = (VpnProfile) obj; return stringEqual(vp.mGatewayIp, mGatewayIp) && - vp.mUseObfs4 == mUseObfs4; + vp.mTransportType == mTransportType; } return false; } @@ -297,15 +295,12 @@ public class VpnProfile implements Serializable, Cloneable { } public boolean usePluggableTransports() { - return mUseObfs4; + Connection.TransportType type = Connection.TransportType.fromInt(mTransportType); + return type != null && type.isPluggableTransport(); } public Connection.TransportType getTransportType() { - if (mUseObfs4) { - return OBFS4; - } else { - return OPENVPN; - } + return Connection.TransportType.fromInt(mTransportType); } public String getName() { diff --git a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java index 6063ea53..e8d333e3 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java +++ b/app/src/main/java/de/blinkt/openvpn/core/ConfigParser.java @@ -27,6 +27,7 @@ import java.util.Vector; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.connection.Connection; import de.blinkt.openvpn.core.connection.Obfs4Connection; +import de.blinkt.openvpn.core.connection.Obfs4HopConnection; import de.blinkt.openvpn.core.connection.OpenvpnConnection; import se.leap.bitmaskclient.pluggableTransports.Obfs4Options; @@ -807,8 +808,23 @@ public class ConfigParser { e.printStackTrace(); return null; } - else - conn = transportType.getMetaType() == PT ? new Obfs4Connection(obfs4Options) : new OpenvpnConnection(); + else { + switch (transportType) { + case OBFS4: + conn = new Obfs4Connection(obfs4Options); + break; + case OBFS4_HOP: + conn = new Obfs4HopConnection(obfs4Options); + break; + case OPENVPN: + conn = new OpenvpnConnection(); + break; + default: + throw new ConfigParseError("Unexpected transport type: " + transportType); + + } + + } Vector port = getOption("port", 1, 1); if (port != null) { 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 0ae7639e..6adffda1 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -12,7 +12,6 @@ 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; import android.content.Intent; import android.content.IntentFilter; @@ -41,7 +40,6 @@ import java.net.Inet6Address; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Collection; -import java.util.Locale; import java.util.Vector; import de.blinkt.openvpn.VpnProfile; @@ -53,7 +51,8 @@ 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.PtClientBuilder; +import se.leap.bitmaskclient.pluggableTransports.PtClientInterface; import se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient; @@ -91,7 +90,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac private Runnable mOpenVPNThread; private VpnNotificationManager notificationManager; private ShapeshifterClient shapeshifter; - private ObfsVpnClient obfsVpnClient; + private PtClientInterface obfsVpnClient; private FirewallManager firewallManager; private final IBinder mBinder = new IOpenVPNServiceInternal.Stub() { @@ -415,18 +414,19 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac stopOldOpenVPNProcess(); // An old running VPN should now be exited mStarting = false; - - if (mProfile.usePluggableTransports() && connection instanceof Obfs4Connection) { - Obfs4Connection obfs4Connection = (Obfs4Connection) connection; + Connection.TransportType transportType = connection.getTransportType(); + if (mProfile.usePluggableTransports() && transportType.isPluggableTransport()) { if (useObfsVpn()) { if (obfsVpnClient != null && obfsVpnClient.isStarted()) { obfsVpnClient.stop(); } - obfsVpnClient = new ObfsVpnClient(obfs4Connection.getDispatcherOptions()); + obfsVpnClient = PtClientBuilder.getPtClient(connection); int runningSocksPort = obfsVpnClient.start(); - connection.setProxyPort(String.valueOf(runningSocksPort)); + if (connection.getTransportType() == Connection.TransportType.OBFS4) { + connection.setProxyPort(String.valueOf(runningSocksPort)); + } } else if (shapeshifter == null) { - shapeshifter = new ShapeshifterClient(obfs4Connection.getDispatcherOptions()); + shapeshifter = new ShapeshifterClient(((Obfs4Connection) connection).getObfs4Options()); shapeshifter.start(); } } 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 137b3f16..6dc78a30 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 @@ -5,6 +5,8 @@ package de.blinkt.openvpn.core.connection; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.*; + import android.text.TextUtils; import com.google.gson.annotations.JsonAdapter; @@ -42,7 +44,7 @@ public abstract class Connection implements Serializable, Cloneable { TCP("tcp"), KCP("kcp"); - String protocol; + final String protocol; TransportProtocol(String transportProtocol) { this.protocol = transportProtocol; @@ -55,11 +57,12 @@ public abstract class Connection implements Serializable, Cloneable { } public enum TransportType { OBFS4("obfs4"), + OBFS4_HOP("obfs4Hop"), OPENVPN("openvpn"), PT("metaTransport"); - String transport; + final String transport; TransportType(String transportType) { this.transport = transportType; @@ -70,12 +73,57 @@ public abstract class Connection implements Serializable, Cloneable { return transport; } + public int toInt() { + switch (this) { + case PT: + return 0; + case OPENVPN: + return 1; + case OBFS4: + return 2; + case OBFS4_HOP: + return 3; + default: + return -1; + } + } + + public static TransportType fromString(String value) { + switch (value) { + case "obfs4": + return OBFS4; + case "obfs4-hop": + return OBFS4_HOP; + case "metaTransport": + return PT; + case "openvpn": + return OPENVPN; + default: + throw new IllegalArgumentException(value + " is not a valid value for TransportType."); + } + } + + public static TransportType fromInt(int value) { + switch (value) { + case 0: + return PT; + case 1: + return OPENVPN; + case 2: + return OBFS4; + case 3: + return OBFS4_HOP; + default: + return null; + } + } + public boolean isPluggableTransport() { - return this == OBFS4 || this == PT; + return this == OBFS4 || this == OBFS4_HOP || this == PT; } public TransportType getMetaType() { - if (this == OBFS4 || this == PT) { + if (this == OBFS4 || this == OBFS4_HOP || this == PT) { return PT; } return OPENVPN; 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 c77c23fd..73bfccdc 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,8 +19,8 @@ public class Obfs4Connection extends Connection { public Obfs4Connection(Obfs4Options options) { if (useObfsVpn()) { - setServerName(options.remoteIP); - setServerPort(options.remotePort); + setServerName(options.gatewayIP); + setServerPort(options.transport.getPorts()[0]); setProxyName(ObfsVpnClient.SOCKS_IP); setProxyPort(String.valueOf(ObfsVpnClient.SOCKS_PORT.get())); setProxyType(ProxyType.SOCKS5); @@ -53,7 +53,7 @@ public class Obfs4Connection extends Connection { } - public Obfs4Options getDispatcherOptions() { + public Obfs4Options getObfs4Options() { return options; } diff --git a/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4HopConnection.java b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4HopConnection.java new file mode 100644 index 00000000..f983ae20 --- /dev/null +++ b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4HopConnection.java @@ -0,0 +1,48 @@ +package de.blinkt.openvpn.core.connection; + +import se.leap.bitmaskclient.pluggableTransports.HoppingObfsVpnClient; +import se.leap.bitmaskclient.pluggableTransports.Obfs4Options; + + +/** + * Created by cyberta on 08.03.19. + */ + +public class Obfs4HopConnection extends Connection { + + private static final String TAG = Obfs4HopConnection.class.getName(); + private Obfs4Options options; + + public Obfs4HopConnection(Obfs4Options options) { + setServerName(HoppingObfsVpnClient.IP); + setServerPort(String.valueOf(HoppingObfsVpnClient.PORT)); + setProxyName(""); + setProxyPort(""); + setProxyType(ProxyType.NONE); + + + setUseUdp(true); + setProxyAuthUser(null); + setProxyAuthPassword(null); + setUseProxyAuth(false); + this.options = options; + } + + @Override + public Connection clone() throws CloneNotSupportedException { + Obfs4HopConnection connection = (Obfs4HopConnection) super.clone(); + connection.options = this.options; + return connection; + } + + @Override + public TransportType getTransportType() { + return TransportType.OBFS4_HOP; + } + + + public Obfs4Options getObfs4Options() { + return options; + } + +} -- cgit v1.2.3 From 6dd7821cd38c69b9fdc3172762744f32dcbf9606 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 13 Apr 2023 13:42:44 +0200 Subject: obfs4-hop enum value - improve handling of disallowed dashes in enums --- app/src/main/java/de/blinkt/openvpn/core/connection/Connection.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'app/src/main/java/de') 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 6dc78a30..0b28cbca 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 @@ -55,8 +55,11 @@ public abstract class Connection implements Serializable, Cloneable { return protocol; } } + + // !! Never use valueOf() to instantiate this enum, use fromString() !! public enum TransportType { OBFS4("obfs4"), + // dashes are not allowed in enums, so obfs4-hop becomes obfs4Hop -.- OBFS4_HOP("obfs4Hop"), OPENVPN("openvpn"), @@ -70,6 +73,9 @@ public abstract class Connection implements Serializable, Cloneable { @Override public String toString() { + if (this == OBFS4_HOP) { + return "obfs4-hop"; + } return transport; } -- cgit v1.2.3 From 2f32f3331b609d8a0324726f173e1aacf8854808 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 13 Apr 2023 13:44:47 +0200 Subject: set correct proxy port for obfs4-hop pt proxy --- .../openvpn/core/connection/Obfs4Connection.java | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'app/src/main/java/de') 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 73bfccdc..d152031a 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 @@ -4,6 +4,7 @@ import static se.leap.bitmaskclient.base.utils.ConfigHelper.ObfsVpnHelper.useObf import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_IP; import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_PORT; +import se.leap.bitmaskclient.pluggableTransports.HoppingObfsVpnClient; import se.leap.bitmaskclient.pluggableTransports.Obfs4Options; import se.leap.bitmaskclient.pluggableTransports.ObfsVpnClient; @@ -22,18 +23,29 @@ public class Obfs4Connection extends Connection { setServerName(options.gatewayIP); setServerPort(options.transport.getPorts()[0]); setProxyName(ObfsVpnClient.SOCKS_IP); - setProxyPort(String.valueOf(ObfsVpnClient.SOCKS_PORT.get())); setProxyType(ProxyType.SOCKS5); + switch (options.transport.getTransportType()) { + case OBFS4: + setUseUdp(false); + setProxyPort(String.valueOf(ObfsVpnClient.SOCKS_PORT.get())); + break; + case OBFS4_HOP: + setUseUdp(true); + setProxyPort(String.valueOf(HoppingObfsVpnClient.PORT)); + break; + default:break; + } } else { setServerName(DISPATCHER_IP); setServerPort(DISPATCHER_PORT); setProxyName(""); setProxyPort(""); setProxyType(ProxyType.NONE); + + // while udp/kcp might be used on the wire, + // we don't use udp for openvpn in case of a obfs4 connection + setUseUdp(false); } - // 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); -- cgit v1.2.3