Add ability to block QUIC when decrypting TLS

This can force apps to fallback to TLS, whose decryption is supported.

https://www.ietf.org/archive/id/draft-ietf-quic-applicability-09.html#section-2

Closes #213
This commit is contained in:
emanuele-f
2022-05-27 15:06:36 +02:00
parent f0d53ed671
commit 557690da1a
10 changed files with 32 additions and 2 deletions
@@ -989,6 +989,8 @@ public class CaptureService extends VpnService implements Runnable {
public int getVpnMTU() { return VPN_MTU; }
public int blockQuick() { return(mSettings.block_quic ? 1 : 0); }
public int getOwnAppUid() {
AppDescriptor app = AppsResolver.resolve(getPackageManager(), BuildConfig.APPLICATION_ID, 0);
@@ -122,6 +122,7 @@ public class SettingsActivity extends BaseActivity implements PreferenceFragment
public static class SettingsFragment extends PreferenceFragmentCompat {
private SwitchPreference mSocks5Enabled;
private SwitchPreference mTlsDecryption;
private SwitchPreference mBlockQuic;
private SwitchPreference mFullPayloadEnabled;
private SwitchPreference mRootCaptureEnabled;
private EditTextPreference mSocks5ProxyIp;
@@ -150,6 +151,7 @@ public class SettingsActivity extends BaseActivity implements PreferenceFragment
fullPayloadHideShow(mTlsDecryption.isChecked());
socks5ProxyHideShow(mTlsDecryption.isChecked(), mSocks5Enabled.isChecked());
mBlockQuic.setVisible(mTlsDecryption.isChecked());
rootCaptureHideShow(Utils.isRootAvailable() && mRootCaptureEnabled.isChecked());
Intent intent = requireActivity().getIntent();
@@ -262,11 +264,13 @@ public class SettingsActivity extends BaseActivity implements PreferenceFragment
}
fullPayloadHideShow((boolean) newValue);
mBlockQuic.setVisible((boolean) newValue);
socks5ProxyHideShow((boolean) newValue, mSocks5Enabled.isChecked());
return true;
});
mFullPayloadEnabled = requirePreference(Prefs.PREF_FULL_PAYLOAD);
mBlockQuic = requirePreference(Prefs.PREF_BLOCK_QUIC);
mSocks5Enabled = requirePreference(Prefs.PREF_SOCKS5_ENABLED_KEY);
mSocks5Enabled.setOnPreferenceChangeListener((preference, newValue) -> {
@@ -366,9 +370,11 @@ public class SettingsActivity extends BaseActivity implements PreferenceFragment
mSocks5ProxyPort.setVisible(false);
mTlsHelp.setVisible(false);
mFullPayloadEnabled.setVisible(true);
mBlockQuic.setVisible(false);
} else {
mTlsDecryption.setVisible(true);
fullPayloadHideShow(mTlsDecryption.isChecked());
mBlockQuic.setVisible(mTlsDecryption.isChecked());
socks5ProxyHideShow(mTlsDecryption.isChecked(), mSocks5Enabled.isChecked());
}
@@ -20,6 +20,7 @@ public class CaptureSettings implements Serializable {
public boolean root_capture;
public boolean pcapdroid_trailer;
public boolean full_payload;
public boolean block_quic;
public String capture_interface;
public String pcap_uri;
public int snaplen = 0;
@@ -42,6 +43,7 @@ public class CaptureSettings implements Serializable {
pcap_uri = Prefs.getPCAPUri(prefs);
tls_decryption = Prefs.getTlsDecryptionEnabled(prefs);
full_payload = Prefs.getFullPayloadMode(prefs);
block_quic = Prefs.blockQuic(prefs);
}
public CaptureSettings(Intent intent) {
@@ -63,6 +65,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);
}
private static String getString(Intent intent, String key, String def_value) {
@@ -64,6 +64,7 @@ public class Prefs {
public static final String PREF_SOCKS5_ENABLED_KEY = "socks5_enabled";
public static final String PREF_TLS_DECRYPTION_SETUP_DONE = "tls_decryption_setup_ok";
public static final String PREF_FULL_PAYLOAD = "full_payload";
public static final String PREF_BLOCK_QUIC = "block_quic";
public enum DumpMode {
NONE,
@@ -123,4 +124,5 @@ public class Prefs {
public static String getPCAPUri(SharedPreferences p) { return(p.getString(PREF_PCAP_URI, "")); }
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)); }
}
+2 -1
View File
@@ -397,6 +397,7 @@ int run_vpn(pcapdroid_t *pd) {
pd->vpn.dns_server = getIPv4Pref(pd->env, pd->capture_service, "getDnsServer");
pd->vpn.resolver = init_uid_resolver(pd->sdk_ver, pd->env, pd->capture_service);
pd->vpn.known_dns_servers = ndpi_ptree_create();
pd->vpn.block_quic = getIntPref(pd->env, pd->capture_service, "blockQuick");
#endif
zdtun_callbacks_t callbacks = {
@@ -530,7 +531,7 @@ int run_vpn(pcapdroid_t *pd) {
pd_process_packet(pd, &pkt, true, tuple, data, get_pkt_timestamp(pd, &tv), &pctx);
if(data->sent_pkts == 0) {
// Newly created connections
data->blacklisted_internal = !check_dns_req_allowed(pd, conn, &pctx);
data->blacklisted_internal |= !check_dns_req_allowed(pd, conn, &pctx);
data->to_block |= data->blacklisted_internal;
if(data->to_block) {
+5
View File
@@ -503,6 +503,11 @@ static void process_ndpi_data(pcapdroid_t *pd, const zdtun_5tuple_t *tuple, pd_c
check_blacklisted_domain(pd, data, tuple);
data->update_type |= CONN_UPDATE_INFO;
}
if(!pd->root_capture && pd->vpn.block_quic && (data->l7proto == NDPI_PROTOCOL_QUIC)) {
data->blacklisted_internal = true;
data->to_block |= data->blacklisted_internal;
}
}
/* ******************************************************* */
+1
View File
@@ -203,6 +203,7 @@ typedef struct pcapdroid {
union {
struct {
int tunfd;
bool block_quic;
uint32_t dns_server;
uint32_t internal_dns;
uint32_t internal_ipv4;
+2
View File
@@ -340,4 +340,6 @@
<string name="netd_block_missed">This connection was initiated by netd so it could not be blocked</string>
<string name="firewall_summary">Block internet access to apps, configure rules for specific domains and IP addresses. Only works with the non-root capture</string>
<string name="no_root_firewall">No-root firewall</string>
<string name="block_quick">Block QUIC</string>
<string name="block_quick_summary">Block QUIC connections to possibly fallback to TLS. Some apps may stop working</string>
</resources>
@@ -52,6 +52,13 @@
app:summary="@string/tls_decryption_summary"
app:defaultValue="false" />
<SwitchPreference
app:key="block_quic"
app:title="@string/block_quick"
app:iconSpaceReserved="false"
app:summary="@string/block_quick_summary"
app:defaultValue="false" />
<SwitchPreference
app:key="full_payload"
app:title="@string/full_payload"
+2 -1
View File
@@ -87,7 +87,8 @@ As shown above, the capture settings can be specified by using intent extras. Th
| snaplen | int | 43 | max size in bytes for each individual packet in the PCAP dump |
| max_pkts_per_flow | int | 43 | only dump the first max_pkts_per_flow packets per flow |
| max_dump_size | int | 43 | max size in bytes for the PCAP dump |
| tls_decryption | bool | - | true to enable the built-in TLS decryption |
| tls_decryption | bool | 49 | true to enable the built-in TLS decryption |
| block_quic | bool | 51 | true to block QUIC traffic |
The `Ver` column indicates the minimum PCAPdroid version required to use the given parameter. The PCAPdroid version can be queried via the `get_status` action as explained below.