summaryrefslogtreecommitdiff
path: root/app/src/main/java/se/leap/bitmaskclient/pluggableTransports
diff options
context:
space:
mode:
authorcyBerta <cyberta@riseup.net>2023-04-06 01:08:05 +0200
committercyBerta <cyberta@riseup.net>2023-04-13 16:47:13 +0200
commit939901a89abb169648423473056260335d3af639 (patch)
tree7e49ac928013cdf5e7979c3a9384fb06f0b0f192 /app/src/main/java/se/leap/bitmaskclient/pluggableTransports
parentf6017ab12d0c472ab4f22e81d9a768ad2510b134 (diff)
first pass on obfs4-hop pt integration
Diffstat (limited to 'app/src/main/java/se/leap/bitmaskclient/pluggableTransports')
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingConfig.java49
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingObfsVpnClient.java72
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java21
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java25
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientBuilder.java18
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientInterface.java9
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java5
7 files changed, 179 insertions, 20 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingConfig.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingConfig.java
new file mode 100644
index 00000000..e885166a
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingConfig.java
@@ -0,0 +1,49 @@
+package se.leap.bitmaskclient.pluggableTransports;
+
+import androidx.annotation.NonNull;
+
+import com.google.gson.FieldNamingPolicy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+import se.leap.bitmaskclient.base.models.Transport;
+
+public class HoppingConfig {
+ final boolean kcp;
+ final String proxyAddr;
+ final String[] remotes;
+ final String[] certs;
+ final int portSeed;
+ final int portCount;
+ final int minHopSeconds;
+ final int hopJitter;
+
+ public HoppingConfig(boolean kcp,
+ String proxyAddr,
+ Transport transport,
+ int minHopSeconds,
+ int hopJitter) {
+ this.kcp = kcp;
+ this.proxyAddr = proxyAddr;
+ Transport.Endpoint[] endpoints = transport.getOptions().getEndpoints();
+ this.remotes = new String[endpoints.length];
+ this.certs = new String[endpoints.length];
+ for (int i = 0; i < remotes.length; i++) {
+ remotes[i] = endpoints[i].getIp();
+ certs[i] = endpoints[i].getCert();
+ }
+ this.portSeed = transport.getOptions().getPortSeed();
+ this.portCount = transport.getOptions().getPortCount();
+ this.minHopSeconds = minHopSeconds;
+ this.hopJitter = hopJitter;
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ Gson gson = new GsonBuilder()
+ .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
+ .create();
+ return gson.toJson(this);
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingObfsVpnClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingObfsVpnClient.java
new file mode 100644
index 00000000..1b19213f
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/HoppingObfsVpnClient.java
@@ -0,0 +1,72 @@
+package se.leap.bitmaskclient.pluggableTransports;
+
+import static de.blinkt.openvpn.core.connection.Connection.TransportProtocol.KCP;
+
+import client.Client;
+import client.HopClient;
+import de.blinkt.openvpn.core.VpnStatus;
+import se.leap.bitmaskclient.base.models.Constants;
+
+public class HoppingObfsVpnClient implements PtClientInterface {
+
+ public static final int PORT = 8080;
+ public static final String IP = "127.0.0.1";
+
+ public final HopClient client;
+
+ public HoppingObfsVpnClient(Obfs4Options options) throws IllegalStateException {
+
+ //FIXME: use a different strategy here
+ //Basically we would want to track if the more performant transport protocol (KCP?/TCP?) usage was successful
+ //if so, we stick to it, otherwise we flip the flag
+ boolean kcp = Constants.KCP.equals(options.transport.getProtocols()[0]);
+
+ if (options.transport.getOptions().getEndpoints() == null) {
+ throw new IllegalStateException("No Endpoints for hopping pt detected!");
+ }
+
+ HoppingConfig hoppingConfig = new HoppingConfig(kcp,IP+":"+PORT, options.transport, 10, 10);
+ try {
+ client = Client.newFFIHopClient(hoppingConfig.toString());
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public int start() {
+ try {
+ client.setEventLogger(this);
+ return client.start() ? PORT : 0;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return 0;
+ }
+ }
+
+ @Override
+ public void stop() {
+ try {
+ client.stop();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ client.setEventLogger(null);
+ }
+ }
+
+ @Override
+ public boolean isStarted() {
+ return client.isStarted();
+ }
+
+ @Override
+ public void error(String s) {
+ VpnStatus.logError("[hopping-obfs4] " + s);
+ }
+
+ @Override
+ public void log(String state, String message) {
+ VpnStatus.logDebug("[hopping-obfs4] " + state + ": " + message);
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java
index b96f88ca..0dd81eb8 100644
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Obfs4Options.java
@@ -2,20 +2,15 @@ package se.leap.bitmaskclient.pluggableTransports;
import java.io.Serializable;
+import se.leap.bitmaskclient.base.models.Transport;
+
public class Obfs4Options implements Serializable {
- public String cert;
- 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 String gatewayIP;
+ public Transport transport;
- 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;
+ public Obfs4Options(String gatewayIP,
+ Transport transport) {
+ this.gatewayIP = gatewayIP;
+ this.transport = transport;
}
-
}
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 f6c8837e..9d5ddcf9 100644
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java
@@ -1,5 +1,7 @@
package se.leap.bitmaskclient.pluggableTransports;
+import static se.leap.bitmaskclient.base.models.Constants.KCP;
+
import android.util.Log;
import java.util.Observable;
@@ -7,12 +9,12 @@ import java.util.Observer;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
-import client.Client_;
+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, client.EventLogger {
+public class ObfsVpnClient implements Observer, PtClientInterface {
public static final AtomicInteger SOCKS_PORT = new AtomicInteger(4430);
public static final String SOCKS_IP = "127.0.0.1";
@@ -27,9 +29,17 @@ public class ObfsVpnClient implements Observer, client.EventLogger {
private final client.Client_ obfsVpnClient;
private final Object LOCK = new Object();
- public ObfsVpnClient(Obfs4Options options) {
- obfsVpnClient = new Client_(options.udp, SOCKS_IP+":"+SOCKS_PORT.get(), options.cert);
- obfsVpnClient.setEventLogger(this);
+ public ObfsVpnClient(Obfs4Options options) throws IllegalStateException{
+ //FIXME: use a different strategy here
+ //Basically we would want to track if the more performant transport protocol (KCP?/TCP?) usage was successful
+ //if so, we stick to it, otherwise we flip the flag
+ boolean kcp = KCP.equals(options.transport.getProtocols()[0]);
+
+ if (options.transport.getOptions().getCert() == null) {
+ throw new IllegalStateException("No cert found to establish a obfs4 connection");
+ }
+
+ obfsVpnClient = Client.newClient(kcp, SOCKS_IP+":"+SOCKS_PORT.get(), options.transport.getOptions().getCert());
}
/**
@@ -38,6 +48,7 @@ public class ObfsVpnClient implements Observer, client.EventLogger {
*/
public int start() {
synchronized (LOCK) {
+ obfsVpnClient.setEventLogger(this);
Log.d(TAG, "aquired LOCK");
new Thread(this::startSync).start();
waitUntilStarted();
@@ -46,6 +57,7 @@ public class ObfsVpnClient implements Observer, client.EventLogger {
return SOCKS_PORT.get();
}
+ // We're waiting here until the obfsvpn client has found a unbound port and started
private void waitUntilStarted() {
int count = -1;
try {
@@ -88,6 +100,8 @@ public class ObfsVpnClient implements Observer, client.EventLogger {
} catch (Exception e) {
e.printStackTrace();
VpnStatus.logError("[obfsvpn] " + e.getLocalizedMessage());
+ } finally {
+ obfsVpnClient.setEventLogger(null);
}
pendingNetworkErrorHandling.set(false);
Log.d(TAG, "stopping obfsVpnClient releasing LOCK ...");
@@ -98,6 +112,7 @@ public class ObfsVpnClient implements Observer, client.EventLogger {
return obfsVpnClient.isStarted();
}
+ // TODO: register observer!
@Override
public void update(Observable observable, Object arg) {
if (observable instanceof EipStatus) {
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientBuilder.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientBuilder.java
new file mode 100644
index 00000000..945e3d7a
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientBuilder.java
@@ -0,0 +1,18 @@
+package se.leap.bitmaskclient.pluggableTransports;
+
+import de.blinkt.openvpn.core.connection.Connection;
+import de.blinkt.openvpn.core.connection.Obfs4Connection;
+import de.blinkt.openvpn.core.connection.Obfs4HopConnection;
+
+public class PtClientBuilder {
+ public static PtClientInterface getPtClient(Connection connection) throws IllegalStateException {
+ switch (connection.getTransportType()) {
+ case OBFS4:
+ return new ObfsVpnClient(((Obfs4Connection) connection).getObfs4Options());
+ case OBFS4_HOP:
+ return new HoppingObfsVpnClient(((Obfs4HopConnection) connection).getObfs4Options());
+ default:
+ throw new IllegalStateException("Unexpected pluggable transport " + connection.getTransportType());
+ }
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientInterface.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientInterface.java
new file mode 100644
index 00000000..28d19a97
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/PtClientInterface.java
@@ -0,0 +1,9 @@
+package se.leap.bitmaskclient.pluggableTransports;
+
+import client.EventLogger;
+
+public interface PtClientInterface extends EventLogger {
+ int start();
+ void stop();
+ boolean isStarted();
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java
index f1eb0f1b..102dcf35 100644
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java
@@ -42,6 +42,7 @@ public class ShapeshifterClient implements Observer {
private int retry = 0;
private final Handler reconnectHandler;
+ @Deprecated
public class ShapeshifterLogger implements shapeshifter.Logger {
@Override
public void log(String s) {
@@ -71,8 +72,8 @@ public class ShapeshifterClient implements Observer {
private void setup(Obfs4Options options) {
shapeShifter.setSocksAddr(DISPATCHER_IP+":"+DISPATCHER_PORT);
- shapeShifter.setTarget(options.remoteIP+":"+options.remotePort);
- shapeShifter.setCert(options.cert);
+ shapeShifter.setTarget(options.gatewayIP +":"+options.transport.getPorts()[0]);
+ shapeShifter.setCert(options.transport.getOptions().getCert());
}
public void setOptions(Obfs4Options options) {