mirror of
https://github.com/emanuele-f/PCAPdroid.git
synced 2026-05-08 21:12:26 +00:00
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:
@@ -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)); }
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/* ******************************************************* */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user