diff --git a/app/build.gradle b/app/build.gradle
index 6df2616921d64d59c28f0073bc8bd0d2a7462c5e..b953df1f3c1f02bb4c949ecae9606d99fab47c0c 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -66,7 +66,8 @@ android {
     buildConfigField "String", "obfsvpn_port", '"4431"'
     buildConfigField "String", "obfsvpn_ip", '"37.218.241.208"'
     buildConfigField "String", "obfsvpn_cert", '"k0L4LFg0Wk98v7P66xvgAx2ud+kggvjZX/qul3iFTJGH5X7xSHT+vVL4UZR0WI3SkmDzUg"'
-    buildConfigField 'boolean', 'obfsvpn_use_kcp', 'true'
+    // obfsvpn_transport_protocol can be any of "tcp", "kcp" or "quic"
+    buildConfigField "String", 'obfsvpn_transport_protocol', '"kcp"'
     // default to UDP usage
     buildConfigField 'boolean', 'prefer_udp', 'false'
 
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 9943faff8badc176f1b8729f9148e30054b0b422..6cd8610591e9697a2e523babfc5fc008d7f3b379 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 e8789b32c7cda0526a3f4b60db700b037015138b..fc561d483f67bafcb15f8c20e397de14d5cc0c65 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/ObfuscationProxyDialog.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java
index 7d12ca70ec32cb9733fd57d94e243eadd6649275..2e4eec8aceffff617275468a4844d5d7a6940872 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java
@@ -2,11 +2,16 @@ package se.leap.bitmaskclient.base.fragments;
 
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
+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 android.app.Dialog;
 import android.os.Bundle;
 import android.text.TextUtils;
 import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -14,10 +19,10 @@ import androidx.appcompat.app.AlertDialog;
 import androidx.appcompat.app.AppCompatDialogFragment;
 import androidx.appcompat.widget.AppCompatButton;
 import androidx.appcompat.widget.AppCompatEditText;
+import androidx.appcompat.widget.AppCompatSpinner;
 
 import se.leap.bitmaskclient.base.utils.BuildConfigHelper;
 import se.leap.bitmaskclient.base.utils.PreferenceHelper;
-import se.leap.bitmaskclient.base.views.IconSwitchEntry;
 import se.leap.bitmaskclient.databinding.DObfuscationProxyBinding;
 import se.leap.bitmaskclient.eip.GatewaysManager;
 
@@ -30,7 +35,9 @@ public class ObfuscationProxyDialog extends AppCompatDialogFragment {
     AppCompatButton saveButton;
     AppCompatButton useDefaultsButton;
     AppCompatButton cancelButton;
-    IconSwitchEntry kcpSwitch;
+    AppCompatSpinner protocolSpinner;
+    private final String[] protocols = { TCP.toString(), KCP.toString(), QUIC.toString() };
+
 
     @NonNull
     @Override
@@ -46,15 +53,29 @@ public class ObfuscationProxyDialog extends AppCompatDialogFragment {
         saveButton = binding.buttonSave;
         useDefaultsButton = binding.buttonDefaults;
         cancelButton = binding.buttonCancel;
-        kcpSwitch = binding.kcpSwitch;
+        protocolSpinner = binding.protocolSpinner;
 
         ipField.setText(PreferenceHelper.getObfuscationPinningIP());
         portField.setText(PreferenceHelper.getObfuscationPinningPort());
         certificateField.setText(PreferenceHelper.getObfuscationPinningCert());
-        kcpSwitch.setChecked(PreferenceHelper.getObfuscationPinningKCP());
 
         GatewaysManager gatewaysManager = new GatewaysManager(getContext());
 
+
+        ArrayAdapter<String> adapter = new ArrayAdapter<>(binding.getRoot().getContext(), android.R.layout.simple_spinner_item, protocols);
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        protocolSpinner.setAdapter(adapter);
+
+        protocolSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+            @Override
+            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+                PreferenceHelper.setObfuscationPinningProtocol(protocols[position]);
+            }
+
+            @Override
+            public void onNothingSelected(AdapterView<?> parent) {}
+        });
+
         saveButton.setOnClickListener(v -> {
             String ip = TextUtils.isEmpty(ipField.getText()) ? null : ipField.getText().toString();
             PreferenceHelper.setObfuscationPinningIP(ip);
@@ -62,7 +83,6 @@ public class ObfuscationProxyDialog extends AppCompatDialogFragment {
             PreferenceHelper.setObfuscationPinningPort(port);
             String cert = TextUtils.isEmpty(certificateField.getText()) ? null : certificateField.getText().toString();
             PreferenceHelper.setObfuscationPinningCert(cert);
-            PreferenceHelper.setObfuscationPinningKCP(kcpSwitch.isChecked());
             PreferenceHelper.setUseObfuscationPinning(ip != null && port != null && cert != null);
             PreferenceHelper.setObfuscationPinningGatewayLocation(gatewaysManager.getLocationNameForIP(ip, v.getContext()));
             dismiss();
@@ -73,7 +93,7 @@ public class ObfuscationProxyDialog extends AppCompatDialogFragment {
            ipField.setText(BuildConfigHelper.obfsvpnIP());
            portField.setText(BuildConfigHelper.obfsvpnPort());
            certificateField.setText(BuildConfigHelper.obfsvpnCert());
-           kcpSwitch.setChecked(BuildConfigHelper.useKcp());
+           protocolSpinner.setSelection(getIndexForProtocol(BuildConfigHelper.obfsvpnTransportProtocol()));
         });
 
         cancelButton.setOnClickListener(v -> {
@@ -85,6 +105,15 @@ public class ObfuscationProxyDialog extends AppCompatDialogFragment {
         return builder.create();
     }
 
+    private int getIndexForProtocol(String protocol) {
+        for (int i = 0; i < protocols.length; i++) {
+            if (protocols[i].equals(protocol)) {
+                return i;
+            }
+        }
+        return 0;
+    }
+
     @Override
     public void onDestroyView() {
         super.onDestroyView();
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 4567bf9744cd50fb389a5d9199f3316e34cf30e7..598f9908724db02b5fc1f7e1c0543d953da59ebd 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 5a5d1d6e1a7ceacbc02042c5b02ffc0e47ae533a..b8849c4d182373f0791782cfbbbe4f12ae1e85d4 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
@@ -53,6 +53,7 @@ public interface Constants {
     String OBFUSCATION_PINNING_PORT = "obfuscation_pinning_port";
     String OBFUSCATION_PINNING_CERT = "obfuscation_pinning_cert";
     String OBFUSCATION_PINNING_KCP = "obfuscation_pinning_udp";
+    String OBFUSCATION_PINNING_PROTOCOL = "obfuscation_pinning_protocol";
     String OBFUSCATION_PINNING_LOCATION = "obfuscation_pinning_location";
     String USE_SYSTEM_PROXY = "usesystemproxy";
     String CUSTOM_PROVIDER_DOMAINS = "custom_provider_domains";
@@ -192,6 +193,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";
@@ -202,6 +204,10 @@ public interface Constants {
     String ENDPOINTS = "endpoints";
     String PORT_SEED = "port_seed";
     String PORT_COUNT = "port_count";
+    String HOP_JITTER = "hop_jitter";
+    String MIN_HOP_PORT = "min_hop_port";
+    String MAX_HOP_PORT = "max_hop_port";
+    String MIN_HOP_SECONDS = "min_hop_seconds";
     String EXPERIMENTAL = "experimental";
     String VERSION = "version";
     String NAME = "name";
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 89cea76b1d0dd0e8f497a6a56a438ea3a6682548..7679561645a853f8baf653f5b8767bd06015482f 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) {
@@ -996,7 +1000,7 @@ public final class Provider implements Parcelable {
         certificatePin = "";
         certificatePinEncoding = "";
         caCert = "";
-        apiVersion = 3;
+        apiVersion = BuildConfig.preferred_client_api_version;
         privateKeyString = "";
         vpnCertificate = "";
         allowRegistered = false;
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Transport.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Transport.java
index abd42812d1b7f8ea10a9a5b5983e398a85a12588..3b6956925343637c54015226293a1b763561e587 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/models/Transport.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Transport.java
@@ -1,10 +1,17 @@
 package se.leap.bitmaskclient.base.models;
 
+import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4_HOP;
 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.CERT;
+import static se.leap.bitmaskclient.base.models.Constants.HOP_JITTER;
 import static se.leap.bitmaskclient.base.models.Constants.IAT_MODE;
+import static se.leap.bitmaskclient.base.models.Constants.MAX_HOP_PORT;
+import static se.leap.bitmaskclient.base.models.Constants.MIN_HOP_PORT;
+import static se.leap.bitmaskclient.base.models.Constants.MIN_HOP_SECONDS;
 import static se.leap.bitmaskclient.base.models.Constants.PORTS;
+import static se.leap.bitmaskclient.base.models.Constants.PORT_COUNT;
+import static se.leap.bitmaskclient.base.models.Constants.PORT_SEED;
 import static se.leap.bitmaskclient.base.models.Constants.PROTOCOLS;
 import static se.leap.bitmaskclient.base.models.Constants.TRANSPORT;
 
@@ -21,6 +28,7 @@ import org.json.JSONObject;
 
 import java.io.Serializable;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Vector;
 
 import de.blinkt.openvpn.core.connection.Connection;
@@ -94,6 +102,14 @@ public class Transport implements Serializable {
         }
         Map<String, Object> options = modelsBridge.getOptions();
         Transport.Options transportOptions = new Transport.Options((String) options.get(CERT), (String) options.get(IAT_MODE));
+        if (OBFS4_HOP.toString().equals(modelsBridge.getType())) {
+            transportOptions.minHopSeconds = getIntOption(options, MIN_HOP_SECONDS, 5);
+            transportOptions.minHopPort = getIntOption(options, MIN_HOP_PORT, 49152);
+            transportOptions.maxHopPort = getIntOption(options, MAX_HOP_PORT, 65535);
+            transportOptions.hopJitter = getIntOption(options, HOP_JITTER, 10);
+            transportOptions.portCount = getIntOption(options, PORT_COUNT, 100);
+            transportOptions.portSeed = getIntOption(options, PORT_SEED, 1);
+        }
         Transport transport = new Transport(
                 modelsBridge.getType(),
                 new String[]{modelsBridge.getTransport()},
@@ -103,6 +119,16 @@ public class Transport implements Serializable {
         return transport;
     }
 
+    private static int getIntOption(Map<String, Object> options, String key, int defaultValue) {
+        try {
+            Object o = options.get(key);
+            return (int) o;
+        } catch (NullPointerException | ClassCastException e){
+            e.printStackTrace();
+            return defaultValue;
+        }
+    }
+
     public static Transport createTransportFrom(ModelsGateway modelsGateway) {
         if (modelsGateway == null) {
             return null;
@@ -165,7 +191,6 @@ public class Transport implements Serializable {
         private final String cert;
         @SerializedName("iatMode")
         private final String iatMode;
-
         @Nullable
         private Endpoint[] endpoints;
 
@@ -174,23 +199,30 @@ public class Transport implements Serializable {
         private int portSeed;
 
         private int portCount;
-
+        private int minHopPort;
+        private int maxHopPort;
+        private int minHopSeconds;
+        private int hopJitter;
 
         public Options(String cert, String iatMode) {
             this.cert = cert;
             this.iatMode = iatMode;
         }
 
-        public Options(String iatMode, Endpoint[] endpoints, int portSeed, int portCount, boolean experimental) {
-            this(iatMode, endpoints, null, portSeed, portCount, experimental);
+        public Options(String iatMode, Endpoint[] endpoints, int portSeed, int portCount, int minHopPort, int maxHopPort, int minHopSeconds, int hopJitter, boolean experimental) {
+            this(iatMode, endpoints, null, portSeed, portCount, minHopPort, maxHopPort, minHopSeconds, hopJitter, experimental);
         }
 
-        public Options(String iatMode, Endpoint[] endpoints, String cert, int portSeed, int portCount, boolean experimental) {
+        public Options(String iatMode, Endpoint[] endpoints, String cert, int portSeed, int portCount,  int minHopPort, int maxHopPort, int minHopSeconds, int hopJitter, boolean experimental) {
             this.iatMode = iatMode;
             this.endpoints = endpoints;
             this.portSeed = portSeed;
             this.portCount = portCount;
             this.experimental = experimental;
+            this.minHopPort = minHopPort;
+            this.maxHopPort = maxHopPort;
+            this.minHopSeconds = minHopSeconds;
+            this.hopJitter = hopJitter;
             this.cert = cert;
         }
 
@@ -221,6 +253,22 @@ public class Transport implements Serializable {
             return portCount;
         }
 
+        public int getMinHopPort() {
+            return minHopPort;
+        }
+
+        public int getMaxHopPort() {
+            return maxHopPort;
+        }
+
+        public int getMinHopSeconds() {
+            return minHopSeconds;
+        }
+
+        public int getHopJitter() {
+            return hopJitter;
+        }
+
         @Override
         public String toString() {
             return new Gson().toJson(this);
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java
index 22af1bfb1ccbc83ceee7ac93395b957c85f4ece8..22939611199509e5fd0d606fb08bd8e7805561cb 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java
@@ -15,7 +15,7 @@ public class BuildConfigHelper {
         String obfsvpnIP();
         String obfsvpnPort();
         String obfsvpnCert();
-        boolean useKcp();
+        String obfsvpnTransportProtocol();
         boolean isDefaultBitmask();
     }
 
@@ -26,9 +26,11 @@ public class BuildConfigHelper {
             return BuildConfig.obfsvpn_ip != null &&
                     BuildConfig.obfsvpn_port != null &&
                     BuildConfig.obfsvpn_cert != null &&
+                    BuildConfig.obfsvpn_transport_protocol != null &&
                     !BuildConfig.obfsvpn_ip.isEmpty() &&
                     !BuildConfig.obfsvpn_port.isEmpty() &&
-                    !BuildConfig.obfsvpn_cert.isEmpty();
+                    !BuildConfig.obfsvpn_cert.isEmpty() &&
+                    !BuildConfig.obfsvpn_transport_protocol.isEmpty();
         }
 
         @Override
@@ -47,8 +49,8 @@ public class BuildConfigHelper {
         }
 
         @Override
-        public boolean useKcp() {
-            return BuildConfig.obfsvpn_use_kcp;
+        public String obfsvpnTransportProtocol() {
+            return BuildConfig.obfsvpn_transport_protocol;
         }
 
         @Override
@@ -79,8 +81,8 @@ public class BuildConfigHelper {
     public static String obfsvpnCert() {
         return instance.obfsvpnCert();
     }
-    public static boolean useKcp() {
-        return instance.useKcp();
+    public static String obfsvpnTransportProtocol() {
+        return instance.obfsvpnTransportProtocol();
     }
 
     public static boolean isDefaultBitmask() {
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 b7c6db5d73991884e0d21bc0adf08e6adff21a13..ba644b91eb2212c885d69b4e6f399894f2d031c0 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,9 +1,11 @@
 package se.leap.bitmaskclient.base.utils;
 
 import static android.content.Context.MODE_PRIVATE;
+import static de.blinkt.openvpn.core.connection.Connection.TransportProtocol.TCP;
 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;
@@ -23,9 +25,9 @@ import static se.leap.bitmaskclient.base.models.Constants.LAST_UPDATE_CHECK;
 import static se.leap.bitmaskclient.base.models.Constants.LAST_USED_PROFILE;
 import static se.leap.bitmaskclient.base.models.Constants.OBFUSCATION_PINNING_CERT;
 import static se.leap.bitmaskclient.base.models.Constants.OBFUSCATION_PINNING_IP;
-import static se.leap.bitmaskclient.base.models.Constants.OBFUSCATION_PINNING_KCP;
 import static se.leap.bitmaskclient.base.models.Constants.OBFUSCATION_PINNING_LOCATION;
 import static se.leap.bitmaskclient.base.models.Constants.OBFUSCATION_PINNING_PORT;
+import static se.leap.bitmaskclient.base.models.Constants.OBFUSCATION_PINNING_PROTOCOL;
 import static se.leap.bitmaskclient.base.models.Constants.PREFERENCES_APP_VERSION;
 import static se.leap.bitmaskclient.base.models.Constants.PREFERRED_CITY;
 import static se.leap.bitmaskclient.base.models.Constants.PREFER_UDP;
@@ -587,12 +589,12 @@ public class PreferenceHelper {
         return getString(OBFUSCATION_PINNING_LOCATION, null);
     }
 
-    public static Boolean getObfuscationPinningKCP() {
-        return getBoolean(OBFUSCATION_PINNING_KCP, false);
+    public static String getObfuscationPinningProtocol() {
+        return getString(OBFUSCATION_PINNING_PROTOCOL, TCP.toString());
     }
 
-    public static void setObfuscationPinningKCP(boolean isKCP) {
-        putBoolean(OBFUSCATION_PINNING_KCP, isKCP);
+    public static void setObfuscationPinningProtocol(String protocol) {
+        putString(OBFUSCATION_PINNING_PROTOCOL, protocol);
     }
 
     public static void setUseIPv6Firewall(boolean useFirewall) {
@@ -615,8 +617,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/Gateway.java b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
index d1ae7c43978137beb417a3d700b81684626c25dd..783f9124255cfdaeabb8ee30208c0221128459a2 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/Gateway.java
@@ -29,15 +29,6 @@ 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 static se.leap.bitmaskclient.base.models.Transport.createTransportsFrom;
-import static se.leap.bitmaskclient.base.utils.PreferenceHelper.allowExperimentalTransports;
-import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getExcludedApps;
-import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningCert;
-import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningGatewayLocation;
-import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningIP;
-import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningKCP;
-import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningPort;
-import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferUDP;
-import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useObfuscationPinning;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -294,7 +285,7 @@ public class Gateway {
      * In case the transport type is an obfuscation transport, you can pass a Vector of required transport layer protocols.
      * This way you can filter for TCP based obfs4 traffic versus KCP based obfs4 traffic.
      * @param transportType transport type, e.g. openvpn or obfs4
-     * @param obfuscationTransportLayerProtocols filters for _any_ of these transport layer protocols (e.g. TCP or KCP) of a given obfuscation transportType, can be omitted if transportType is OPENVPN.
+     * @param obfuscationTransportLayerProtocols filters for _any_ of these transport layer protocols (e.g. TCP, KCP, QUIC) of a given obfuscation transportType, can be omitted if transportType is OPENVPN.
      *
      * @return
      */
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 9655013c600a4fa5f3721e0b1ede34ef5ac09e85..16f12e024202bc1c3b121930b9f0bd99a3e8a621 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaysManager.java
@@ -26,16 +26,18 @@ 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;
 import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningIP;
-import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningKCP;
 import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningPort;
+import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningProtocol;
 import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferredCity;
 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.getUseObfs4Quic;
 import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUsePortHopping;
 
 import android.content.Context;
@@ -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);
         }
     }
 
@@ -432,7 +436,7 @@ public class GatewaysManager {
                 try {
                     Transport[] transports = new Transport[]{
                             new Transport(OBFS4.toString(),
-                                    new String[]{getObfuscationPinningKCP() ? "kcp" : "tcp"},
+                                    new String[]{getObfuscationPinningProtocol()},
                                     new String[]{getObfuscationPinningPort()},
                                     getObfuscationPinningCert())};
                     GatewayJson.Capabilities capabilities = new GatewayJson.Capabilities(false, false, false, transports, false);
@@ -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(getObfuscationPinningProtocol());
                 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/eip/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
index f988dfa0174d63df4fcdf75863ecc9b7f24e69ce..0288ab2582468524695a62f073cad9548c36eefa 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
@@ -21,6 +21,7 @@ import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4_H
 import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN;
 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.REMOTE;
 import static se.leap.bitmaskclient.base.models.Constants.TCP;
 import static se.leap.bitmaskclient.base.models.Constants.UDP;
@@ -29,8 +30,8 @@ import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getExcludedApps;
 import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningCert;
 import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningGatewayLocation;
 import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningIP;
-import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningKCP;
 import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningPort;
+import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getObfuscationPinningProtocol;
 import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferUDP;
 import static se.leap.bitmaskclient.base.utils.PreferenceHelper.useObfuscationPinning;
 
@@ -69,7 +70,7 @@ public class VpnConfigGenerator {
     private final String obfuscationPinningIP;
     private final String obfuscationPinningPort;
     private final String obfuscationPinningCert;
-    private final boolean obfuscationPinningKCP;
+    private final String obfuscationPinningTransportProtocol;
     private final String remoteGatewayIP;
     private final String remoteGatewayIPv6;
     private final String profileName;
@@ -89,7 +90,7 @@ public class VpnConfigGenerator {
         Set<String> excludedApps = null;
 
         boolean useObfuscationPinning;
-        boolean obfuscationProxyKCP;
+        String obfuscationProxyTransportProtocol = "";
         String obfuscationProxyIP = "";
         String obfuscationProxyPort = "";
         String obfuscationProxyCert = "";
@@ -110,7 +111,7 @@ public class VpnConfigGenerator {
                 config.obfuscationProxyIP = getObfuscationPinningIP();
                 config.obfuscationProxyPort = getObfuscationPinningPort();
                 config.obfuscationProxyCert = getObfuscationPinningCert();
-                config.obfuscationProxyKCP = getObfuscationPinningKCP();
+                config.obfuscationProxyTransportProtocol = getObfuscationPinningProtocol();
             }
             config.transports = transports;
             return config;
@@ -128,7 +129,7 @@ public class VpnConfigGenerator {
         this.obfuscationPinningIP = config.obfuscationProxyIP;
         this.obfuscationPinningPort = config.obfuscationProxyPort;
         this.obfuscationPinningCert = config.obfuscationProxyCert;
-        this.obfuscationPinningKCP = config.obfuscationProxyKCP;
+        this.obfuscationPinningTransportProtocol = config.obfuscationProxyTransportProtocol;
         this.remoteGatewayIP = config.remoteGatewayIP;
         this.remoteGatewayIPv6 = config.remoteGatewayIPv6;
         this.transports = config.transports;
@@ -196,7 +197,7 @@ public class VpnConfigGenerator {
         String ip = remoteGatewayIP;
         if (useObfuscationPinning) {
             transport = new Transport(OBFS4.toString(),
-                    new String[]{obfuscationPinningKCP ? KCP : TCP},
+                    new String[]{obfuscationPinningTransportProtocol},
                     new String[]{obfuscationPinningPort},
                     obfuscationPinningCert);
             ip = obfuscationPinningIP;
@@ -326,7 +327,7 @@ public class VpnConfigGenerator {
                 return TCP.equals(protocol) || UDP.equals(protocol);
             case OBFS4_HOP:
             case OBFS4:
-                return TCP.equals(protocol) || KCP.equals(protocol);
+                return TCP.equals(protocol) || KCP.equals(protocol) || QUIC.equals(protocol);
         }
         return false;
     }
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 6ee49951daa8658e47cac09978d707a1a4e100af..625bbfd84926c97bb8c6dff2e7ee9615ed9a8ab8 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);
-        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() );
+        QuicConfig quicConfig = new QuicConfig(quicEnabled);
+        HoppingConfig hoppingConfig = new HoppingConfig(hoppingEnabled,IP+":"+PORT, options);
+        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/HoppingConfig.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/HoppingConfig.java
index 96b8c4606ff17a20fb8f620325b07dde50c1cbae..0dc2d5085f076bd18f1998b56039f1b2944061af 100644
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/HoppingConfig.java
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/models/HoppingConfig.java
@@ -11,14 +11,15 @@ import se.leap.bitmaskclient.base.models.Transport;
 public class HoppingConfig {
 
     /**
-     * Enabled       bool     `json:"enabled"`
+     * 	Enabled       bool     `json:"enabled"`
      * 	Remotes       []string `json:"remotes"`
      * 	Obfs4Certs    []string `json:"obfs4_certs"`
      * 	PortSeed      int64    `json:"port_seed"`
      * 	PortCount     uint     `json:"port_count"`
+     * 	MinHopPort    uint     `json:"min_hop_port"`
+     * 	MaxHopPort    uint     `json:"max_hop_port"`
      * 	MinHopSeconds uint     `json:"min_hop_seconds"`
      * 	HopJitter     uint     `json:"hop_jitter"`
-     * }
      */
 
     final boolean enabled;
@@ -29,12 +30,12 @@ public class HoppingConfig {
     final int portCount;
     final int minHopSeconds;
     final int hopJitter;
+    final int minHopPort;
+    final int maxHopPort;
 
     public HoppingConfig(boolean enabled,
                          String proxyAddr,
-                         Obfs4Options options,
-                         int minHopSeconds,
-                         int hopJitter) {
+                         Obfs4Options options) {
         this.enabled = enabled;
         this.proxyAddr = proxyAddr;
         Transport transport = options.transport;
@@ -54,8 +55,10 @@ public class HoppingConfig {
         }
         this.portSeed = transport.getOptions().getPortSeed();
         this.portCount = transport.getOptions().getPortCount();
-        this.minHopSeconds = minHopSeconds;
-        this.hopJitter = hopJitter;
+        this.minHopSeconds = transport.getOptions().getMinHopSeconds();
+        this.hopJitter = transport.getOptions().getHopJitter();
+        this.minHopPort = transport.getOptions().getMinHopPort();
+        this.maxHopPort = transport.getOptions().getMaxHopPort();
     }
 
     @NonNull
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 9f85c4a04807e5dc247f4e6b53a8e9b7fa5adbce..cfcd6b6c3b6449c5c35cea0885fd3ee968ea28d7 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 0000000000000000000000000000000000000000..dd377dd74591e193df9e02a64bb6d018d3f0d40e
--- /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/layout/d_obfuscation_proxy.xml b/app/src/main/res/layout/d_obfuscation_proxy.xml
index 7b8fcaa734897d54cb0816a64b72689b634f7919..03ffb61ffc6a90b8832c4140964011539caa632b 100644
--- a/app/src/main/res/layout/d_obfuscation_proxy.xml
+++ b/app/src/main/res/layout/d_obfuscation_proxy.xml
@@ -57,16 +57,32 @@
             android:id="@+id/cert_field"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"/>
-        <se.leap.bitmaskclient.base.views.IconSwitchEntry
-            android:id="@+id/kcp_switch"
+
+        <TextView
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            app:text="KCP"
-            app:subtitle="UDP based network protocol"
-            app:icon="@drawable/ic_multiple_stop"
-            >
-
-        </se.leap.bitmaskclient.base.views.IconSwitchEntry>
+            android:text="Network protocol"
+            android:textStyle="bold"
+            android:paddingTop="@dimen/activity_margin"
+            android:textAppearance="@android:style/TextAppearance.DeviceDefault" />
+        <androidx.appcompat.widget.LinearLayoutCompat
+            android:id="@+id/protocol_spinner_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:gravity="center_vertical"
+            android:orientation="horizontal">
+            <androidx.appcompat.widget.AppCompatImageView
+                android:layout_width="?android:attr/listPreferredItemHeightSmall"
+                android:layout_height="?android:attr/listPreferredItemHeightSmall"
+                android:src="@drawable/ic_multiple_stop"
+                android:padding="@dimen/stdpadding"/>
+            <androidx.appcompat.widget.AppCompatSpinner
+                android:id="@+id/protocol_spinner"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:tooltipText="select nework protocol"/>
+        </androidx.appcompat.widget.LinearLayoutCompat>
 
         <androidx.appcompat.widget.LinearLayoutCompat
             android:layout_width="wrap_content"
diff --git a/app/src/main/res/values/untranslatable.xml b/app/src/main/res/values/untranslatable.xml
index bd8fa0e77d56eeb33b1276083d7192e1cee99bde..3d499e85b605637d944d6e79f845f8293820ab7c 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>
diff --git a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java
index 43df146b05789038619e168e7a7ab00695b86766..aa098b94928b04360f76e034d57515d36e37e872 100644
--- a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java
+++ b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java
@@ -33,15 +33,16 @@ import se.leap.bitmaskclient.pluggableTransports.models.Obfs4Options;
 public class VpnProfileTest {
 
     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,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"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,\"mTransportType\":1,\"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,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"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\":\"8080\",\"mUseUdp\":true,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"bridgeIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"portCount\":0,\"iatMode\":\"0\",\"cert\":\"CERT\",\"experimental\":false,\"portSeed\":0},\"type\":\"obfs4\",\"protocols\":[\"tcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":2,\"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,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"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\":\"8080\",\"mUseUdp\":true,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"bridgeIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"portCount\":0,\"iatMode\":\"1\",\"cert\":\"CERT\",\"experimental\":false,\"portSeed\":0},\"type\":\"obfs4\",\"protocols\":[\"tcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":2,\"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,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"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\":\"8080\",\"mUseUdp\":true,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"bridgeIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"portCount\":0,\"iatMode\":\"1\",\"cert\":\"CERT\",\"experimental\":false,\"portSeed\":0},\"type\":\"obfs4\",\"protocols\":[\"kcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":2,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}\n";
+    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,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"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\":\"8080\",\"mUseUdp\":true,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"bridgeIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"minHopSeconds\":0,\"portCount\":0,\"iatMode\":\"0\",\"cert\":\"CERT\",\"experimental\":false,\"minHopPort\":0,\"portSeed\":0,\"hopJitter\":0,\"maxHopPort\":0},\"type\":\"obfs4\",\"protocols\":[\"tcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":2,\"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,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"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\":\"8080\",\"mUseUdp\":true,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"bridgeIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"minHopSeconds\":0,\"portCount\":0,\"iatMode\":\"1\",\"cert\":\"CERT\",\"experimental\":false,\"minHopPort\":0,\"portSeed\":0,\"hopJitter\":0,\"maxHopPort\":0},\"type\":\"obfs4\",\"protocols\":[\"tcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":2,\"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,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"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\":\"8080\",\"mUseUdp\":true,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"bridgeIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"minHopSeconds\":0,\"portCount\":0,\"iatMode\":\"1\",\"cert\":\"CERT\",\"experimental\":false,\"minHopPort\":0,\"portSeed\":0,\"hopJitter\":0,\"maxHopPort\":0},\"type\":\"obfs4\",\"protocols\":[\"kcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":2,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}\n";
+    private static final String OBFS4CONNECTION_PROFILE_OBFSVPN_QUIC = "{\"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,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"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\":\"8080\",\"mUseUdp\":true,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"bridgeIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"minHopSeconds\":0,\"portCount\":0,\"iatMode\":\"1\",\"cert\":\"CERT\",\"experimental\":false,\"minHopPort\":0,\"portSeed\":0,\"hopJitter\":0,\"maxHopPort\":0},\"type\":\"obfs4\",\"protocols\":[\"quic\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":2,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}\n";
 
-    private static final String OBFS4CONNECTION_PROFILE_OBFSVPN_HOP = "{\"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,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"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\":\"8080\",\"mUseUdp\":true,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"bridgeIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"portCount\":100,\"endpoints\":[{\"ip\":\"1.1.1.1\",\"cert\":\"CERT1\"},{\"ip\":\"2.2.2.2\",\"cert\":\"CERT2\"}],\"iatMode\":\"1\",\"experimental\":true,\"portSeed\":200},\"type\":\"obfs4\",\"protocols\":[\"tcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":3,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}\n";
+    private static final String OBFS4CONNECTION_PROFILE_OBFSVPN_HOP = "{\"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,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"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\":\"8080\",\"mUseUdp\":true,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"bridgeIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"minHopSeconds\":10,\"portCount\":100,\"endpoints\":[{\"ip\":\"1.1.1.1\",\"cert\":\"CERT1\"},{\"ip\":\"2.2.2.2\",\"cert\":\"CERT2\"}],\"iatMode\":\"1\",\"experimental\":true,\"minHopPort\":40000,\"portSeed\":2500,\"hopJitter\":10,\"maxHopPort\":64000},\"type\":\"obfs4\",\"protocols\":[\"tcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":3,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}\n";
 
-    private static final String OBFS4CONNECTION_PROFILE_OBFSVPN_HOP_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,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"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\":\"8080\",\"mUseUdp\":true,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"bridgeIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"portCount\":100,\"endpoints\":[{\"ip\":\"1.1.1.1\",\"cert\":\"CERT1\"},{\"ip\":\"2.2.2.2\",\"cert\":\"CERT2\"}],\"iatMode\":\"1\",\"experimental\":true,\"portSeed\":2500},\"type\":\"obfs4\",\"protocols\":[\"kcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":3,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}\n";
+    private static final String OBFS4CONNECTION_PROFILE_OBFSVPN_HOP_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,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"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\":\"8080\",\"mUseUdp\":true,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"bridgeIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"minHopSeconds\":10,\"portCount\":100,\"endpoints\":[{\"ip\":\"1.1.1.1\",\"cert\":\"CERT1\"},{\"ip\":\"2.2.2.2\",\"cert\":\"CERT2\"}],\"iatMode\":\"1\",\"experimental\":true,\"minHopPort\":40000,\"portSeed\":2500,\"hopJitter\":10,\"maxHopPort\":64000},\"type\":\"obfs4\",\"protocols\":[\"kcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":3,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}\n";
 
-    private static final String OBFS4CONNECTION_PROFILE_OBFSVPN_PORTHOPPING = "{\"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,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"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\":\"8080\",\"mUseUdp\":true,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"bridgeIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"portCount\":100,\"iatMode\":\"1\",\"cert\":\"CERT\",\"experimental\":true,\"portSeed\":200},\"type\":\"obfs4-hop\",\"protocols\":[\"tcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":3,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}\n";
+    private static final String OBFS4CONNECTION_PROFILE_OBFSVPN_PORTHOPPING = "{\"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,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"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\":\"8080\",\"mUseUdp\":true,\"mProxyPort\":\"\",\"mUseCustomConfig\":false,\"options\":{\"bridgeIP\":\"192.168.0.1\",\"transport\":{\"options\":{\"minHopSeconds\":10,\"portCount\":100,\"iatMode\":\"1\",\"cert\":\"CERT\",\"experimental\":true,\"minHopPort\":40000,\"portSeed\":2500,\"hopJitter\":10,\"maxHopPort\":64000},\"type\":\"obfs4-hop\",\"protocols\":[\"tcp\"],\"ports\":[\"1234\"]}},\"mProxyName\":\"\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.Obfs4Connection\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":3,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}\n";
 
     @Before
     public void setup() {
@@ -128,12 +129,30 @@ public class VpnProfileTest {
         assertEquals(expectation.toString(),actual.toString());
     }
 
+    @Test
+    public void toJson_obfs4_obfsvpn_quic() throws JSONException {
+
+        VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4);
+        Transport.Options options = new Transport.Options("CERT", "1");
+        Transport transport = new Transport(OBFS4.toString(), new String[]{"quic"}, new String[]{"1234"}, options);
+        mockVpnProfile.mConnections[0] = new Obfs4Connection(new Obfs4Options("192.168.0.1", transport));
+        mockVpnProfile.mLastUsed = 0;
+        String s = mockVpnProfile.toJson();
+
+        //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_QUIC);
+
+        assertEquals(expectation.toString(),actual.toString());
+    }
+
     @Test
     public void toJson_obfs4hop_kcp() throws JSONException {
 
         VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4_HOP);
 
-        Transport.Options options = new Transport.Options("1", new Transport.Endpoint[]{new Transport.Endpoint("1.1.1.1", "CERT1"), new Transport.Endpoint("2.2.2.2", "CERT2")}, 2500, 100, true);
+        Transport.Options options = new Transport.Options("1", new Transport.Endpoint[]{new Transport.Endpoint("1.1.1.1", "CERT1"), new Transport.Endpoint("2.2.2.2", "CERT2")}, 2500, 100, 40000, 64000, 10, 10, true);
         Transport transport = new Transport(OBFS4.toString(), new String[]{"kcp"}, new String[]{"1234"}, options);
         mockVpnProfile.mConnections[0] = new Obfs4Connection(new Obfs4Options("192.168.0.1", transport));
 
@@ -153,7 +172,7 @@ public class VpnProfileTest {
 
         VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4_HOP);
 
-        Transport.Options options = new Transport.Options("1", null, "CERT",200, 100, true);
+        Transport.Options options = new Transport.Options("1", null, "CERT",2500, 100, 40000, 64000, 10, 10,  true);
         Transport transport = new Transport(OBFS4_HOP.toString(), new String[]{"tcp"}, new String[]{"1234"}, options);
         mockVpnProfile.mConnections[0] = new Obfs4Connection(new Obfs4Options("192.168.0.1", transport));
 
@@ -172,7 +191,7 @@ public class VpnProfileTest {
     public void toJson_obfs4hop() throws JSONException {
 
         VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4_HOP);
-        Transport.Options options = new Transport.Options("1", new Transport.Endpoint[]{new Transport.Endpoint("1.1.1.1", "CERT1"), new Transport.Endpoint("2.2.2.2", "CERT2")}, 200, 100, true);
+        Transport.Options options = new Transport.Options("1", new Transport.Endpoint[]{new Transport.Endpoint("1.1.1.1", "CERT1"), new Transport.Endpoint("2.2.2.2", "CERT2")}, 2500, 100, 40000, 64000, 10, 10, true);
         Transport transport = new Transport(OBFS4.toString(), new String[]{"tcp"}, new String[]{"1234"}, options);
         mockVpnProfile.mConnections[0] = new Obfs4Connection(new Obfs4Options("192.168.0.1", transport));
 
@@ -242,4 +261,21 @@ public class VpnProfileTest {
         assertEquals("192.168.0.1", obfs4Connection.getObfs4Options().bridgeIP);
         assertEquals("1234", obfs4Connection.getObfs4Options().transport.getPorts()[0]);
     }
+
+    @Test
+    public void fromJson_obfs4_obfsvpn_quic() {
+
+        VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE_OBFSVPN_QUIC);
+        assertNotNull(mockVpnProfile);
+        assertNotNull(mockVpnProfile.mConnections);
+        assertNotNull(mockVpnProfile.mConnections[0]);
+        assertTrue(mockVpnProfile.mConnections[0].isUseUdp());
+        Obfs4Connection obfs4Connection = (Obfs4Connection) mockVpnProfile.mConnections[0];
+        assertEquals(OBFS4, obfs4Connection.getTransportType());
+        assertEquals("quic", obfs4Connection.getObfs4Options().transport.getProtocols()[0]);
+        assertEquals("CERT", obfs4Connection.getObfs4Options().transport.getOptions().getCert());
+        assertEquals("1", obfs4Connection.getObfs4Options().transport.getOptions().getIatMode());
+        assertEquals("192.168.0.1", obfs4Connection.getObfs4Options().bridgeIP);
+        assertEquals("1234", obfs4Connection.getObfs4Options().transport.getPorts()[0]);
+    }
 }
\ No newline at end of file
diff --git a/app/src/test/java/se/leap/bitmaskclient/base/models/GatewayJsonTest.java b/app/src/test/java/se/leap/bitmaskclient/base/models/GatewayJsonTest.java
index 801f98ad8198894f986f284c634dd532d65ca23a..1e07b293aa6c7f1c16871098f7abf8c5fc884620 100644
--- a/app/src/test/java/se/leap/bitmaskclient/base/models/GatewayJsonTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/base/models/GatewayJsonTest.java
@@ -12,7 +12,7 @@ public class GatewayJsonTest {
 
     @Test
     public void testToString() {
-        String gatewayJSON = "{\"location\":\"Unknown Location\",\"ip_address\":\"1.2.3.4\",\"host\":\"pinned.obfuscation.proxy\",\"capabilities\":{\"adblock\":false,\"filter_dns\":false,\"limited\":false,\"transport\":[{\"type\":\"obfs4\",\"protocols\":[\"tcp\"],\"ports\":[\"1194\"],\"options\":{\"cert\":\"xxxxxxx\",\"iatMode\":\"0\",\"experimental\":false,\"portSeed\":0,\"portCount\":0}}],\"user_ips\":false}}";
+        String gatewayJSON = "{\"location\":\"Unknown Location\",\"ip_address\":\"1.2.3.4\",\"host\":\"pinned.obfuscation.proxy\",\"capabilities\":{\"adblock\":false,\"filter_dns\":false,\"limited\":false,\"transport\":[{\"type\":\"obfs4\",\"protocols\":[\"tcp\"],\"ports\":[\"1194\"],\"options\":{\"cert\":\"xxxxxxx\",\"iatMode\":\"0\",\"experimental\":false,\"portSeed\":0,\"portCount\":0,\"minHopPort\":0,\"maxHopPort\":0,\"minHopSeconds\":0,\"hopJitter\":0}}],\"user_ips\":false}}";
 
         Connection.TransportType transportType = OBFS4;
         Transport[] transports = new Transport[]{
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 dc35ecb9fd3dc9b5d77bab251f4e7305fb4b9e15..fc2e6d0325bfa97d20a66bed7b57e11f93105ab0 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
@@ -124,6 +124,20 @@ public class ProviderTest {
         assertTrue(p1.supportsExperimentalPluggableTransports());
     }
 
+    @Test
+    public void testIsExperimentalPluggableTransportsSupported_Obfs4Quic_returnsTrue() throws Exception {
+        Provider p1 = TestSetupHelper.getProvider(
+                "https://pt.demo.bitmask.net",
+                null,
+                null,
+                null,
+                null,
+                null,
+                "multiple_pts_per_host_eip-service.json",
+                null);
+        assertTrue(p1.supportsExperimentalPluggableTransports());
+    }
+
     @Test
     public void testSupportsPluggableTransports_Obfs4Kcp_obsvpn_returnsTrue() throws Exception {
         BuildConfigHelper helper = MockHelper.mockBuildConfigHelper(true);
@@ -140,4 +154,20 @@ public class ProviderTest {
         assertTrue(p1.supportsPluggableTransports());
     }
 
+    @Test
+    public void testSupportsPluggableTransports_Obfs4Quic_obsvpn_returnsTrue() throws Exception {
+        BuildConfigHelper helper = MockHelper.mockBuildConfigHelper(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/java/se/leap/bitmaskclient/eip/GatewayTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/GatewayTest.java
index 88e58cd8698a29e1e454ce35fbd879ea716cdbdf..fc0620793ab2af66f1b6ea7c6cf50b82d8953824 100644
--- a/app/src/test/java/se/leap/bitmaskclient/eip/GatewayTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/eip/GatewayTest.java
@@ -1,11 +1,12 @@
 package se.leap.bitmaskclient.eip;
 
-import static org.junit.Assert.*;
-
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 import static se.leap.bitmaskclient.base.models.Constants.GATEWAYS;
-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.Provider.CA_CERT;
 import static se.leap.bitmaskclient.testutils.TestSetupHelper.getProvider;
 
 import android.content.Context;
@@ -33,11 +34,8 @@ import de.blinkt.openvpn.core.ConfigParser;
 import de.blinkt.openvpn.core.connection.Connection;
 import de.blinkt.openvpn.core.connection.Obfs4Connection;
 import se.leap.bitmaskclient.base.models.Provider;
-import se.leap.bitmaskclient.base.models.ProviderObservable;
 import se.leap.bitmaskclient.base.utils.PreferenceHelper;
-import se.leap.bitmaskclient.base.utils.TimezoneHelper;
 import se.leap.bitmaskclient.testutils.MockSharedPreferences;
-import se.leap.bitmaskclient.testutils.TestSetupHelper;
 
 @RunWith(RobolectricTestRunner.class)
 @Config(sdk = {Build.VERSION_CODES.P})
@@ -129,6 +127,7 @@ public class GatewayTest {
         assertTrue(gateway.supportsTransport(Connection.TransportType.OBFS4, null));
         assertTrue(gateway.supportsTransport(Connection.TransportType.OBFS4, new HashSet<>(Arrays.asList("kcp"))));
         assertTrue(gateway.supportsTransport(Connection.TransportType.OBFS4, new HashSet<>(Arrays.asList("tcp"))));
+        assertTrue(gateway.supportsTransport(Connection.TransportType.OBFS4, new HashSet<>(Arrays.asList("quic"))));
         assertFalse(gateway.supportsTransport(Connection.TransportType.OBFS4, new HashSet<>(Arrays.asList("invalid"))));
     }
 
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 327e208580e4ac209b20d4756d5e31610609b189..fa5d888b659b6272e45ee60f90c778f42b0251d9 100644
--- a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java
@@ -1653,7 +1653,7 @@ public class VpnConfigGeneratorTest {
         configuration.obfuscationProxyPort = "443";
         configuration.obfuscationProxyIP = "5.6.7.8";
         configuration.obfuscationProxyCert = "asdfasdf";
-        configuration.obfuscationProxyKCP = true;
+        configuration.obfuscationProxyTransportProtocol = "kcp";
         configuration.remoteGatewayIP = "1.2.3.4";
         configuration.transports = createTransportsFrom(gateway, 3);
         vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, configuration);
@@ -1671,7 +1671,7 @@ public class VpnConfigGeneratorTest {
         VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
         configuration.apiVersion = 3;
         configuration.useObfuscationPinning = true;
-        configuration.obfuscationProxyKCP = false;
+        configuration.obfuscationProxyTransportProtocol = "tcp";
         configuration.obfuscationProxyPort = "443";
         configuration.obfuscationProxyIP = "5.6.7.8";
         configuration.obfuscationProxyCert = "asdfasdf";
@@ -1692,7 +1692,7 @@ public class VpnConfigGeneratorTest {
         VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
         configuration.apiVersion = 3;
         configuration.useObfuscationPinning = true;
-        configuration.obfuscationProxyKCP = true;
+        configuration.obfuscationProxyTransportProtocol = "kcp";
         configuration.obfuscationProxyPort = "443";
         configuration.obfuscationProxyIP = "5.6.7.8";
         configuration.obfuscationProxyCert = "asdfasdf";
@@ -1706,6 +1706,28 @@ public class VpnConfigGeneratorTest {
         assertTrue("bridge is pinned one", getVpnProfile(vpnProfiles, OBFS4).getTransportType() == OBFS4 && getVpnProfile(vpnProfiles, OBFS4).mGatewayIp.equals("1.2.3.4"));
         assertTrue("bridge is running KCP", ((Obfs4Connection) getVpnProfile(vpnProfiles, OBFS4).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("kcp"));
     }
+
+    @Test
+    public void testGenerateVpnProfile_ObfuscationPinningEnabled_quic_obfs4QuicProfile () 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.Configuration configuration = new VpnConfigGenerator.Configuration();
+        configuration.apiVersion = 3;
+        configuration.useObfuscationPinning = true;
+        configuration.obfuscationProxyTransportProtocol = "quic";
+        configuration.obfuscationProxyPort = "443";
+        configuration.obfuscationProxyIP = "5.6.7.8";
+        configuration.obfuscationProxyCert = "asdfasdf";
+        configuration.remoteGatewayIP = "1.2.3.4";
+        configuration.transports = createTransportsFrom(gateway, 3);
+
+        vpnConfigGenerator = new VpnConfigGenerator(generalConfig, secrets, configuration);
+        Vector<VpnProfile> vpnProfiles = vpnConfigGenerator.generateVpnProfiles();
+        assertFalse("has openvpn profile", containsKey(vpnProfiles, OPENVPN));
+        assertTrue("has no obfs4 profile", containsKey(vpnProfiles, OBFS4));
+        assertTrue("bridge is pinned one", getVpnProfile(vpnProfiles, OBFS4).getTransportType() == OBFS4 && getVpnProfile(vpnProfiles, OBFS4).mGatewayIp.equals("1.2.3.4"));
+        assertTrue("bridge is running QUIC", ((Obfs4Connection) getVpnProfile(vpnProfiles, OBFS4).mConnections[0]).getObfs4Options().transport.getProtocols()[0].equals("quic"));
+    }
     @Test
     public void testGenerateVpnProfile_obfs4hop_tcp () throws Exception {
         gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo_obfs4hop_tcp_gateways.json"))).getJSONArray("gateways").getJSONObject(2);
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 c89d08cbea66cecbab9d239232b136f1b4e22934..cb22603399866aa9237c4b575359363f4de44427 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java
@@ -203,8 +203,8 @@ public class MockHelper {
             }
 
             @Override
-            public boolean useKcp() {
-                return false;
+            public String obfsvpnTransportProtocol() {
+                return "tcp";
             }
 
             @Override
diff --git a/app/src/test/resources/multiple_pts_per_host_eip-service.json b/app/src/test/resources/multiple_pts_per_host_eip-service.json
index 2bd053d8e8f0df1106652b3a2059c010bb2b47ce..c2fec3568d2369f7d10525a370ddf4bf0e05855b 100644
--- a/app/src/test/resources/multiple_pts_per_host_eip-service.json
+++ b/app/src/test/resources/multiple_pts_per_host_eip-service.json
@@ -41,6 +41,19 @@
               "kcp"
             ],
             "type":"obfs4"
+          },
+          {
+            "options":{
+              "cert":"XXXX",
+              "iatMode":"0"
+            },
+            "ports":[
+              "4432"
+            ],
+            "protocols":[
+              "quic"
+            ],
+            "type":"obfs4"
           }
         ]
       },