diff --git a/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java b/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java index 7e104165..6d9fb267 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java +++ b/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java @@ -1309,7 +1309,7 @@ public class CaptureService extends VpnService implements Runnable { public int getVpnMTU() { return VPN_MTU; } - public int blockQuick() { return(mSettings.block_quic ? 1 : 0); } + public int getBlockQuickMode() { return mSettings.block_quic_mode.ordinal(); } // returns 1 if dumpPcapData should be called public int pcapDumpEnabled() { diff --git a/app/src/main/java/com/emanuelef/remote_capture/activities/prefs/SettingsActivity.java b/app/src/main/java/com/emanuelef/remote_capture/activities/prefs/SettingsActivity.java index 223befad..240c5266 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/activities/prefs/SettingsActivity.java +++ b/app/src/main/java/com/emanuelef/remote_capture/activities/prefs/SettingsActivity.java @@ -132,13 +132,13 @@ public class SettingsActivity extends BaseActivity implements PreferenceFragment public static class SettingsFragment extends PreferenceFragmentCompat { private SwitchPreference mTlsDecryption; - private SwitchPreference mBlockQuic; private SwitchPreference mFullPayloadEnabled; private SwitchPreference mRootCaptureEnabled; private SwitchPreference mAutoBlockPrivateDNS; private EditTextPreference mMitmproxyOpts; private DropDownPreference mIpMode; private DropDownPreference mCapInterface; + private DropDownPreference mBlockQuic; private Preference mVpnExceptions; private Preference mSocks5Settings; private Preference mDnsSettings; @@ -167,7 +167,8 @@ public class SettingsActivity extends BaseActivity implements PreferenceFragment setupSecurityPrefs(); setupOtherPrefs(); - socks5ProxyAndQuicHideShow(mTlsDecryption.isChecked(), rootCaptureEnabled()); + socks5ProxyHideShow(mTlsDecryption.isChecked(), rootCaptureEnabled()); + mBlockQuic.setVisible(!rootCaptureEnabled()); rootCaptureHideShow(rootCaptureEnabled()); Intent intent = requireActivity().getIntent(); @@ -309,7 +310,7 @@ public class SettingsActivity extends BaseActivity implements PreferenceFragment mMitmWizard.setVisible((boolean) newValue); mMitmproxyOpts.setVisible((boolean) newValue); - socks5ProxyAndQuicHideShow((boolean) newValue, rootCaptureEnabled()); + socks5ProxyHideShow((boolean) newValue, rootCaptureEnabled()); return true; }); @@ -343,9 +344,8 @@ public class SettingsActivity extends BaseActivity implements PreferenceFragment mSocks5Settings = requirePreference("socks5_settings"); } - private void socks5ProxyAndQuicHideShow(boolean tlsDecryption, boolean rootEnabled) { + private void socks5ProxyHideShow(boolean tlsDecryption, boolean rootEnabled) { mSocks5Settings.setVisible(!tlsDecryption && !rootEnabled); - mBlockQuic.setVisible(tlsDecryption && !rootEnabled); } private void setupOtherPrefs() { @@ -406,7 +406,7 @@ public class SettingsActivity extends BaseActivity implements PreferenceFragment } else { mAutoBlockPrivateDNS.setVisible(true); mBlockQuic.setVisible(true); - socks5ProxyAndQuicHideShow(mTlsDecryption.isChecked(), false); + socks5ProxyHideShow(mTlsDecryption.isChecked(), false); } mIpMode.setVisible(!enabled); diff --git a/app/src/main/java/com/emanuelef/remote_capture/model/CaptureSettings.java b/app/src/main/java/com/emanuelef/remote_capture/model/CaptureSettings.java index 5c752308..a7aa65d1 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/model/CaptureSettings.java +++ b/app/src/main/java/com/emanuelef/remote_capture/model/CaptureSettings.java @@ -26,7 +26,7 @@ public class CaptureSettings implements Serializable { public boolean root_capture; public boolean pcapdroid_trailer; public boolean full_payload; - public boolean block_quic; + public Prefs.BlockQuicMode block_quic_mode; public boolean auto_block_private_dns; public boolean pcapng_format; public String capture_interface; @@ -54,7 +54,7 @@ public class CaptureSettings implements Serializable { capture_interface = Prefs.getCaptureInterface(prefs); tls_decryption = Prefs.getTlsDecryptionEnabled(prefs); full_payload = Prefs.getFullPayloadMode(prefs); - block_quic = Prefs.blockQuic(prefs); + block_quic_mode = Prefs.getBlockQuicMode(prefs); auto_block_private_dns = Prefs.isPrivateDnsBlockingEnabled(prefs); mitmproxy_opts = Prefs.getMitmproxyOpts(prefs); pcapng_format = Prefs.isPcapngEnabled(ctx, prefs); @@ -82,7 +82,7 @@ public class CaptureSettings implements Serializable { max_dump_size = getInt(intent, Prefs.PREF_MAX_DUMP_SIZE, 0); tls_decryption = getBool(intent, Prefs.PREF_TLS_DECRYPTION_KEY, false); full_payload = false; - block_quic = getBool(intent, Prefs.PREF_BLOCK_QUIC, false); + block_quic_mode = Prefs.getBlockQuicMode(getString(intent, Prefs.PREF_BLOCK_QUIC, Prefs.BLOCK_QUIC_MODE_DEFAULT)); auto_block_private_dns = getBool(intent, Prefs.PREF_AUTO_BLOCK_PRIVATE_DNS, true); mitmproxy_opts = getString(intent, Prefs.PREF_MITMPROXY_OPTS, ""); pcapng_format = getBool(intent, Prefs.PREF_PCAPNG_ENABLED, false) && Billing.newInstance(ctx).isPurchased(Billing.PCAPNG_SKU); diff --git a/app/src/main/java/com/emanuelef/remote_capture/model/Prefs.java b/app/src/main/java/com/emanuelef/remote_capture/model/Prefs.java index 474434d3..b9b7712c 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/model/Prefs.java +++ b/app/src/main/java/com/emanuelef/remote_capture/model/Prefs.java @@ -41,6 +41,11 @@ public class Prefs { public static final String IP_MODE_BOTH = "both"; public static final String IP_MODE_DEFAULT = IP_MODE_IPV4_ONLY; + public static final String BLOCK_QUIC_MODE_NEVER = "never"; + public static final String BLOCK_QUIC_MODE_ALWAYS = "always"; + public static final String BLOCK_QUIC_MODE_TO_DECRYPT = "to_decrypt"; + public static final String BLOCK_QUIC_MODE_DEFAULT = BLOCK_QUIC_MODE_NEVER; + public static final String PAYLOAD_MODE_NONE = "none"; public static final String PAYLOAD_MODE_MINIMAL = "minimal"; public static final String PAYLOAD_MODE_FULL = "full"; @@ -83,7 +88,7 @@ public class Prefs { public static final String PREF_TLS_DECRYPTION_SETUP_DONE = "tls_decryption_setup_ok"; public static final String PREF_CA_INSTALLATION_SKIPPED = "ca_install_skipped"; public static final String PREF_FULL_PAYLOAD = "full_payload"; - public static final String PREF_BLOCK_QUIC = "block_quic"; + public static final String PREF_BLOCK_QUIC = "block_quic_mode"; public static final String PREF_AUTO_BLOCK_PRIVATE_DNS = "auto_block_private_dns"; public static final String PREF_APP_VERSION = "appver"; public static final String PREF_LOCKDOWN_VPN_NOTICE_SHOWN = "vpn_lockdown_notice"; @@ -113,6 +118,12 @@ public class Prefs { BOTH, } + public enum BlockQuicMode { + NEVER, + ALWAYS, + TO_DECRYPT + } + public enum PayloadMode { NONE, MINIMAL, @@ -136,6 +147,14 @@ public class Prefs { } } + public static BlockQuicMode getBlockQuicMode(String pref) { + switch (pref) { + case BLOCK_QUIC_MODE_ALWAYS: return BlockQuicMode.ALWAYS; + case BLOCK_QUIC_MODE_TO_DECRYPT: return BlockQuicMode.TO_DECRYPT; + default: return BlockQuicMode.NEVER; + } + } + public static PayloadMode getPayloadMode(String pref) { switch (pref) { case PAYLOAD_MODE_MINIMAL: return PayloadMode.MINIMAL; @@ -182,6 +201,7 @@ public class Prefs { public static String getSocks5Password(SharedPreferences p) { return(p.getString(PREF_SOCKS5_PASSWORD_KEY, "")); } public static String getAppFilter(SharedPreferences p) { return(p.getString(PREF_APP_FILTER, "")); } public static IpMode getIPMode(SharedPreferences p) { return(getIPMode(p.getString(PREF_IP_MODE, IP_MODE_DEFAULT))); } + public static BlockQuicMode getBlockQuicMode(SharedPreferences p) { return(getBlockQuicMode(p.getString(PREF_BLOCK_QUIC, BLOCK_QUIC_MODE_DEFAULT))); } public static boolean useEnglishLanguage(SharedPreferences p){ return("english".equals(p.getString(PREF_APP_LANGUAGE, "system")));} public static boolean isRootCaptureEnabled(SharedPreferences p) { return(Utils.isRootAvailable() && p.getBoolean(PREF_ROOT_CAPTURE, false)); } public static boolean isPcapdroidTrailerEnabled(SharedPreferences p) { return(p.getBoolean(PREF_PCAPDROID_TRAILER, false)); } @@ -202,7 +222,6 @@ public class Prefs { public static boolean startAtBoot(SharedPreferences p) { return(p.getBoolean(PREF_START_AT_BOOT, false)); } public static boolean isTLSDecryptionSetupDone(SharedPreferences p) { return(p.getBoolean(PREF_TLS_DECRYPTION_SETUP_DONE, false)); } public static boolean getFullPayloadMode(SharedPreferences p) { return(p.getBoolean(PREF_FULL_PAYLOAD, false)); } - public static boolean blockQuic(SharedPreferences p) { return(p.getBoolean(PREF_BLOCK_QUIC, false)); } public static boolean isPrivateDnsBlockingEnabled(SharedPreferences p) { return(p.getBoolean(PREF_AUTO_BLOCK_PRIVATE_DNS, true)); } public static boolean lockdownVpnNoticeShown(SharedPreferences p) { return(p.getBoolean(PREF_LOCKDOWN_VPN_NOTICE_SHOWN, false)); } public static boolean trailerNoticeShown(SharedPreferences p) { return(p.getBoolean(PREF_PCAPDROID_TRAILER_NOTICE_SHOWN, false)); } @@ -224,7 +243,7 @@ public class Prefs { "\nTLSDecryption: " + getTlsDecryptionEnabled(p) + "\nTLSSetupOk: " + isTLSDecryptionSetupDone(p) + "\nCAInstallSkipped: " + MitmAddon.isCAInstallationSkipped(ctx) + - "\nBlockQuic: " + blockQuic(p) + + "\nBlockQuic: " + getBlockQuicMode(p) + "\nRootCapture: " + isRootCaptureEnabled(p) + "\nSocks5: " + getSocks5Enabled(p) + "\nBlockPrivateDns: " + isPrivateDnsBlockingEnabled(p) + diff --git a/app/src/main/jni/core/capture_vpn.c b/app/src/main/jni/core/capture_vpn.c index 1ca852c1..e653a228 100644 --- a/app/src/main/jni/core/capture_vpn.c +++ b/app/src/main/jni/core/capture_vpn.c @@ -385,10 +385,14 @@ static bool should_proxify(pcapdroid_t *pd, const zdtun_5tuple_t *tuple, pd_conn /* ******************************************************* */ void vpn_process_ndpi(pcapdroid_t *pd, const zdtun_5tuple_t *tuple, pd_conn_t *data) { - if(pd->vpn.block_quic && (data->l7proto == NDPI_PROTOCOL_QUIC) && - pd->tls_decryption.enabled && matches_decryption_whitelist(pd, tuple, data)) { - data->blacklisted_internal = true; - data->to_block = true; + if(data->l7proto == NDPI_PROTOCOL_QUIC) { + block_quic_mode_t block_mode = pd->vpn.block_quic_mode; + + if ((block_mode == BLOCK_QUIC_MODE_ALWAYS) || + ((block_mode == BLOCK_QUIC_MODE_TO_DECRYPT) && matches_decryption_whitelist(pd, tuple, data))) { + data->blacklisted_internal = true; + data->to_block = true; + } } if(block_private_dns && !data->to_block && @@ -449,7 +453,7 @@ int run_vpn(pcapdroid_t *pd) { #if ANDROID pd->vpn.resolver = init_uid_resolver(pd->sdk_ver, pd->env, pd->capture_service); pd->vpn.known_dns_servers = blacklist_init(); - pd->vpn.block_quic = getIntPref(pd->env, pd->capture_service, "blockQuick"); + pd->vpn.block_quic_mode = getIntPref(pd->env, pd->capture_service, "getBlockQuickMode"); pd->vpn.ipv4.enabled = (bool) getIntPref(pd->env, pd->capture_service, "getIPv4Enabled"); pd->vpn.ipv4.dns_server = getIPv4Pref(pd->env, pd->capture_service, "getDnsServer"); diff --git a/app/src/main/jni/core/pcapdroid.h b/app/src/main/jni/core/pcapdroid.h index 045b3078..c90badb0 100644 --- a/app/src/main/jni/core/pcapdroid.h +++ b/app/src/main/jni/core/pcapdroid.h @@ -65,6 +65,13 @@ typedef enum { PAYLOAD_MODE_FULL } payload_mode_t; +// NOTE: sync with Prefs.BlockQuicMode +typedef enum { + BLOCK_QUIC_MODE_NEVER = 0, + BLOCK_QUIC_MODE_ALWAYS, + BLOCK_QUIC_MODE_TO_DECRYPT +} block_quic_mode_t; + typedef struct { jint incr_id; // an incremental number which identifies a specific connection @@ -205,7 +212,7 @@ typedef struct pcapdroid { union { struct { int tunfd; - bool block_quic; + block_quic_mode_t block_quic_mode; blacklist_t *known_dns_servers; uid_resolver_t *resolver; diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 122ce756..d33152e2 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -49,4 +49,15 @@ @string/theme_light @string/theme_dark + + + never + always + to_decrypt + + + @string/never + @string/always + @string/for_connections_to_decrypt + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8e21871a..7c7dc3ad 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -497,4 +497,7 @@ redirected This connection has been redirected due to a port mapping rule How to use DoH / DNSCrypt with PCAPdroid + Never + Always + Only for connections to decrypt diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml index 38d2865e..3923a96f 100644 --- a/app/src/main/res/xml/root_preferences.xml +++ b/app/src/main/res/xml/root_preferences.xml @@ -94,12 +94,14 @@ app:summary="@string/pcapng_format_summary" app:defaultValue="true" /> - + app:defaultValue="never" + app:useSimpleSummaryProvider="true" />