diff options
Diffstat (limited to 'app/src')
11 files changed, 84 insertions, 18 deletions
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 9943faff..6cd86105 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 @@ -45,7 +45,8 @@ public abstract class Connection implements Serializable, Cloneable { public enum TransportProtocol { UDP("udp"), TCP("tcp"), - KCP("kcp"); + KCP("kcp"), + QUIC("quic"); final String protocol; diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/CensorshipCircumventionFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/CensorshipCircumventionFragment.java index e8789b32..fc561d48 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/CensorshipCircumventionFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/CensorshipCircumventionFragment.java @@ -3,6 +3,7 @@ package se.leap.bitmaskclient.base.fragments; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseObfs4; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseObfs4Kcp; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUsePortHopping; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseObfs4Quic; 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.resetSnowflakeSettings; @@ -37,6 +38,7 @@ public class CensorshipCircumventionFragment extends Fragment { public static int TUNNELING_AUTOMATICALLY = 100300000; public static int TUNNELING_OBFS4 = 100300001; public static int TUNNELING_OBFS4_KCP = 100300002; + public static int TUNNELING_QUIC = 100300003; private @NonNull FCensorshipCircumventionBinding binding; @@ -113,7 +115,7 @@ public class CensorshipCircumventionFragment extends Fragment { private void initTunneling() { RadioButton noneRadioButton = new RadioButton(binding.getRoot().getContext()); noneRadioButton.setText(getText(R.string.automatically_select)); - noneRadioButton.setChecked(!getUseObfs4() && !getUseObfs4Kcp()); + noneRadioButton.setChecked(!getUseObfs4() && !getUseObfs4Kcp() && !getUseObfs4Quic()); noneRadioButton.setId(TUNNELING_AUTOMATICALLY); binding.tunnelingRadioGroup.addView(noneRadioButton); @@ -133,6 +135,14 @@ public class CensorshipCircumventionFragment extends Fragment { binding.tunnelingRadioGroup.addView(obfs4KcpRadioButton); } + if (ProviderObservable.getInstance().getCurrentProvider().supportsObfs4Quic()) { + RadioButton obfs4QuicRadioButton = new RadioButton(binding.getRoot().getContext()); + obfs4QuicRadioButton.setText(getText(R.string.tunnelling_quic)); + obfs4QuicRadioButton.setId(TUNNELING_QUIC); + obfs4QuicRadioButton.setChecked(getUseObfs4Quic()); + binding.tunnelingRadioGroup.addView(obfs4QuicRadioButton); + } + binding.tunnelingRadioGroup.setOnCheckedChangeListener((group, checkedId) -> { useBridges(true); setUseTunnel(checkedId); 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 4567bf97..598f9908 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 @@ -15,6 +15,8 @@ import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getExcludedApps; 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.resetSnowflakeSettings; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.setAllowExperimentalTransports; @@ -22,6 +24,7 @@ import static se.leap.bitmaskclient.base.utils.PreferenceHelper.setUseObfuscatio import static se.leap.bitmaskclient.base.utils.PreferenceHelper.setUsePortHopping; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.setUseTunnel; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useBridges; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useManualDiscoverySettings; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useObfuscationPinning; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useSnowflake; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useManualBridgeSettings; @@ -132,14 +135,14 @@ public class SettingsFragment extends Fragment implements SharedPreferences.OnSh manualConfigRoot.setVisibility(ProviderObservable.getInstance().getCurrentProvider().supportsPluggableTransports() ? VISIBLE : GONE); IconTextEntry manualConfiguration = rootView.findViewById(R.id.bridge_manual_switch); SwitchCompat manualConfigurationSwitch = rootView.findViewById(R.id.bridge_manual_switch_control); - boolean usesManualBridge = useManualBridgeSettings(); - manualConfigurationSwitch.setChecked(usesManualBridge); + boolean useManualCircumventionSettings = useManualBridgeSettings() || useManualDiscoverySettings(); + manualConfigurationSwitch.setChecked(useManualCircumventionSettings); manualConfigurationSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { if (!buttonView.isPressed()) { return; } resetManualConfig(); - if (!usesManualBridge){ + if (!useManualCircumventionSettings){ openManualConfigurationFragment(); } }); 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 5a5d1d6e..44fc6e89 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 @@ -192,6 +192,7 @@ public interface Constants { String UDP = "udp"; String TCP = "tcp"; String KCP = "kcp"; + String QUIC = "quic"; String CAPABILITIES = "capabilities"; String TRANSPORT = "transport"; String TYPE = "type"; 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 89cea76b..e056ada9 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 @@ -17,6 +17,7 @@ package se.leap.bitmaskclient.base.models; import static de.blinkt.openvpn.core.connection.Connection.TransportProtocol.KCP; +import static de.blinkt.openvpn.core.connection.Connection.TransportProtocol.QUIC; import static de.blinkt.openvpn.core.connection.Connection.TransportProtocol.TCP; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4_HOP; @@ -52,7 +53,6 @@ import java.security.PrivateKey; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; -import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.Set; @@ -303,11 +303,11 @@ public final class Provider implements Parcelable { } public boolean supportsPluggableTransports() { - return supportsTransports(new Pair[]{new Pair<>(OBFS4, TCP), new Pair<>(OBFS4, KCP), new Pair<>(OBFS4_HOP, TCP), new Pair<>(OBFS4_HOP, KCP)}); + return supportsTransports(new Pair[]{new Pair<>(OBFS4, TCP), new Pair<>(OBFS4, KCP), new Pair<>(OBFS4, QUIC), new Pair<>(OBFS4_HOP, TCP), new Pair<>(OBFS4_HOP, KCP), new Pair<>(OBFS4_HOP, QUIC)}); } public boolean supportsExperimentalPluggableTransports() { - return supportsTransports(new Pair[]{new Pair<>(OBFS4, KCP), new Pair<>(OBFS4_HOP, TCP), new Pair<>(OBFS4_HOP, KCP)}); + return supportsTransports(new Pair[]{new Pair<>(OBFS4, KCP), new Pair<>(OBFS4_HOP, TCP), new Pair<>(OBFS4_HOP, KCP), new Pair<>(OBFS4, QUIC), new Pair<>(OBFS4_HOP, QUIC)}); } @@ -319,8 +319,12 @@ public final class Provider implements Parcelable { return supportsTransports(new Pair[]{new Pair<>(OBFS4, KCP)}); } + public boolean supportsObfs4Quic() { + return supportsTransports(new Pair[]{new Pair<>(OBFS4, QUIC)}); + } + public boolean supportsObfs4Hop() { - return supportsTransports(new Pair[]{new Pair<>(OBFS4_HOP, KCP),new Pair<>(OBFS4_HOP, TCP)}); + return supportsTransports(new Pair[]{new Pair<>(OBFS4_HOP, KCP), new Pair<>(OBFS4_HOP, QUIC), new Pair<>(OBFS4_HOP, TCP)}); } private boolean supportsTransports(Pair<TransportType, TransportProtocol>[] transportTypes) { 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 b7c6db5d..d2bb4d1b 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 @@ -4,6 +4,7 @@ import static android.content.Context.MODE_PRIVATE; import static se.leap.bitmaskclient.base.fragments.CensorshipCircumventionFragment.TUNNELING_AUTOMATICALLY; import static se.leap.bitmaskclient.base.fragments.CensorshipCircumventionFragment.TUNNELING_OBFS4; import static se.leap.bitmaskclient.base.fragments.CensorshipCircumventionFragment.TUNNELING_OBFS4_KCP; +import static se.leap.bitmaskclient.base.fragments.CensorshipCircumventionFragment.TUNNELING_QUIC; 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; @@ -615,8 +616,16 @@ public class PreferenceHelper { return getUseTunnel() == TUNNELING_OBFS4_KCP; } - public static boolean useManualBridgeSettings(){ - return (hasSnowflakePrefs() && getUseSnowflake()) || getUseObfs4() || getUseObfs4Kcp() || getUsePortHopping(); + public static boolean getUseObfs4Quic() { + return getUseTunnel() == TUNNELING_QUIC; + } + + public static boolean useManualBridgeSettings() { + return getUseObfs4() || getUseObfs4Kcp() || getUseObfs4Quic() || getUsePortHopping(); + } + + public static boolean useManualDiscoverySettings() { + return hasSnowflakePrefs() && getUseSnowflake(); } public static void setUseTunnel(int tunnel) { 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 9655013c..76aece23 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java @@ -26,6 +26,7 @@ import static se.leap.bitmaskclient.base.models.Constants.HOST; import static se.leap.bitmaskclient.base.models.Constants.IAT_MODE; import static se.leap.bitmaskclient.base.models.Constants.KCP; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; +import static se.leap.bitmaskclient.base.models.Constants.QUIC; import static se.leap.bitmaskclient.base.models.Constants.SORTED_GATEWAYS; import static se.leap.bitmaskclient.base.models.Constants.TCP; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningCert; @@ -37,6 +38,7 @@ import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseBridges; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseObfs4; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseObfs4Kcp; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUsePortHopping; +import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseObfs4Quic; import android.content.Context; import android.util.Log; @@ -174,7 +176,7 @@ public class GatewaysManager { if (getUsePortHopping()) { return new TransportType[]{OBFS4_HOP}; - } else if (getUseObfs4() || getUseObfs4Kcp()) { + } else if (getUseObfs4() || getUseObfs4Kcp() || getUseObfs4Quic()) { return new TransportType[]{OBFS4}; } else { return new TransportType[]{OBFS4, OBFS4_HOP}; @@ -192,10 +194,12 @@ public class GatewaysManager { return Set.of(TCP); } else if (getUseObfs4Kcp()) { return Set.of(KCP); + } else if (getUseObfs4Quic()) { + return Set.of(QUIC); } else { // If neither Obf4 nor Obf4Kcp are used, and bridges are enabled, - // then use both TCP and KCP (based on the original logic). - return Set.of(TCP, KCP); + // then allow to use any of these protocols + return Set.of(TCP, KCP, QUIC); } } @@ -492,7 +496,7 @@ public class GatewaysManager { options.put(CERT, getObfuscationPinningCert()); options.put(IAT_MODE, "0"); modelsBridge.options(options); - modelsBridge.transport(getObfuscationPinningKCP() ? "kcp" : "tcp"); + modelsBridge.transport(getObfuscationPinningKCP() ? KCP : TCP); modelsBridge.type(OBFS4.toString()); modelsBridge.host(PINNED_OBFUSCATION_PROXY); Gateway gateway = new Gateway(modelsEIPService, secrets, modelsBridge, provider.getApiVersion()); 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 6ee49951..9fdf3670 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,8 @@ package se.leap.bitmaskclient.pluggableTransports; +import static se.leap.bitmaskclient.base.models.Constants.KCP; +import static se.leap.bitmaskclient.base.models.Constants.QUIC; + import android.util.Log; import client.Client; @@ -12,6 +15,7 @@ import se.leap.bitmaskclient.pluggableTransports.models.HoppingConfig; import se.leap.bitmaskclient.pluggableTransports.models.KcpConfig; import se.leap.bitmaskclient.pluggableTransports.models.Obfs4Options; import se.leap.bitmaskclient.pluggableTransports.models.ObfsvpnConfig; +import se.leap.bitmaskclient.pluggableTransports.models.QuicConfig; public class ObfsvpnClient implements EventLogger { @@ -29,14 +33,17 @@ public class ObfsvpnClient implements EventLogger { //FIXME: use a different strategy here //Basically we would want to track if the more performant transport protocol (KCP?/TCP?) usage was successful //if so, we stick to it, otherwise we flip the flag - boolean kcpEnabled = Constants.KCP.equals(options.transport.getProtocols()[0]); + String protocol = options.transport.getProtocols()[0]; + boolean kcpEnabled = KCP.equals(protocol); + boolean quicEnabled = QUIC.equals(protocol); boolean hoppingEnabled = options.transport.getTransportType() == Connection.TransportType.OBFS4_HOP; if (!hoppingEnabled && (options.transport.getPorts() == null || options.transport.getPorts().length == 0)) { throw new IllegalStateException("obf4 based transport has no bridge ports configured"); } KcpConfig kcpConfig = new KcpConfig(kcpEnabled); + QuicConfig quicConfig = new QuicConfig(quicEnabled); HoppingConfig hoppingConfig = new HoppingConfig(hoppingEnabled,IP+":"+PORT, options, 10, 10); - ObfsvpnConfig obfsvpnConfig = new ObfsvpnConfig(IP+":"+PORT, hoppingConfig, kcpConfig, options.bridgeIP, options.transport.getPorts()[0], options.transport.getOptions().getCert() ); + ObfsvpnConfig obfsvpnConfig = new ObfsvpnConfig(IP+":"+PORT, hoppingConfig, kcpConfig, quicConfig, options.bridgeIP, options.transport.getPorts()[0], options.transport.getOptions().getCert() ); try { Log.d(TAG, obfsvpnConfig.toString()); client = Client.newFFIClient(obfsvpnConfig.toString()); diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/ObfsvpnConfig.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/ObfsvpnConfig.java index 9f85c4a0..cfcd6b6c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/ObfsvpnConfig.java +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/ObfsvpnConfig.java @@ -11,14 +11,16 @@ public class ObfsvpnConfig { final String proxyAddr; final HoppingConfig hoppingConfig; final KcpConfig kcpConfig; + final QuicConfig quicConfig; final String remoteIp; final String remotePort; final String obfs4Cert; - public ObfsvpnConfig(String proxyAddress, HoppingConfig hoppingConfig, KcpConfig kcpConfig, String remoteIP, String remotePort, String obfsv4Cert) { + public ObfsvpnConfig(String proxyAddress, HoppingConfig hoppingConfig, KcpConfig kcpConfig, QuicConfig quicConfig, String remoteIP, String remotePort, String obfsv4Cert) { this.proxyAddr = proxyAddress; this.hoppingConfig = hoppingConfig; this.kcpConfig = kcpConfig; + this.quicConfig = quicConfig; this.remoteIp = remoteIP; this.remotePort = remotePort; this.obfs4Cert = obfsv4Cert; diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/QuicConfig.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/QuicConfig.java new file mode 100644 index 00000000..dd377dd7 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/QuicConfig.java @@ -0,0 +1,24 @@ +package se.leap.bitmaskclient.pluggableTransports.models; + +import androidx.annotation.NonNull; + +import com.google.gson.FieldNamingPolicy; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class QuicConfig { + final boolean enabled; + + public QuicConfig(boolean enabled) { + this.enabled = enabled; + } + + @NonNull + @Override + public String toString() { + Gson gson = new GsonBuilder() + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) + .create(); + return gson.toJson(this); + } +} diff --git a/app/src/main/res/values/untranslatable.xml b/app/src/main/res/values/untranslatable.xml index bd8fa0e7..3d499e85 100644 --- a/app/src/main/res/values/untranslatable.xml +++ b/app/src/main/res/values/untranslatable.xml @@ -76,4 +76,5 @@ </string-array> <string name="tunnelling_obfs4" translatable="false">Obfs4</string> <string name="tunnelling_obfs4_kcp" translatable="false">Obfs4+KCP</string> + <string name="tunnelling_quic" translatable="false">Quic</string> </resources> |