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 c97d2244..b9cce905 100644
--- a/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java
+++ b/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java
@@ -160,9 +160,6 @@ public class CaptureService extends VpnService implements Runnable {
* Max estimated memory usage: less than 4 MB (+8 MB with payload mode minimal). */
public static final int CONNECTIONS_LOG_SIZE = 8192;
- public static final String FALLBACK_DNS_SERVER = "8.8.8.8";
- public static final String IPV6_DNS_SERVER = "2001:4860:4860::8888";
-
/* The IP address of the virtual network interface */
public static final String VPN_IP_ADDRESS = "10.215.173.1";
public static final String VPN_IP6_ADDRESS = "fd00:2:fd00:1:fd00:1:fd00:1";
@@ -259,7 +256,8 @@ public class CaptureService extends VpnService implements Runnable {
mSettings.root_capture = false;
// Retrieve DNS server
- dns_server = FALLBACK_DNS_SERVER;
+ String fallbackDnsV4 = Prefs.getDnsServerV4(mPrefs);
+ dns_server = fallbackDnsV4;
mBlockPrivateDns = false;
mStrictDnsNoticeShown = false;
mDnsEncrypted = false;
@@ -284,13 +282,16 @@ public class CaptureService extends VpnService implements Runnable {
if(net != null) {
handleLinkProperties(cm.getLinkProperties(net));
- dns_server = Utils.getDnsServer(cm, net);
- if(dns_server == null)
- dns_server = FALLBACK_DNS_SERVER;
- else {
- mMonitoredNetwork = net.getNetworkHandle();
- registerNetworkCallbacks();
- }
+ if(Prefs.useSystemDns(mPrefs) || mSettings.root_capture) {
+ dns_server = Utils.getDnsServer(cm, net);
+ if (dns_server == null)
+ dns_server = fallbackDnsV4;
+ else {
+ mMonitoredNetwork = net.getNetworkHandle();
+ registerNetworkCallbacks();
+ }
+ } else
+ dns_server = fallbackDnsV4;
}
}
@@ -405,7 +406,7 @@ public class CaptureService extends VpnService implements Runnable {
builder.addRoute("2000::", 3);
try {
- builder.addDnsServer(InetAddress.getByName(IPV6_DNS_SERVER));
+ builder.addDnsServer(InetAddress.getByName(Prefs.getDnsServerV6(mPrefs)));
} catch (UnknownHostException e) {
Log.w(TAG, "Could not set IPv6 DNS server");
}
@@ -688,6 +689,7 @@ public class CaptureService extends VpnService implements Runnable {
if(mNetworkCallback != null)
return;
+ String fallbackDns = Prefs.getDnsServerV4(mPrefs);
ConnectivityManager cm = (ConnectivityManager) getSystemService(Service.CONNECTIVITY_SERVICE);
mNetworkCallback = new ConnectivityManager.NetworkCallback() {
@Override
@@ -697,8 +699,8 @@ public class CaptureService extends VpnService implements Runnable {
// If the network goes offline we roll back to the fallback DNS server to
// avoid possibly using a private IP DNS server not reachable anymore
if(network.getNetworkHandle() == mMonitoredNetwork) {
- Log.i(TAG, "Main network " + network + " lost, using fallback DNS " + FALLBACK_DNS_SERVER);
- dns_server = FALLBACK_DNS_SERVER;
+ Log.i(TAG, "Main network " + network + " lost, using fallback DNS " + fallbackDns);
+ dns_server = fallbackDns;
mMonitoredNetwork = 0;
unregisterNetworkCallbacks();
@@ -728,7 +730,7 @@ public class CaptureService extends VpnService implements Runnable {
e.printStackTrace();
Log.w(TAG, "registerNetworkCallback failed, DNS server detection disabled");
- dns_server = FALLBACK_DNS_SERVER;
+ dns_server = fallbackDns;
mNetworkCallback = null;
}
}
@@ -1195,7 +1197,7 @@ public class CaptureService extends VpnService implements Runnable {
return(dns_server);
}
- public String getIpv6DnsServer() { return(IPV6_DNS_SERVER); }
+ public String getIpv6DnsServer() { return(Prefs.getDnsServerV4(mPrefs)); }
public int getSocks5Enabled() { return mSocks5Enabled ? 1 : 0; }
diff --git a/app/src/main/java/com/emanuelef/remote_capture/Utils.java b/app/src/main/java/com/emanuelef/remote_capture/Utils.java
index 230a97ce..a98221c2 100644
--- a/app/src/main/java/com/emanuelef/remote_capture/Utils.java
+++ b/app/src/main/java/com/emanuelef/remote_capture/Utils.java
@@ -127,6 +127,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Random;
import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@@ -1432,6 +1433,19 @@ public class Utils {
}
}
+ // https://mkyong.com/regular-expressions/how-to-validate-ip-address-with-regular-expression/
+ private static final Pattern IPV4_PATTERN = Pattern.compile(
+ "^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\\.(?!$)|$)){4}$");
+
+ public static boolean validateIpv4Address(String s) {
+ Matcher matcher = IPV4_PATTERN.matcher(s);
+ return matcher.matches();
+ }
+
+ public static boolean validateIpv6Address(String s) {
+ return validateIpAddress(s) && !validateIpv4Address(s);
+ }
+
// rough validation
public static boolean validateHost(String host) {
int len = host.length();
diff --git a/app/src/main/java/com/emanuelef/remote_capture/activities/SettingsActivity.java b/app/src/main/java/com/emanuelef/remote_capture/activities/SettingsActivity.java
index c575e1fb..2712c4f7 100644
--- a/app/src/main/java/com/emanuelef/remote_capture/activities/SettingsActivity.java
+++ b/app/src/main/java/com/emanuelef/remote_capture/activities/SettingsActivity.java
@@ -44,6 +44,7 @@ import com.emanuelef.remote_capture.Log;
import com.emanuelef.remote_capture.PCAPdroid;
import com.emanuelef.remote_capture.Utils;
import com.emanuelef.remote_capture.MitmAddon;
+import com.emanuelef.remote_capture.fragments.DnsSettings;
import com.emanuelef.remote_capture.fragments.GeoipSettings;
import com.emanuelef.remote_capture.model.Prefs;
import com.emanuelef.remote_capture.R;
@@ -83,6 +84,9 @@ public class SettingsActivity extends BaseActivity implements PreferenceFragment
if(prefKey.equals("geolocation")) {
targetFragment = new GeoipSettings();
setTitle(R.string.geolocation);
+ } else if(prefKey.equals("dns_settings")) {
+ targetFragment = new DnsSettings();
+ setTitle(R.string.dns_servers);
}
if(targetFragment != null) {
@@ -131,6 +135,7 @@ public class SettingsActivity extends BaseActivity implements PreferenceFragment
private DropDownPreference mIpMode;
private DropDownPreference mCapInterface;
private Preference mVpnExceptions;
+ private Preference mDnsSettings;
private Preference mPortMapping;
private Preference mMitmWizard;
private SwitchPreference mMalwareDetectionEnabled;
@@ -238,21 +243,25 @@ public class SettingsActivity extends BaseActivity implements PreferenceFragment
private void setupCapturePrefs() {
mCapInterface = requirePreference(Prefs.PREF_CAPTURE_INTERFACE);
- mVpnExceptions = requirePreference(Prefs.PREF_VPN_EXCEPTIONS);
- mPortMapping = requirePreference(Prefs.PREF_PORT_MAPPING);
refreshInterfaces();
+ mRootCaptureEnabled = requirePreference(Prefs.PREF_ROOT_CAPTURE);
+ if(Utils.isRootAvailable()) {
+ mRootCaptureEnabled.setOnPreferenceChangeListener((preference, newValue) -> {
+ rootCaptureHideShow((Boolean) newValue);
+ checkDecrpytionWithRoot((Boolean) newValue, mTlsDecryption.isChecked());
+ return true;
+ });
+ } else
+ mRootCaptureEnabled.setVisible(false);
+
+ mDnsSettings = requirePreference("dns_settings");;
+ mVpnExceptions = requirePreference(Prefs.PREF_VPN_EXCEPTIONS);
mVpnExceptions.setOnPreferenceClickListener(preference -> {
Intent intent = new Intent(requireContext(), VpnExemptionsActivity.class);
startActivity(intent);
return true;
});
-
- mPortMapping.setOnPreferenceClickListener(preference -> {
- Intent intent = new Intent(requireContext(), PortMapActivity.class);
- startActivity(intent);
- return true;
- });
}
private void setupSecurityPrefs() {
@@ -351,23 +360,18 @@ public class SettingsActivity extends BaseActivity implements PreferenceFragment
});
DropDownPreference appTheme = requirePreference(Prefs.PREF_APP_THEME);
-
appTheme.setOnPreferenceChangeListener((preference, newValue) -> {
Utils.setAppTheme(newValue.toString());
return true;
});
- mRootCaptureEnabled = requirePreference(Prefs.PREF_ROOT_CAPTURE);
-
- if(Utils.isRootAvailable()) {
- mRootCaptureEnabled.setOnPreferenceChangeListener((preference, newValue) -> {
- rootCaptureHideShow((Boolean) newValue);
- checkDecrpytionWithRoot((Boolean) newValue, mTlsDecryption.isChecked());
- return true;
- });
- } else
- mRootCaptureEnabled.setVisible(false);
+ mPortMapping = requirePreference(Prefs.PREF_PORT_MAPPING);
+ mPortMapping.setOnPreferenceClickListener(preference -> {
+ Intent intent = new Intent(requireContext(), PortMapActivity.class);
+ startActivity(intent);
+ return true;
+ });
mIpMode = requirePreference(Prefs.PREF_IP_MODE);
@@ -398,6 +402,7 @@ public class SettingsActivity extends BaseActivity implements PreferenceFragment
mIpMode.setVisible(!enabled);
mCapInterface.setVisible(enabled);
mVpnExceptions.setVisible(!enabled);
+ mDnsSettings.setVisible(!enabled);
mPortMapping.setVisible(!enabled);
}
diff --git a/app/src/main/java/com/emanuelef/remote_capture/fragments/DnsSettings.java b/app/src/main/java/com/emanuelef/remote_capture/fragments/DnsSettings.java
new file mode 100644
index 00000000..8021e4c1
--- /dev/null
+++ b/app/src/main/java/com/emanuelef/remote_capture/fragments/DnsSettings.java
@@ -0,0 +1,44 @@
+/*
+ * This file is part of PCAPdroid.
+ *
+ * PCAPdroid is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PCAPdroid is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with PCAPdroid. If not, see .
+ *
+ * Copyright 2020-22 - Emanuele Faranda
+ */
+
+package com.emanuelef.remote_capture.fragments;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.preference.EditTextPreference;
+import androidx.preference.PreferenceFragmentCompat;
+
+import com.emanuelef.remote_capture.R;
+import com.emanuelef.remote_capture.Utils;
+import com.emanuelef.remote_capture.model.Prefs;
+
+import java.util.Objects;
+
+public class DnsSettings extends PreferenceFragmentCompat {
+ @Override
+ public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
+ setPreferencesFromResource(R.xml.dns_preferences, rootKey);
+
+ EditTextPreference p1 = Objects.requireNonNull(findPreference(Prefs.PREF_DNS_SERVER_V4));
+ p1.setOnPreferenceChangeListener((preference, newValue) -> Utils.validateIpv4Address(newValue.toString()));
+
+ EditTextPreference p2 = Objects.requireNonNull(findPreference(Prefs.PREF_DNS_SERVER_V6));
+ p2.setOnPreferenceChangeListener((preference, newValue) -> Utils.validateIpv6Address(newValue.toString()));
+ }
+}
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 99e9c022..cce9b765 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
@@ -91,6 +91,9 @@ public class Prefs {
public static final String PREF_PAYLOAD_NOTICE_ACK = "payload_notice";
public static final String PREF_REMOTE_COLLECTOR_ACK = "remote_collector_notice";
public static final String PREF_MITMPROXY_OPTS = "mitmproxy_opts";
+ public static final String PREF_DNS_SERVER_V4 = "dns_v4";
+ public static final String PREF_DNS_SERVER_V6 = "dns_v6";
+ public static final String PREF_USE_SYSTEM_DNS = "system_dns";
public enum DumpMode {
NONE,
@@ -192,6 +195,9 @@ public class Prefs {
public static boolean isFirewallWhitelistInitialized(SharedPreferences p) { return(p.getInt(PREF_FIREWALL_WHITELIST_INIT_VER, 0) == FIREWALL_WHITELIST_INIT_VER); }
public static String getMitmproxyOpts(SharedPreferences p) { return(p.getString(PREF_MITMPROXY_OPTS, "")); }
public static boolean isPortMappingEnabled(SharedPreferences p) { return(p.getBoolean(PREF_PORT_MAPPING_ENABLED, true)); }
+ public static boolean useSystemDns(SharedPreferences p) { return(p.getBoolean(PREF_USE_SYSTEM_DNS, true)); }
+ public static String getDnsServerV4(SharedPreferences p) { return(p.getString(PREF_DNS_SERVER_V4, "1.1.1.1")); }
+ public static String getDnsServerV6(SharedPreferences p) { return(p.getString(PREF_DNS_SERVER_V6, "2606:4700:4700::1111")); }
public static String asString(Context ctx) {
SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(ctx);
diff --git a/app/src/main/jni/core/capture_vpn.c b/app/src/main/jni/core/capture_vpn.c
index bbc32e2a..df5e7ffe 100644
--- a/app/src/main/jni/core/capture_vpn.c
+++ b/app/src/main/jni/core/capture_vpn.c
@@ -386,6 +386,8 @@ static void load_dns_servers(pcapdroid_t *pd) {
blacklist_add_ipstr(pd->vpn.known_dns_servers, "2001:4860:4860::8844");
blacklist_add_ipstr(pd->vpn.known_dns_servers, "2606:4700:4700::64");
blacklist_add_ipstr(pd->vpn.known_dns_servers, "2606:4700:4700::6400");
+ blacklist_add_ipstr(pd->vpn.known_dns_servers, "2606:4700:4700::1111");
+ blacklist_add_ipstr(pd->vpn.known_dns_servers, "2606:4700:4700::1001");
// Domains (only private DNS)
// https://help.firewalla.com/hc/en-us/articles/360060661873-Dealing-DNS-over-HTTPS-and-DNS-over-TLS-on-your-network
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 41da9527..bf0fe449 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -436,4 +436,10 @@
Delete the selected items?
IP address
Rule already defined
+ DNS servers
+ Configure the DNS servers to use during the capture
+ IPv4 DNS server
+ IPv6 DNS server
+ Use system DNS
+ Use the system DNS servers if possible
diff --git a/app/src/main/res/xml/dns_preferences.xml b/app/src/main/res/xml/dns_preferences.xml
new file mode 100644
index 00000000..710ca74d
--- /dev/null
+++ b/app/src/main/res/xml/dns_preferences.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml
index a4e3ae53..fa91d404 100644
--- a/app/src/main/res/xml/root_preferences.xml
+++ b/app/src/main/res/xml/root_preferences.xml
@@ -113,12 +113,6 @@
app:iconSpaceReserved="false"
app:defaultValue="8050"
app:useSimpleSummaryProvider="true" />
-
-
@@ -142,6 +136,13 @@
app:summary="@string/vpn_exemptions_summary"
app:iconSpaceReserved="false" />
+
+
+
+
-
+ android:summary="@string/control_permissions_summary" />