From 74391b14137efa7a828f58e8a185abea34034a27 Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 13:52:09 -0700 Subject: [PATCH 001/108] Add root DNS hijacker daemon --- .gitignore | 2 + .../main/assets/dnsd/arm64-v8a/afwall_dnsd | Bin 0 -> 19816 bytes .../main/assets/dnsd/armeabi-v7a/afwall_dnsd | Bin 0 -> 14960 bytes app/src/main/assets/dnsd/x86/afwall_dnsd | Bin 0 -> 18240 bytes app/src/main/assets/dnsd/x86_64/afwall_dnsd | Bin 0 -> 20224 bytes .../main/java/dev/ukanth/ufirewall/Api.java | 9 + .../ufirewall/dns/DnsHijackManager.java | 289 +++++ .../preferences/RulesPreferenceFragment.java | 28 + .../java/dev/ukanth/ufirewall/util/G.java | 78 ++ app/src/main/res/values/strings.xml | 25 + app/src/main/res/xml/rules_preferences.xml | 80 ++ dnsdaemon/jni/Android.mk | 10 + dnsdaemon/jni/Application.mk | 3 + dnsdaemon/jni/afwall_dnsd.c | 1072 +++++++++++++++++ 14 files changed, 1596 insertions(+) create mode 100755 app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd create mode 100755 app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd create mode 100755 app/src/main/assets/dnsd/x86/afwall_dnsd create mode 100755 app/src/main/assets/dnsd/x86_64/afwall_dnsd create mode 100644 app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java create mode 100644 dnsdaemon/jni/Android.mk create mode 100644 dnsdaemon/jni/Application.mk create mode 100644 dnsdaemon/jni/afwall_dnsd.c diff --git a/.gitignore b/.gitignore index 3c70068df..899b6e6cf 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,8 @@ proguard/ # native binaries libs/ obj/ +dnsdaemon/libs/ +dnsdaemon/obj/ # IDE related .idea/ diff --git a/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd b/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd new file mode 100755 index 0000000000000000000000000000000000000000..a73ef33e038077ede80d6e3040cbd1e5b8a8486a GIT binary patch literal 19816 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 literal 0 HcmV?d00001 diff --git a/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd b/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd new file mode 100755 index 0000000000000000000000000000000000000000..69c915f58ec9745886f96465ce1501c8dd6fa421 GIT binary patch literal 14960 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 V9m$Y84Wc@Poda@W7=VZ6{x806PImwR literal 0 HcmV?d00001 diff --git a/app/src/main/assets/dnsd/x86/afwall_dnsd b/app/src/main/assets/dnsd/x86/afwall_dnsd new file mode 100755 index 0000000000000000000000000000000000000000..53b376283ed7bc40c6edc5e77b06ed334ba74130 GIT binary patch literal 18240 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 literal 0 HcmV?d00001 diff --git a/app/src/main/assets/dnsd/x86_64/afwall_dnsd b/app/src/main/assets/dnsd/x86_64/afwall_dnsd new file mode 100755 index 0000000000000000000000000000000000000000..c043d959e9d57a7c9ae3a12f4b5a896c656d753c GIT binary patch literal 20224 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 commands, boolean ipv6) { + appendPurgeRules(commands, ipv6); + if (!G.enableDnsHijack()) { + if (!ipv6) { + appendStopCommand(context, commands); + } + return; + } + + // Do not queue NAT redirects unless the daemon and supervisor are ready; otherwise DNS + // capture would turn a preparation failure into device-wide DNS loss. + if (!prepareDaemon(context)) { + ApplicationErrorLog.add(context, "DNS hijacker was enabled but daemon files could not be prepared; redirect rules were not queued"); + return; + } + + if (!ipv6) { + ApplicationErrorLog.add(context, "DNS hijacker enabled; daemon start and DNS redirect rules queued"); + commands.add("#LITERAL# " + shellQuote(supervisorPath(context)) + " start"); + } + appendRedirectRules(commands, ipv6); + } + + public static void appendPurgeCommands(Context context, List commands, boolean ipv6) { + appendPurgeRules(commands, ipv6); + if (!ipv6) { + appendStopCommand(context, commands); + } + } + + public static void requestReload(Context context) { + if (context == null) { + return; + } + if (!prepareDaemon(context)) { + return; + } + List commands = new java.util.ArrayList<>(); + commands.add(shellQuote(supervisorPath(context)) + " reload"); + new dev.ukanth.ufirewall.service.RootCommand() + .setLogging(true) + .run(context.getApplicationContext(), commands); + } + + private static void appendRedirectRules(List commands, boolean ipv6) { + int port = G.dnsHijackPort(DEFAULT_PORT); + String chain = ipv6 ? CHAIN_V6 : CHAIN_V4; + String preChain = ipv6 ? CHAIN_V6_PRE : CHAIN_V4_PRE; + + commands.add("#NOCHK# -t nat -N " + chain); + commands.add("#NOCHK# -t nat -N " + preChain); + commands.add("#NOCHK# -t nat -F " + chain); + commands.add("#NOCHK# -t nat -F " + preChain); + + commands.add("#NOCHK# -t nat -A " + chain + " -o lo -j RETURN"); + commands.add("#NOCHK# -t nat -A " + chain + " -m owner --uid-owner 0 -j RETURN"); + commands.add("#NOCHK# -t nat -A " + chain + " -p udp --dport 53 -j REDIRECT --to-ports " + port); + commands.add("#NOCHK# -t nat -A " + chain + " -p tcp --dport 53 -j REDIRECT --to-ports " + port); + + commands.add("#NOCHK# -t nat -A " + preChain + " -i lo -j RETURN"); + commands.add("#NOCHK# -t nat -A " + preChain + " -p udp --dport 53 -j REDIRECT --to-ports " + port); + commands.add("#NOCHK# -t nat -A " + preChain + " -p tcp --dport 53 -j REDIRECT --to-ports " + port); + + commands.add("#NOCHK# -t nat -I OUTPUT 1 -p udp --dport 53 -j " + chain); + commands.add("#NOCHK# -t nat -I OUTPUT 1 -p tcp --dport 53 -j " + chain); + commands.add("#NOCHK# -t nat -I PREROUTING 1 -p udp --dport 53 -j " + preChain); + commands.add("#NOCHK# -t nat -I PREROUTING 1 -p tcp --dport 53 -j " + preChain); + } + + private static void appendPurgeRules(List commands, boolean ipv6) { + String chain = ipv6 ? CHAIN_V6 : CHAIN_V4; + String preChain = ipv6 ? CHAIN_V6_PRE : CHAIN_V4_PRE; + + commands.add("#NOCHK# -t nat -D OUTPUT -p udp --dport 53 -j " + chain); + commands.add("#NOCHK# -t nat -D OUTPUT -p tcp --dport 53 -j " + chain); + commands.add("#NOCHK# -t nat -D PREROUTING -p udp --dport 53 -j " + preChain); + commands.add("#NOCHK# -t nat -D PREROUTING -p tcp --dport 53 -j " + preChain); + commands.add("#NOCHK# -t nat -F " + chain); + commands.add("#NOCHK# -t nat -F " + preChain); + commands.add("#NOCHK# -t nat -X " + chain); + commands.add("#NOCHK# -t nat -X " + preChain); + } + + private static void appendStopCommand(Context context, List commands) { + if (context == null) { + return; + } + File supervisor = new File(workDir(context), SUPERVISOR); + if (supervisor.exists()) { + commands.add("#LITERAL# " + shellQuote(supervisor.getAbsolutePath()) + " stop || true"); + } + } + + private static boolean prepareDaemon(Context context) { + if (context == null) { + return false; + } + + try { + File dir = workDir(context); + if (!dir.exists() && !dir.mkdirs()) { + throw new IOException("Unable to create " + dir.getAbsolutePath()); + } + + File daemon = new File(dir, DAEMON_NAME); + copyDaemonAsset(context, daemon); + if (!daemon.setExecutable(true, false)) { + Log.w(TAG, "Unable to mark daemon executable from app context; root start will chmod it"); + } + + writeText(new File(dir, CONF), buildConfig(context)); + File supervisor = new File(dir, SUPERVISOR); + writeText(supervisor, buildSupervisorScript(dir, daemon)); + if (!supervisor.setExecutable(true, false)) { + Log.w(TAG, "Unable to mark supervisor executable from app context; root start will chmod it"); + } + return true; + } catch (IOException e) { + Log.e(TAG, "Unable to prepare DNS daemon", e); + ApplicationErrorLog.add(context, "Unable to prepare DNS hijacker daemon: " + e.getMessage()); + return false; + } + } + + private static void copyDaemonAsset(Context context, File target) throws IOException { + String abi = selectAbi(); + String asset = "dnsd/" + abi + "/" + DAEMON_NAME; + try (InputStream input = context.getAssets().open(asset); + FileOutputStream output = new FileOutputStream(target, false)) { + byte[] buffer = new byte[8192]; + int read; + while ((read = input.read(buffer)) != -1) { + output.write(buffer, 0, read); + } + } + } + + private static String buildConfig(Context context) { + File dir = workDir(context); + StringBuilder config = new StringBuilder(); + config.append("port=").append(G.dnsHijackPort(DEFAULT_PORT)).append('\n'); + config.append("control_socket=").append(new File(dir, SOCKET).getAbsolutePath()).append('\n'); + config.append("pid_file=").append(new File(dir, PID).getAbsolutePath()).append('\n'); + config.append("log_file=").append(new File(dir, QUERY_LOG).getAbsolutePath()).append('\n'); + config.append("fail_open=").append(G.dnsHijackFailOpen() ? "1" : "0").append('\n'); + config.append("strict_mode=").append(G.dnsHijackStrictMode() ? "1" : "0").append('\n'); + config.append("timeout_ms=").append(G.dnsHijackTimeoutMs()).append('\n'); + + appendConfigEntries(config, "upstream", G.dnsHijackUpstreams()); + appendConfigEntries(config, "allow_exact", G.dnsHijackAllowExact()); + appendConfigEntries(config, "allow_suffix", G.dnsHijackAllowSuffix()); + appendConfigEntries(config, "block_exact", G.dnsHijackBlockExact()); + appendConfigEntries(config, "block_suffix", G.dnsHijackBlockSuffix()); + appendConfigEntries(config, "allow_regex", G.dnsHijackAllowRegex()); + appendConfigEntries(config, "block_regex", G.dnsHijackBlockRegex()); + + return config.toString(); + } + + private static void appendConfigEntries(StringBuilder config, String key, String raw) { + if (raw == null) { + return; + } + String[] lines = raw.split("[\\r\\n,]+"); + for (String line : lines) { + String value = line == null ? "" : line.trim(); + if (value.isEmpty() || value.startsWith("#")) { + continue; + } + config.append(key).append('=').append(value.toLowerCase(Locale.US)).append('\n'); + } + } + + private static String buildSupervisorScript(File dir, File daemon) { + String marker = new File(dir, ENABLED_MARKER).getAbsolutePath(); + String config = new File(dir, CONF).getAbsolutePath(); + String pid = new File(dir, PID).getAbsolutePath(); + String log = new File(dir, SUPERVISOR_LOG).getAbsolutePath(); + + return "#!/system/bin/sh\n" + + "DIR=" + shellQuote(dir.getAbsolutePath()) + "\n" + + "DAEMON=" + shellQuote(daemon.getAbsolutePath()) + "\n" + + "CONF=" + shellQuote(config) + "\n" + + "PID=" + shellQuote(pid) + "\n" + + "MARKER=" + shellQuote(marker) + "\n" + + "LOG=" + shellQuote(log) + "\n" + + "is_running() {\n" + + " [ -f \"$PID\" ] && kill -0 \"$(cat \"$PID\")\" 2>/dev/null\n" + + "}\n" + + "start_daemon() {\n" + + " mkdir -p \"$DIR\"\n" + + " chmod 700 \"$DIR\" 2>/dev/null || true\n" + + " chmod 755 \"$DAEMON\" 2>/dev/null || true\n" + + " touch \"$MARKER\"\n" + + " if is_running; then exit 0; fi\n" + + " ( while [ -f \"$MARKER\" ]; do\n" + + " \"$DAEMON\" \"$CONF\" >> \"$LOG\" 2>&1\n" + + " sleep 2\n" + + " done ) >/dev/null 2>&1 &\n" + + " sleep 1\n" + + " if is_running; then exit 0; fi\n" + + " exit 1\n" + + "}\n" + + "stop_daemon() {\n" + + " rm -f \"$MARKER\"\n" + + " if [ -f \"$PID\" ]; then kill -TERM \"$(cat \"$PID\")\" 2>/dev/null || true; fi\n" + + "}\n" + + "case \"$1\" in\n" + + " start) start_daemon ;;\n" + + " stop) stop_daemon; exit 0 ;;\n" + + " restart) stop_daemon; start_daemon ;;\n" + + " reload) if is_running; then kill -HUP \"$(cat \"$PID\")\" 2>/dev/null; else start_daemon; fi ;;\n" + + " status) if is_running; then echo running; exit 0; else echo stopped; exit 1; fi ;;\n" + + " *) echo \"usage: $0 {start|stop|restart|reload|status}\"; exit 2 ;;\n" + + "esac\n"; + } + + private static File workDir(Context context) { + return context.getApplicationContext().getDir(WORK_DIR, Context.MODE_PRIVATE); + } + + private static String supervisorPath(Context context) { + return new File(workDir(context), SUPERVISOR).getAbsolutePath(); + } + + private static void writeText(File file, String text) throws IOException { + try (FileOutputStream output = new FileOutputStream(file, false)) { + output.write(text.getBytes(StandardCharsets.UTF_8)); + } + } + + private static String selectAbi() { + String[] abis = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP + ? Build.SUPPORTED_ABIS + : new String[]{Build.CPU_ABI}; + for (String abi : abis) { + if ("arm64-v8a".equals(abi) || "armeabi-v7a".equals(abi) + || "x86_64".equals(abi) || "x86".equals(abi)) { + return abi; + } + } + return "armeabi-v7a"; + } + + private static String shellQuote(String value) { + if (value == null) { + return "''"; + } + return "'" + value.replace("'", "'\"'\"'") + "'"; + } +} diff --git a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java index 71d5e2161..9f20a620f 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java +++ b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java @@ -16,6 +16,7 @@ import dev.ukanth.ufirewall.Api; import dev.ukanth.ufirewall.R; +import dev.ukanth.ufirewall.dns.DnsHijackManager; import dev.ukanth.ufirewall.service.RootCommand; import dev.ukanth.ufirewall.util.G; @@ -174,6 +175,10 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, enableTor.setChecked(false); CheckBoxPreference enableCustomRules = (CheckBoxPreference) findPreference("enableCustomRules"); enableCustomRules.setChecked(false); + CheckBoxPreference enableDnsHijack = (CheckBoxPreference) findPreference("enableDnsHijack"); + if (enableDnsHijack != null) { + enableDnsHijack.setChecked(false); + } G.enableRoam(false); G.enableLAN(false); @@ -181,6 +186,7 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, G.enableTether(false); G.enableTor(false); G.enableCustomRules(false); + G.enableDnsHijack(false); } } @@ -306,5 +312,27 @@ public void cbFunc(RootCommand state) { allow.setChecked(false); } + if (isDnsHijackPreference(key)) { + Api.setRulesUpToDate(false); + if (!key.equals("enableDnsHijack") && !key.equals("dnsHijackPort") && G.enableDnsHijack()) { + DnsHijackManager.requestReload(ctx); + } + } + + } + + private boolean isDnsHijackPreference(String key) { + return key != null && (key.equals("enableDnsHijack") + || key.equals("dnsHijackPort") + || key.equals("dnsHijackUpstreams") + || key.equals("dnsHijackFailOpen") + || key.equals("dnsHijackStrictMode") + || key.equals("dnsHijackTimeoutMs") + || key.equals("dnsHijackAllowExact") + || key.equals("dnsHijackAllowSuffix") + || key.equals("dnsHijackBlockExact") + || key.equals("dnsHijackBlockSuffix") + || key.equals("dnsHijackAllowRegex") + || key.equals("dnsHijackBlockRegex")); } } diff --git a/app/src/main/java/dev/ukanth/ufirewall/util/G.java b/app/src/main/java/dev/ukanth/ufirewall/util/G.java index d92f666a0..b31ffd4a9 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/util/G.java +++ b/app/src/main/java/dev/ukanth/ufirewall/util/G.java @@ -170,6 +170,18 @@ public static Context getContext() { private static final String COPIED_OLD_EXPORTS = "copyOldExports"; private static final String SYSTEM_FILE_PICKER = "useSystemFilePicker"; private static final String ZIP_LOG_REPORTS = "zipLogReports"; + private static final String ENABLE_DNS_HIJACK = "enableDnsHijack"; + private static final String DNS_HIJACK_PORT = "dnsHijackPort"; + private static final String DNS_HIJACK_UPSTREAMS = "dnsHijackUpstreams"; + private static final String DNS_HIJACK_FAIL_OPEN = "dnsHijackFailOpen"; + private static final String DNS_HIJACK_STRICT_MODE = "dnsHijackStrictMode"; + private static final String DNS_HIJACK_TIMEOUT_MS = "dnsHijackTimeoutMs"; + private static final String DNS_HIJACK_ALLOW_EXACT = "dnsHijackAllowExact"; + private static final String DNS_HIJACK_ALLOW_SUFFIX = "dnsHijackAllowSuffix"; + private static final String DNS_HIJACK_BLOCK_EXACT = "dnsHijackBlockExact"; + private static final String DNS_HIJACK_BLOCK_SUFFIX = "dnsHijackBlockSuffix"; + private static final String DNS_HIJACK_ALLOW_REGEX = "dnsHijackAllowRegex"; + private static final String DNS_HIJACK_BLOCK_REGEX = "dnsHijackBlockRegex"; private static final String SHOW_ALL_APPS = "showAllApps"; @@ -255,6 +267,72 @@ public static boolean zipLogReports() { return gPrefs.getBoolean(ZIP_LOG_REPORTS, false); } + public static boolean enableDnsHijack() { + return gPrefs.getBoolean(ENABLE_DNS_HIJACK, false); + } + + public static boolean enableDnsHijack(boolean val) { + gPrefs.edit().putBoolean(ENABLE_DNS_HIJACK, val).commit(); + return val; + } + + public static int dnsHijackPort(int fallback) { + return readIntPreference(DNS_HIJACK_PORT, fallback, 1024, 65535); + } + + public static String dnsHijackUpstreams() { + return gPrefs.getString(DNS_HIJACK_UPSTREAMS, "1.1.1.1:53\n8.8.8.8:53"); + } + + public static boolean dnsHijackFailOpen() { + return gPrefs.getBoolean(DNS_HIJACK_FAIL_OPEN, true); + } + + public static boolean dnsHijackStrictMode() { + return gPrefs.getBoolean(DNS_HIJACK_STRICT_MODE, false); + } + + public static int dnsHijackTimeoutMs() { + return readIntPreference(DNS_HIJACK_TIMEOUT_MS, 2500, 250, 10000); + } + + public static String dnsHijackAllowExact() { + return gPrefs.getString(DNS_HIJACK_ALLOW_EXACT, ""); + } + + public static String dnsHijackAllowSuffix() { + return gPrefs.getString(DNS_HIJACK_ALLOW_SUFFIX, ""); + } + + public static String dnsHijackBlockExact() { + return gPrefs.getString(DNS_HIJACK_BLOCK_EXACT, ""); + } + + public static String dnsHijackBlockSuffix() { + return gPrefs.getString(DNS_HIJACK_BLOCK_SUFFIX, ""); + } + + public static String dnsHijackAllowRegex() { + return gPrefs.getString(DNS_HIJACK_ALLOW_REGEX, ""); + } + + public static String dnsHijackBlockRegex() { + return gPrefs.getString(DNS_HIJACK_BLOCK_REGEX, ""); + } + + private static int readIntPreference(String key, int fallback, int min, int max) { + String value = gPrefs.getString(key, String.valueOf(fallback)); + try { + int parsed = Integer.parseInt(value); + if (parsed < min || parsed > max) { + return fallback; + } + return parsed; + } catch (NumberFormatException e) { + return fallback; + } + } + public static boolean hasCopyOld() { return gPrefs.getBoolean(COPIED_OLD_EXPORTS, false); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2a439dc55..fb9fe6ae2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -298,6 +298,31 @@ IPv4 Chains IPv6 Chains Rules/Connectivity + Root DNS Filtering + Capture DNS with root redirect + Run the native DNS daemon and redirect UDP/TCP DNS traffic through it when firewall rules are applied. + Local DNS daemon port + Port used by the local root DNS daemon. Reapply firewall rules after changing this. + Upstream DNS servers + One upstream per line, using host:port format. + Fail open + Allow upstream DNS when filtering cannot complete instead of blocking the query. + Strict allow/block priority + When enabled, exact and wildcard block rules can override allow rules. + Upstream timeout + DNS upstream timeout in milliseconds. + Exact allow domains + Domains that should always be allowed. One entry per line. + Wildcard allow suffixes + Suffix rules that allow matching domains, such as example.com. + Exact block domains + Domains that should be blocked exactly. One entry per line. + Wildcard block suffixes + Suffix rules that block matching subdomains and domains. + Regex allow rules + Regular expressions that allow matching queries. + Regex block rules + Regular expressions that block matching queries. Log Hide app icons Improve performance by disabling app icons in the main view diff --git a/app/src/main/res/xml/rules_preferences.xml b/app/src/main/res/xml/rules_preferences.xml index 2dbbc56ca..6aa692637 100644 --- a/app/src/main/res/xml/rules_preferences.xml +++ b/app/src/main/res/xml/rules_preferences.xml @@ -69,6 +69,86 @@ android:title="@string/direct_rules_visibility_title" /> + + + + + + + + + + + + + + + + + + + + + + + + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_PACKET 4096 +#define MAX_DOMAIN 256 +#define MAX_RULES 8192 +#define MAX_REGEX 128 +#define MAX_UPSTREAMS 8 +#define CACHE_SIZE 1024 +#define LOG_RING 256 +#define DEFAULT_PORT 5354 +#define DEFAULT_TIMEOUT_MS 2500 + +typedef enum { + DECISION_ALLOW = 0, + DECISION_BLOCK = 1 +} decision_t; + +typedef struct { + char value[MAX_DOMAIN]; +} string_rule_t; + +typedef struct { + regex_t compiled; + char pattern[MAX_DOMAIN]; + bool valid; +} regex_rule_t; + +typedef struct { + char host[128]; + int port; +} upstream_t; + +typedef struct { + int listen_port; + int strict_mode; + int fail_open; + int timeout_ms; + char control_socket[256]; + char log_file[256]; + char pid_file[256]; + upstream_t upstreams[MAX_UPSTREAMS]; + int upstream_count; + string_rule_t exact_allow[MAX_RULES]; + string_rule_t suffix_allow[MAX_RULES]; + string_rule_t exact_block[MAX_RULES]; + string_rule_t suffix_block[MAX_RULES]; + int exact_allow_count; + int suffix_allow_count; + int exact_block_count; + int suffix_block_count; + regex_rule_t regex_allow[MAX_REGEX]; + regex_rule_t regex_block[MAX_REGEX]; + int regex_allow_count; + int regex_block_count; + uint64_t generation; +} config_t; + +typedef struct { + uint64_t queries; + uint64_t allowed; + uint64_t blocked; + uint64_t cache_hits; + uint64_t upstream_failures; + uint64_t reloads; + uint64_t start_time; +} stats_t; + +typedef struct { + char domain[MAX_DOMAIN]; + char action[16]; + int latency_ms; + uint64_t timestamp; +} log_entry_t; + +typedef struct { + char domain[MAX_DOMAIN]; + uint16_t qtype; + uint8_t response[MAX_PACKET]; + size_t response_len; + time_t expires_at; + uint32_t hash; + bool used; +} cache_entry_t; + +static volatile sig_atomic_t g_running = 1; +static config_t g_cfg; +static stats_t g_stats; +static log_entry_t g_logs[LOG_RING]; +static int g_log_pos = 0; +static cache_entry_t g_cache[CACHE_SIZE]; +static char g_config_path[256]; + +static uint64_t now_seconds(void) { + return (uint64_t) time(NULL); +} + +static int elapsed_ms(const struct timeval *start, const struct timeval *end) { + long seconds = end->tv_sec - start->tv_sec; + long micros = end->tv_usec - start->tv_usec; + return (int) ((seconds * 1000L) + (micros / 1000L)); +} + +static void trim(char *s) { + size_t len; + char *p = s; + while (*p && isspace((unsigned char) *p)) { + p++; + } + if (p != s) { + memmove(s, p, strlen(p) + 1); + } + len = strlen(s); + while (len > 0 && isspace((unsigned char) s[len - 1])) { + s[len - 1] = '\0'; + len--; + } +} + +static void lower_ascii(char *s) { + while (*s) { + *s = (char) tolower((unsigned char) *s); + s++; + } +} + +static void safe_copy(char *dst, size_t dst_len, const char *src) { + if (dst_len == 0) { + return; + } + if (src == NULL) { + dst[0] = '\0'; + return; + } + strncpy(dst, src, dst_len - 1); + dst[dst_len - 1] = '\0'; +} + +static uint32_t hash_domain(const char *domain, uint16_t qtype) { + uint32_t h = 2166136261u; + const unsigned char *p = (const unsigned char *) domain; + while (*p) { + h ^= *p++; + h *= 16777619u; + } + h ^= qtype & 0xffu; + h *= 16777619u; + h ^= (qtype >> 8) & 0xffu; + h *= 16777619u; + return h; +} + +static void add_log(const char *domain, const char *action, int latency_ms) { + log_entry_t *entry = &g_logs[g_log_pos % LOG_RING]; + safe_copy(entry->domain, sizeof(entry->domain), domain); + safe_copy(entry->action, sizeof(entry->action), action); + entry->latency_ms = latency_ms; + entry->timestamp = now_seconds(); + g_log_pos = (g_log_pos + 1) % LOG_RING; +} + +static void free_regex_rules(config_t *cfg) { + int i; + for (i = 0; i < cfg->regex_allow_count; i++) { + if (cfg->regex_allow[i].valid) { + regfree(&cfg->regex_allow[i].compiled); + cfg->regex_allow[i].valid = false; + } + } + for (i = 0; i < cfg->regex_block_count; i++) { + if (cfg->regex_block[i].valid) { + regfree(&cfg->regex_block[i].compiled); + cfg->regex_block[i].valid = false; + } + } +} + +static bool add_string_rule(string_rule_t *rules, int *count, const char *value) { + if (*count >= MAX_RULES || value == NULL || value[0] == '\0') { + return false; + } + safe_copy(rules[*count].value, sizeof(rules[*count].value), value); + lower_ascii(rules[*count].value); + (*count)++; + return true; +} + +static bool add_regex_rule(regex_rule_t *rules, int *count, const char *value) { + regex_rule_t *rule; + if (*count >= MAX_REGEX || value == NULL || value[0] == '\0') { + return false; + } + rule = &rules[*count]; + memset(rule, 0, sizeof(*rule)); + safe_copy(rule->pattern, sizeof(rule->pattern), value); + if (regcomp(&rule->compiled, value, REG_EXTENDED | REG_NOSUB | REG_ICASE) != 0) { + return false; + } + rule->valid = true; + (*count)++; + return true; +} + +static bool exact_match(const string_rule_t *rules, int count, const char *domain) { + int i; + for (i = 0; i < count; i++) { + if (strcmp(rules[i].value, domain) == 0) { + return true; + } + } + return false; +} + +static bool suffix_match(const string_rule_t *rules, int count, const char *domain) { + int i; + size_t domain_len = strlen(domain); + for (i = 0; i < count; i++) { + const char *suffix = rules[i].value; + size_t suffix_len = strlen(suffix); + if (suffix_len == 0 || suffix_len > domain_len) { + continue; + } + if (strcmp(domain + domain_len - suffix_len, suffix) == 0) { + if (suffix_len == domain_len || domain[domain_len - suffix_len - 1] == '.') { + return true; + } + } + } + return false; +} + +static bool regex_match_rules(const regex_rule_t *rules, int count, const char *domain) { + int i; + for (i = 0; i < count; i++) { + if (rules[i].valid && regexec(&rules[i].compiled, domain, 0, NULL, 0) == 0) { + return true; + } + } + return false; +} + +static decision_t evaluate_domain(const config_t *cfg, const char *domain, const char **reason) { + bool exact_allow = exact_match(cfg->exact_allow, cfg->exact_allow_count, domain); + bool suffix_allow = suffix_match(cfg->suffix_allow, cfg->suffix_allow_count, domain); + bool regex_allow = regex_match_rules(cfg->regex_allow, cfg->regex_allow_count, domain); + bool block = false; + + if (exact_match(cfg->exact_block, cfg->exact_block_count, domain)) { + *reason = "exact_block"; + block = true; + } else if (suffix_match(cfg->suffix_block, cfg->suffix_block_count, domain)) { + *reason = "suffix_block"; + block = true; + } else if (regex_match_rules(cfg->regex_block, cfg->regex_block_count, domain)) { + *reason = "regex_block"; + block = true; + } + + if (block && cfg->strict_mode) { + return DECISION_BLOCK; + } + if (exact_allow) { + *reason = "exact_allow"; + return DECISION_ALLOW; + } + if (suffix_allow) { + *reason = "suffix_allow"; + return DECISION_ALLOW; + } + if (regex_allow) { + *reason = "regex_allow"; + return DECISION_ALLOW; + } + if (block) { + return DECISION_BLOCK; + } + *reason = "upstream"; + return DECISION_ALLOW; +} + +static bool parse_qname(const uint8_t *packet, size_t len, char *domain, size_t domain_len, uint16_t *qtype) { + size_t pos = 12; + size_t out = 0; + if (len < 12) { + return false; + } + while (pos < len) { + uint8_t label_len = packet[pos++]; + if (label_len == 0) { + break; + } + if ((label_len & 0xc0u) != 0 || label_len > 63 || pos + label_len > len) { + return false; + } + if (out != 0) { + if (out + 1 >= domain_len) { + return false; + } + domain[out++] = '.'; + } + if (out + label_len >= domain_len) { + return false; + } + memcpy(domain + out, packet + pos, label_len); + out += label_len; + pos += label_len; + } + if (pos + 4 > len || out == 0) { + return false; + } + domain[out] = '\0'; + lower_ascii(domain); + *qtype = (uint16_t) ((packet[pos] << 8) | packet[pos + 1]); + return true; +} + +static size_t build_block_response(const uint8_t *query, size_t query_len, uint8_t *out, size_t out_len) { + size_t pos = 12; + if (query_len < 12 || out_len < query_len) { + return 0; + } + while (pos < query_len && query[pos] != 0) { + uint8_t label_len = query[pos]; + if ((label_len & 0xc0u) != 0 || label_len > 63 || pos + label_len + 1 > query_len) { + return 0; + } + pos += (size_t) label_len + 1; + } + if (pos + 5 > query_len) { + return 0; + } + memcpy(out, query, pos + 5); + out[2] = 0x81; + out[3] = 0x83; + out[6] = 0x00; + out[7] = 0x00; + out[8] = 0x00; + out[9] = 0x00; + out[10] = 0x00; + out[11] = 0x00; + return pos + 5; +} + +static uint32_t read_u32(const uint8_t *p) { + return ((uint32_t) p[0] << 24) | ((uint32_t) p[1] << 16) | ((uint32_t) p[2] << 8) | p[3]; +} + +static uint16_t read_u16(const uint8_t *p) { + return (uint16_t) (((uint16_t) p[0] << 8) | p[1]); +} + +static size_t skip_name(const uint8_t *packet, size_t len, size_t pos) { + while (pos < len) { + uint8_t c = packet[pos++]; + if (c == 0) { + return pos; + } + if ((c & 0xc0u) == 0xc0u) { + return pos + 1 <= len ? pos + 1 : len + 1; + } + if ((c & 0xc0u) != 0 || pos + c > len) { + return len + 1; + } + pos += c; + } + return len + 1; +} + +static uint32_t extract_min_ttl(const uint8_t *packet, size_t len) { + uint16_t qd; + uint16_t an; + size_t pos = 12; + uint16_t i; + uint32_t min_ttl = 60; + if (len < 12) { + return 0; + } + qd = read_u16(packet + 4); + an = read_u16(packet + 6); + for (i = 0; i < qd; i++) { + pos = skip_name(packet, len, pos); + if (pos + 4 > len) { + return 0; + } + pos += 4; + } + if (an == 0) { + return 30; + } + min_ttl = UINT32_MAX; + for (i = 0; i < an; i++) { + uint32_t ttl; + uint16_t rdlen; + pos = skip_name(packet, len, pos); + if (pos + 10 > len) { + return 30; + } + ttl = read_u32(packet + pos + 4); + rdlen = read_u16(packet + pos + 8); + if (ttl < min_ttl) { + min_ttl = ttl; + } + pos += 10 + rdlen; + if (pos > len) { + return 30; + } + } + if (min_ttl == UINT32_MAX || min_ttl == 0) { + return 30; + } + if (min_ttl > 86400) { + return 86400; + } + return min_ttl; +} + +static bool cache_lookup(const char *domain, uint16_t qtype, const uint8_t *query, uint8_t *out, size_t *out_len) { + uint32_t h = hash_domain(domain, qtype); + uint32_t start = h % CACHE_SIZE; + uint32_t i; + time_t now = time(NULL); + for (i = 0; i < 8; i++) { + cache_entry_t *entry = &g_cache[(start + i) % CACHE_SIZE]; + if (!entry->used) { + return false; + } + if (entry->hash == h && entry->qtype == qtype && strcmp(entry->domain, domain) == 0) { + if (entry->expires_at <= now) { + entry->used = false; + return false; + } + memcpy(out, entry->response, entry->response_len); + out[0] = query[0]; + out[1] = query[1]; + *out_len = entry->response_len; + return true; + } + } + return false; +} + +static void cache_store(const char *domain, uint16_t qtype, const uint8_t *response, size_t response_len) { + uint32_t h; + uint32_t slot; + uint32_t ttl; + cache_entry_t *entry; + if (response_len < 12 || response_len > MAX_PACKET) { + return; + } + ttl = extract_min_ttl(response, response_len); + if (ttl == 0) { + return; + } + h = hash_domain(domain, qtype); + slot = h % CACHE_SIZE; + entry = &g_cache[slot]; + memset(entry, 0, sizeof(*entry)); + safe_copy(entry->domain, sizeof(entry->domain), domain); + entry->qtype = qtype; + entry->hash = h; + memcpy(entry->response, response, response_len); + entry->response_len = response_len; + entry->expires_at = time(NULL) + ttl; + entry->used = true; +} + +static int connect_upstream(const upstream_t *upstream, int socktype, int timeout_ms) { + struct addrinfo hints; + struct addrinfo *res = NULL; + struct addrinfo *rp; + char port[16]; + int fd = -1; + snprintf(port, sizeof(port), "%d", upstream->port); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = socktype; + if (getaddrinfo(upstream->host, port, &hints, &res) != 0) { + return -1; + } + for (rp = res; rp != NULL; rp = rp->ai_next) { + struct timeval timeout; + fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (fd < 0) { + continue; + } + timeout.tv_sec = timeout_ms / 1000; + timeout.tv_usec = (timeout_ms % 1000) * 1000; + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); + if (connect(fd, rp->ai_addr, rp->ai_addrlen) == 0) { + break; + } + close(fd); + fd = -1; + } + freeaddrinfo(res); + return fd; +} + +static ssize_t forward_udp(const config_t *cfg, const uint8_t *query, size_t query_len, uint8_t *response, size_t response_len) { + int i; + for (i = 0; i < cfg->upstream_count; i++) { + int fd = connect_upstream(&cfg->upstreams[i], SOCK_DGRAM, cfg->timeout_ms); + ssize_t got; + if (fd < 0) { + continue; + } + if (send(fd, query, query_len, 0) < 0) { + close(fd); + continue; + } + got = recv(fd, response, response_len, 0); + close(fd); + if (got > 0) { + return got; + } + } + return -1; +} + +static ssize_t read_full(int fd, uint8_t *buf, size_t len) { + size_t got = 0; + while (got < len) { + ssize_t n = recv(fd, buf + got, len - got, 0); + if (n <= 0) { + return -1; + } + got += (size_t) n; + } + return (ssize_t) got; +} + +static ssize_t forward_tcp(const config_t *cfg, const uint8_t *query, size_t query_len, uint8_t *response, size_t response_len) { + int i; + uint8_t lenbuf[2]; + if (query_len > 65535) { + return -1; + } + lenbuf[0] = (uint8_t) ((query_len >> 8) & 0xffu); + lenbuf[1] = (uint8_t) (query_len & 0xffu); + for (i = 0; i < cfg->upstream_count; i++) { + uint8_t rlenbuf[2]; + uint16_t rlen; + int fd = connect_upstream(&cfg->upstreams[i], SOCK_STREAM, cfg->timeout_ms); + if (fd < 0) { + continue; + } + if (send(fd, lenbuf, 2, 0) != 2 || send(fd, query, query_len, 0) != (ssize_t) query_len) { + close(fd); + continue; + } + if (read_full(fd, rlenbuf, 2) != 2) { + close(fd); + continue; + } + rlen = (uint16_t) ((rlenbuf[0] << 8) | rlenbuf[1]); + if (rlen == 0 || rlen > response_len) { + close(fd); + continue; + } + if (read_full(fd, response, rlen) != rlen) { + close(fd); + continue; + } + close(fd); + return rlen; + } + return -1; +} + +static void default_config(config_t *cfg) { + memset(cfg, 0, sizeof(*cfg)); + cfg->listen_port = DEFAULT_PORT; + cfg->fail_open = 1; + cfg->timeout_ms = DEFAULT_TIMEOUT_MS; + safe_copy(cfg->control_socket, sizeof(cfg->control_socket), "/data/local/tmp/afwall_dnsd.sock"); + cfg->upstream_count = 1; + safe_copy(cfg->upstreams[0].host, sizeof(cfg->upstreams[0].host), "1.1.1.1"); + cfg->upstreams[0].port = 53; +} + +static bool parse_upstream(config_t *cfg, const char *value) { + const char *colon; + upstream_t *upstream; + if (cfg->upstream_count >= MAX_UPSTREAMS || value == NULL || value[0] == '\0') { + return false; + } + upstream = &cfg->upstreams[cfg->upstream_count]; + memset(upstream, 0, sizeof(*upstream)); + colon = strrchr(value, ':'); + if (colon != NULL && colon[1] != '\0') { + char host[128]; + size_t host_len = (size_t) (colon - value); + if (host_len >= sizeof(host)) { + return false; + } + memcpy(host, value, host_len); + host[host_len] = '\0'; + safe_copy(upstream->host, sizeof(upstream->host), host); + upstream->port = atoi(colon + 1); + } else { + safe_copy(upstream->host, sizeof(upstream->host), value); + upstream->port = 53; + } + if (upstream->port <= 0 || upstream->port > 65535) { + upstream->port = 53; + } + cfg->upstream_count++; + return true; +} + +static bool load_config(const char *path, config_t *new_cfg) { + FILE *fp; + char line[1024]; + default_config(new_cfg); + fp = fopen(path, "r"); + if (fp == NULL) { + return false; + } + new_cfg->upstream_count = 0; + while (fgets(line, sizeof(line), fp) != NULL) { + char *eq; + char *key = line; + char *value; + trim(line); + if (line[0] == '\0' || line[0] == '#') { + continue; + } + eq = strchr(line, '='); + if (eq == NULL) { + continue; + } + *eq = '\0'; + value = eq + 1; + trim(key); + trim(value); + if (strcmp(key, "port") == 0) { + int port = atoi(value); + if (port > 0 && port <= 65535) { + new_cfg->listen_port = port; + } + } else if (strcmp(key, "control_socket") == 0) { + safe_copy(new_cfg->control_socket, sizeof(new_cfg->control_socket), value); + } else if (strcmp(key, "log_file") == 0) { + safe_copy(new_cfg->log_file, sizeof(new_cfg->log_file), value); + } else if (strcmp(key, "pid_file") == 0) { + safe_copy(new_cfg->pid_file, sizeof(new_cfg->pid_file), value); + } else if (strcmp(key, "fail_open") == 0) { + new_cfg->fail_open = atoi(value) != 0; + } else if (strcmp(key, "strict_mode") == 0) { + new_cfg->strict_mode = atoi(value) != 0; + } else if (strcmp(key, "timeout_ms") == 0) { + int timeout = atoi(value); + if (timeout >= 250 && timeout <= 10000) { + new_cfg->timeout_ms = timeout; + } + } else if (strcmp(key, "upstream") == 0) { + parse_upstream(new_cfg, value); + } else if (strcmp(key, "allow_exact") == 0) { + add_string_rule(new_cfg->exact_allow, &new_cfg->exact_allow_count, value); + } else if (strcmp(key, "allow_suffix") == 0) { + add_string_rule(new_cfg->suffix_allow, &new_cfg->suffix_allow_count, value); + } else if (strcmp(key, "block_exact") == 0) { + add_string_rule(new_cfg->exact_block, &new_cfg->exact_block_count, value); + } else if (strcmp(key, "block_suffix") == 0) { + add_string_rule(new_cfg->suffix_block, &new_cfg->suffix_block_count, value); + } else if (strcmp(key, "allow_regex") == 0) { + add_regex_rule(new_cfg->regex_allow, &new_cfg->regex_allow_count, value); + } else if (strcmp(key, "block_regex") == 0) { + add_regex_rule(new_cfg->regex_block, &new_cfg->regex_block_count, value); + } + } + fclose(fp); + if (new_cfg->upstream_count == 0) { + safe_copy(new_cfg->upstreams[0].host, sizeof(new_cfg->upstreams[0].host), "1.1.1.1"); + new_cfg->upstreams[0].port = 53; + new_cfg->upstream_count = 1; + } + new_cfg->generation = g_cfg.generation + 1; + return true; +} + +static bool reload_config(void) { + config_t next; + if (!load_config(g_config_path, &next)) { + return false; + } + free_regex_rules(&g_cfg); + g_cfg = next; + memset(g_cache, 0, sizeof(g_cache)); + g_stats.reloads++; + return true; +} + +static void write_pid_file(void) { + FILE *fp; + if (g_cfg.pid_file[0] == '\0') { + return; + } + fp = fopen(g_cfg.pid_file, "w"); + if (fp != NULL) { + fprintf(fp, "%ld\n", (long) getpid()); + fclose(fp); + } +} + +static int create_udp_socket(int port) { + int fd; + int off = 0; + int on = 1; + struct sockaddr_in6 addr6; + fd = socket(AF_INET6, SOCK_DGRAM, 0); + if (fd < 0) { + return -1; + } + setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)); + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + memset(&addr6, 0, sizeof(addr6)); + addr6.sin6_family = AF_INET6; + addr6.sin6_addr = in6addr_any; + addr6.sin6_port = htons((uint16_t) port); + if (bind(fd, (struct sockaddr *) &addr6, sizeof(addr6)) != 0) { + close(fd); + return -1; + } + return fd; +} + +static int create_tcp_socket(int port) { + int fd; + int off = 0; + int on = 1; + struct sockaddr_in6 addr6; + fd = socket(AF_INET6, SOCK_STREAM, 0); + if (fd < 0) { + return -1; + } + setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)); + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + memset(&addr6, 0, sizeof(addr6)); + addr6.sin6_family = AF_INET6; + addr6.sin6_addr = in6addr_any; + addr6.sin6_port = htons((uint16_t) port); + if (bind(fd, (struct sockaddr *) &addr6, sizeof(addr6)) != 0 || listen(fd, 16) != 0) { + close(fd); + return -1; + } + return fd; +} + +static int create_control_socket(const char *path) { + int fd; + struct sockaddr_un addr; + if (path == NULL || path[0] == '\0') { + return -1; + } + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + return -1; + } + unlink(path); + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + safe_copy(addr.sun_path, sizeof(addr.sun_path), path); + if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) != 0 || listen(fd, 4) != 0) { + close(fd); + return -1; + } + chmod(path, 0666); + return fd; +} + +static void handle_dns_query(const config_t *cfg, const uint8_t *query, size_t query_len, + uint8_t *response, size_t *response_len, const char **action_out, + int tcp) { + char domain[MAX_DOMAIN]; + uint16_t qtype = 0; + const char *reason = "parse"; + ssize_t forwarded; + if (!parse_qname(query, query_len, domain, sizeof(domain), &qtype)) { + *response_len = build_block_response(query, query_len, response, MAX_PACKET); + *action_out = "invalid"; + return; + } + g_stats.queries++; + if (evaluate_domain(cfg, domain, &reason) == DECISION_BLOCK) { + *response_len = build_block_response(query, query_len, response, MAX_PACKET); + g_stats.blocked++; + *action_out = reason; + add_log(domain, "blocked", 0); + return; + } + if (cache_lookup(domain, qtype, query, response, response_len)) { + g_stats.cache_hits++; + g_stats.allowed++; + *action_out = "cache"; + add_log(domain, "cache", 0); + return; + } + forwarded = tcp + ? forward_tcp(cfg, query, query_len, response, MAX_PACKET) + : forward_udp(cfg, query, query_len, response, MAX_PACKET); + if (forwarded > 0) { + *response_len = (size_t) forwarded; + cache_store(domain, qtype, response, *response_len); + g_stats.allowed++; + *action_out = "upstream"; + add_log(domain, "allowed", 0); + return; + } + g_stats.upstream_failures++; + if (cfg->fail_open) { + *response_len = 0; + *action_out = "upstream_failed"; + } else { + *response_len = build_block_response(query, query_len, response, MAX_PACKET); + g_stats.blocked++; + *action_out = "fail_closed"; + } + add_log(domain, *action_out, 0); +} + +static void handle_udp(int fd) { + uint8_t query[MAX_PACKET]; + uint8_t response[MAX_PACKET]; + struct sockaddr_storage peer; + socklen_t peer_len = sizeof(peer); + ssize_t got; + size_t response_len = 0; + const char *action = "none"; + struct timeval start; + struct timeval end; + got = recvfrom(fd, query, sizeof(query), 0, (struct sockaddr *) &peer, &peer_len); + if (got <= 0) { + return; + } + gettimeofday(&start, NULL); + handle_dns_query(&g_cfg, query, (size_t) got, response, &response_len, &action, 0); + gettimeofday(&end, NULL); + (void) action; + if (response_len > 0) { + sendto(fd, response, response_len, 0, (struct sockaddr *) &peer, peer_len); + } + if (response_len == 0 && !g_cfg.fail_open) { + add_log("unknown", "no_response", elapsed_ms(&start, &end)); + } +} + +static void handle_tcp_client(int client) { + uint8_t lenbuf[2]; + uint8_t query[MAX_PACKET]; + uint8_t response[MAX_PACKET + 2]; + uint16_t qlen; + size_t response_len = 0; + const char *action = "none"; + struct timeval timeout; + timeout.tv_sec = 5; + timeout.tv_usec = 0; + setsockopt(client, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + setsockopt(client, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); + if (read_full(client, lenbuf, 2) != 2) { + return; + } + qlen = (uint16_t) ((lenbuf[0] << 8) | lenbuf[1]); + if (qlen == 0 || qlen > MAX_PACKET) { + return; + } + if (read_full(client, query, qlen) != qlen) { + return; + } + handle_dns_query(&g_cfg, query, qlen, response + 2, &response_len, &action, 1); + (void) action; + if (response_len > 0) { + response[0] = (uint8_t) ((response_len >> 8) & 0xffu); + response[1] = (uint8_t) (response_len & 0xffu); + send(client, response, response_len + 2, 0); + } +} + +static void handle_tcp(int fd) { + int client = accept(fd, NULL, NULL); + if (client >= 0) { + handle_tcp_client(client); + close(client); + } +} + +static void write_control_response(int fd, const char *fmt, ...) { + char buf[4096]; + va_list ap; + int n; + va_start(ap, fmt); + n = vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + if (n > 0) { + send(fd, buf, (size_t) n, 0); + } +} + +static void handle_control(int fd) { + int client = accept(fd, NULL, NULL); + char cmd[128]; + ssize_t n; + if (client < 0) { + return; + } + n = recv(client, cmd, sizeof(cmd) - 1, 0); + if (n <= 0) { + close(client); + return; + } + cmd[n] = '\0'; + trim(cmd); + if (strcmp(cmd, "status") == 0 || strcmp(cmd, "stats") == 0) { + write_control_response(client, + "running=1\npid=%ld\nuptime=%llu\ngeneration=%llu\nqueries=%llu\nallowed=%llu\nblocked=%llu\ncache_hits=%llu\nupstream_failures=%llu\nreloads=%llu\nrules_exact_allow=%d\nrules_suffix_allow=%d\nrules_exact_block=%d\nrules_suffix_block=%d\nrules_regex_allow=%d\nrules_regex_block=%d\n", + (long) getpid(), + (unsigned long long) (now_seconds() - g_stats.start_time), + (unsigned long long) g_cfg.generation, + (unsigned long long) g_stats.queries, + (unsigned long long) g_stats.allowed, + (unsigned long long) g_stats.blocked, + (unsigned long long) g_stats.cache_hits, + (unsigned long long) g_stats.upstream_failures, + (unsigned long long) g_stats.reloads, + g_cfg.exact_allow_count, + g_cfg.suffix_allow_count, + g_cfg.exact_block_count, + g_cfg.suffix_block_count, + g_cfg.regex_allow_count, + g_cfg.regex_block_count); + } else if (strcmp(cmd, "reload") == 0) { + if (reload_config()) { + write_control_response(client, "ok reload generation=%llu\n", (unsigned long long) g_cfg.generation); + } else { + write_control_response(client, "error reload\n"); + } + } else if (strcmp(cmd, "logs") == 0) { + int i; + for (i = 0; i < LOG_RING; i++) { + int idx = (g_log_pos + i) % LOG_RING; + if (g_logs[idx].timestamp == 0) { + continue; + } + write_control_response(client, "%llu %s %s %dms\n", + (unsigned long long) g_logs[idx].timestamp, + g_logs[idx].action, + g_logs[idx].domain, + g_logs[idx].latency_ms); + } + } else if (strcmp(cmd, "stop") == 0) { + write_control_response(client, "ok stopping\n"); + g_running = 0; + } else { + write_control_response(client, "error unknown_command\n"); + } + close(client); +} + +static void signal_handler(int signo) { + if (signo == SIGTERM || signo == SIGINT) { + g_running = 0; + } else if (signo == SIGHUP) { + reload_config(); + } +} + +static void usage(const char *argv0) { + fprintf(stderr, "usage: %s --config \n", argv0); +} + +int main(int argc, char **argv) { + int udp_fd; + int tcp_fd; + int control_fd; + int i; + default_config(&g_cfg); + g_stats.start_time = now_seconds(); + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "--config") == 0 && i + 1 < argc) { + safe_copy(g_config_path, sizeof(g_config_path), argv[++i]); + } else { + usage(argv[0]); + return 2; + } + } + if (g_config_path[0] == '\0') { + usage(argv[0]); + return 2; + } + if (!reload_config()) { + fprintf(stderr, "failed to load config: %s\n", g_config_path); + return 1; + } + write_pid_file(); + signal(SIGTERM, signal_handler); + signal(SIGINT, signal_handler); + signal(SIGHUP, signal_handler); + udp_fd = create_udp_socket(g_cfg.listen_port); + tcp_fd = create_tcp_socket(g_cfg.listen_port); + control_fd = create_control_socket(g_cfg.control_socket); + if (udp_fd < 0 || tcp_fd < 0 || control_fd < 0) { + fprintf(stderr, "failed to create listeners on port %d\n", g_cfg.listen_port); + return 1; + } + while (g_running) { + fd_set readfds; + int maxfd = udp_fd; + int ready; + FD_ZERO(&readfds); + FD_SET(udp_fd, &readfds); + FD_SET(tcp_fd, &readfds); + FD_SET(control_fd, &readfds); + if (tcp_fd > maxfd) { + maxfd = tcp_fd; + } + if (control_fd > maxfd) { + maxfd = control_fd; + } + ready = select(maxfd + 1, &readfds, NULL, NULL, NULL); + if (ready < 0) { + if (errno == EINTR) { + continue; + } + break; + } + if (FD_ISSET(udp_fd, &readfds)) { + handle_udp(udp_fd); + } + if (FD_ISSET(tcp_fd, &readfds)) { + handle_tcp(tcp_fd); + } + if (FD_ISSET(control_fd, &readfds)) { + handle_control(control_fd); + } + } + close(udp_fd); + close(tcp_fd); + close(control_fd); + unlink(g_cfg.control_socket); + unlink(g_cfg.pid_file); + free_regex_rules(&g_cfg); + return 0; +} From a59a399fb5cfbec961bb97924763affcfe4ba41e Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 13:54:19 -0700 Subject: [PATCH 002/108] Persist DNS daemon query logs --- .../main/assets/dnsd/arm64-v8a/afwall_dnsd | Bin 19816 -> 20264 bytes .../main/assets/dnsd/armeabi-v7a/afwall_dnsd | Bin 14960 -> 15552 bytes app/src/main/assets/dnsd/x86/afwall_dnsd | Bin 18240 -> 19168 bytes app/src/main/assets/dnsd/x86_64/afwall_dnsd | Bin 20224 -> 20784 bytes dnsdaemon/jni/afwall_dnsd.c | 48 +++++++++++++++++- 5 files changed, 47 insertions(+), 1 deletion(-) diff --git a/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd b/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd index a73ef33e038077ede80d6e3040cbd1e5b8a8486a..3e5522fc20d45374fe8f5d10d10473aa6c485648 100755 GIT binary patch delta 8591 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 PmpBdHd2xj^U>yGoaITN0 diff --git a/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd b/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd index 69c915f58ec9745886f96465ce1501c8dd6fa421..5fa8c3b8df26a2975d343268250892d16fa292cf 100755 GIT binary patch delta 6583 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 delta 5896 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 H!0&$nzIvxX diff --git a/app/src/main/assets/dnsd/x86/afwall_dnsd b/app/src/main/assets/dnsd/x86/afwall_dnsd index 53b376283ed7bc40c6edc5e77b06ed334ba74130..5a71ac57bdaf4a49a0a4df555931194914b6a744 100755 GIT binary patch delta 7651 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 delta 6592 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 Np-Q2C$xghD2u5&GvJ#ZpMLOAZ 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 be>ch=Yb@7AEMl)WR)>wL=qK!kCF%bMwX5H1 diff --git a/dnsdaemon/jni/afwall_dnsd.c b/dnsdaemon/jni/afwall_dnsd.c index 1ac690b96..d923df2e9 100644 --- a/dnsdaemon/jni/afwall_dnsd.c +++ b/dnsdaemon/jni/afwall_dnsd.c @@ -95,6 +95,7 @@ typedef struct { } stats_t; typedef struct { + uint64_t seq; char domain[MAX_DOMAIN]; char action[16]; int latency_ms; @@ -116,6 +117,8 @@ static config_t g_cfg; static stats_t g_stats; static log_entry_t g_logs[LOG_RING]; static int g_log_pos = 0; +static uint64_t g_log_seq = 0; +static uint64_t g_log_flushed_seq = 0; static cache_entry_t g_cache[CACHE_SIZE]; static char g_config_path[256]; @@ -180,6 +183,7 @@ static uint32_t hash_domain(const char *domain, uint16_t qtype) { static void add_log(const char *domain, const char *action, int latency_ms) { log_entry_t *entry = &g_logs[g_log_pos % LOG_RING]; + entry->seq = ++g_log_seq; safe_copy(entry->domain, sizeof(entry->domain), domain); safe_copy(entry->action, sizeof(entry->action), action); entry->latency_ms = latency_ms; @@ -187,6 +191,43 @@ static void add_log(const char *domain, const char *action, int latency_ms) { g_log_pos = (g_log_pos + 1) % LOG_RING; } +static void flush_logs(void) { + FILE *fp; + uint64_t first_seq; + uint64_t seq; + int i; + + if (g_cfg.log_file[0] == '\0' || g_log_flushed_seq == g_log_seq) { + return; + } + + first_seq = g_log_flushed_seq + 1; + if (g_log_seq >= LOG_RING && first_seq < g_log_seq - LOG_RING + 1) { + first_seq = g_log_seq - LOG_RING + 1; + } + + fp = fopen(g_cfg.log_file, "a"); + if (fp == NULL) { + return; + } + + for (seq = first_seq; seq <= g_log_seq; seq++) { + for (i = 0; i < LOG_RING; i++) { + const log_entry_t *entry = &g_logs[i]; + if (entry->seq == seq) { + fprintf(fp, "%llu %s %s %dms\n", + (unsigned long long) entry->timestamp, + entry->action, + entry->domain, + entry->latency_ms); + break; + } + } + } + fclose(fp); + g_log_flushed_seq = g_log_seq; +} + static void free_regex_rules(config_t *cfg) { int i; for (i = 0; i < cfg->regex_allow_count; i++) { @@ -1033,19 +1074,22 @@ int main(int argc, char **argv) { } while (g_running) { fd_set readfds; + struct timeval timeout; int maxfd = udp_fd; int ready; FD_ZERO(&readfds); FD_SET(udp_fd, &readfds); FD_SET(tcp_fd, &readfds); FD_SET(control_fd, &readfds); + timeout.tv_sec = 1; + timeout.tv_usec = 0; if (tcp_fd > maxfd) { maxfd = tcp_fd; } if (control_fd > maxfd) { maxfd = control_fd; } - ready = select(maxfd + 1, &readfds, NULL, NULL, NULL); + ready = select(maxfd + 1, &readfds, NULL, NULL, &timeout); if (ready < 0) { if (errno == EINTR) { continue; @@ -1061,7 +1105,9 @@ int main(int argc, char **argv) { if (FD_ISSET(control_fd, &readfds)) { handle_control(control_fd); } + flush_logs(); } + flush_logs(); close(udp_fd); close(tcp_fd); close(control_fd); From b6b2d6b083cb73913fe7c50837d8963e6a61365d Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 13:59:36 -0700 Subject: [PATCH 003/108] Add DNS daemon diagnostics controls --- .../ufirewall/activity/DataDumpActivity.java | 13 ++ .../activity/DiagnosticsActivity.java | 87 ++++++++++ .../ufirewall/dns/DnsHijackManager.java | 148 +++++++++++++++++- app/src/main/res/values/strings.xml | 8 + 4 files changed, 252 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/dev/ukanth/ufirewall/activity/DataDumpActivity.java b/app/src/main/java/dev/ukanth/ufirewall/activity/DataDumpActivity.java index cf2a8b234..fdd404023 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/activity/DataDumpActivity.java +++ b/app/src/main/java/dev/ukanth/ufirewall/activity/DataDumpActivity.java @@ -222,6 +222,8 @@ private String detectSectionType(String line) { return "ifconfig"; } else if (trimmed.contains("System info")) { return "system"; + } else if (trimmed.equals(getString(R.string.dns_diagnostics_title))) { + return "dns"; } else if (trimmed.contains("Preferences")) { return "preferences"; } else if (trimmed.equals(getString(R.string.application_errors_title))) { @@ -266,6 +268,17 @@ private void processSectionContent(String sectionType, String content) { systemCard.setVisibility(View.VISIBLE); systemContent.setText(trimmedContent); break; + + case "dns": + systemCard.setVisibility(View.VISIBLE); + String existingSystem = systemContent.getText().toString(); + String dnsContent = getString(R.string.dns_diagnostics_title) + "\n" + trimmedContent; + if (!existingSystem.isEmpty()) { + systemContent.setText(existingSystem + "\n\n" + dnsContent); + } else { + systemContent.setText(dnsContent); + } + break; case "preferences": preferencesCard.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/dev/ukanth/ufirewall/activity/DiagnosticsActivity.java b/app/src/main/java/dev/ukanth/ufirewall/activity/DiagnosticsActivity.java index b1ae788ed..063a31fda 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/activity/DiagnosticsActivity.java +++ b/app/src/main/java/dev/ukanth/ufirewall/activity/DiagnosticsActivity.java @@ -2,17 +2,34 @@ import android.content.Context; import android.os.Bundle; +import android.view.MenuItem; +import android.view.SubMenu; +import dev.ukanth.ufirewall.Api; import dev.ukanth.ufirewall.R; +import dev.ukanth.ufirewall.dns.DnsHijackManager; +import dev.ukanth.ufirewall.service.RootCommand; public class DiagnosticsActivity extends RulesActivity { + private static final int MENU_DNS_RELOAD = 101; + private static final int MENU_DNS_RESTART = 102; + private static final int MENU_DNS_STOP = 103; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setTitle(getString(R.string.log_hub_diagnostics)); } + @Override + protected void populateMenu(SubMenu sub) { + super.populateMenu(sub); + sub.add(0, MENU_DNS_RELOAD, 0, R.string.dns_diagnostics_reload).setIcon(R.drawable.ic_refresh); + sub.add(0, MENU_DNS_RESTART, 0, R.string.dns_diagnostics_restart).setIcon(R.drawable.ic_apply_menu); + sub.add(0, MENU_DNS_STOP, 0, R.string.dns_diagnostics_stop).setIcon(R.drawable.ic_clearlog); + } + @Override protected void populateData(final Context ctx) { result = new StringBuilder(); @@ -24,4 +41,74 @@ protected void populateData(final Context ctx) { protected boolean includeApplicationLog() { return false; } + + @Override + protected void appendIfconfig(final Context ctx) { + writeHeading(result, true, "ifconfig"); + updateLoadingState(getString(R.string.loading_system_info)); + Api.runIfconfig(ctx, new RootCommand() + .setLogging(true) + .setCallback(new RootCommand.Callback() { + public void cbFunc(RootCommand state) { + result.append(state.res); + appendDnsDiagnostics(ctx); + } + })); + } + + private void appendDnsDiagnostics(final Context ctx) { + writeHeading(result, true, getString(R.string.dns_diagnostics_title)); + result.append(DnsHijackManager.collectLocalDiagnostics(ctx)); + updateLoadingState(getString(R.string.dns_diagnostics_loading)); + new RootCommand() + .setLogging(true) + .setReopenShell(true) + .setCallback(new RootCommand.Callback() { + @Override + public void cbFunc(RootCommand state) { + result.append("\n[root checks]\n"); + if (state.res != null) { + result.append(state.res); + } else { + result.append("No root diagnostic output.\n"); + } + appendSystemInfo(ctx); + } + }) + .run(ctx, DnsHijackManager.buildRootDiagnosticsCommands(ctx)); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case MENU_DNS_RELOAD: + runDnsAction("reload", getString(R.string.dns_diagnostics_reload_queued)); + return true; + case MENU_DNS_RESTART: + runDnsAction("restart", getString(R.string.dns_diagnostics_restart_queued)); + return true; + case MENU_DNS_STOP: + runDnsAction("stop", getString(R.string.dns_diagnostics_stop_queued)); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + private void runDnsAction(String action, String successMessage) { + updateLoadingState(successMessage); + DnsHijackManager.runSupervisorAction(this, action, new RootCommand.Callback() { + @Override + public void cbFunc(RootCommand state) { + runOnUiThread(() -> { + if (state.exitCode == 0) { + Api.toast(DiagnosticsActivity.this, successMessage); + } else { + Api.toast(DiagnosticsActivity.this, getString(R.string.error_apply)); + } + populateData(DiagnosticsActivity.this); + }); + } + }); + } } diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java index 60358f46d..bf6645150 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java @@ -1,17 +1,25 @@ package dev.ukanth.ufirewall.dns; import android.content.Context; +import android.net.LocalSocket; +import android.net.LocalSocketAddress; import android.os.Build; import android.util.Log; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.List; import java.util.Locale; +import dev.ukanth.ufirewall.Api; +import dev.ukanth.ufirewall.R; +import dev.ukanth.ufirewall.service.RootCommand; import dev.ukanth.ufirewall.util.ApplicationErrorLog; import dev.ukanth.ufirewall.util.G; @@ -67,19 +75,151 @@ public static void appendPurgeCommands(Context context, List commands, b } public static void requestReload(Context context) { + runSupervisorAction(context, "reload", null); + } + + public static void runSupervisorAction(Context context, String action, RootCommand.Callback callback) { if (context == null) { return; } - if (!prepareDaemon(context)) { + String safeAction = normalizeSupervisorAction(action); + if (safeAction == null) { + failSupervisorAction(context, callback, "DNS hijacker supervisor action was invalid: " + action); + return; + } + if (!"stop".equals(safeAction) && !prepareDaemon(context)) { + failSupervisorAction(context, callback, "DNS hijacker " + safeAction + " requested but daemon files could not be prepared"); + return; + } + File supervisor = new File(workDir(context), SUPERVISOR); + if (!supervisor.exists()) { + failSupervisorAction(context, callback, "DNS hijacker " + safeAction + " requested but supervisor script is missing"); return; } - List commands = new java.util.ArrayList<>(); - commands.add(shellQuote(supervisorPath(context)) + " reload"); - new dev.ukanth.ufirewall.service.RootCommand() + List commands = new ArrayList<>(); + commands.add(shellQuote(supervisor.getAbsolutePath()) + " " + safeAction); + ApplicationErrorLog.add(context, "DNS hijacker supervisor action queued: " + safeAction); + new RootCommand() .setLogging(true) + .setReopenShell(true) + .setFailureToast(R.string.error_apply) + .setCallback(callback) .run(context.getApplicationContext(), commands); } + public static String collectLocalDiagnostics(Context context) { + StringBuilder out = new StringBuilder(); + File dir = workDir(context); + File daemon = new File(dir, DAEMON_NAME); + File supervisor = new File(dir, SUPERVISOR); + File config = new File(dir, CONF); + File pid = new File(dir, PID); + File socket = new File(dir, SOCKET); + File queryLog = new File(dir, QUERY_LOG); + File supervisorLog = new File(dir, SUPERVISOR_LOG); + + out.append("enabled_pref=").append(G.enableDnsHijack()).append('\n'); + out.append("port=").append(G.dnsHijackPort(DEFAULT_PORT)).append('\n'); + out.append("fail_open=").append(G.dnsHijackFailOpen()).append('\n'); + out.append("strict_mode=").append(G.dnsHijackStrictMode()).append('\n'); + out.append("timeout_ms=").append(G.dnsHijackTimeoutMs()).append('\n'); + appendFileInfo(out, "work_dir", dir); + appendFileInfo(out, "daemon", daemon); + appendFileInfo(out, "supervisor", supervisor); + appendFileInfo(out, "config", config); + appendFileInfo(out, "pid", pid); + appendFileInfo(out, "control_socket", socket); + appendFileInfo(out, "query_log", queryLog); + appendFileInfo(out, "supervisor_log", supervisorLog); + + out.append("\n[control status]\n"); + out.append(queryControl(context, "status")); + out.append("\n[recent queries]\n"); + String logs = queryControl(context, "logs"); + out.append(logs.trim().isEmpty() ? "no daemon query logs reported\n" : logs); + return out.toString(); + } + + public static List buildRootDiagnosticsCommands(Context context) { + List commands = new ArrayList<>(); + String supervisor = shellQuote(supervisorPath(context)); + String iptables = shellQuote(Api.getBinaryPath(context, false)); + String ip6tables = shellQuote(Api.getBinaryPath(context, true)); + + commands.add("echo '[supervisor status]'"); + commands.add("if [ -x " + supervisor + " ]; then " + supervisor + " status 2>&1; else echo 'supervisor missing'; fi"); + commands.add("echo '[pid]'"); + commands.add("cat " + shellQuote(new File(workDir(context), PID).getAbsolutePath()) + " 2>&1 || true"); + commands.add("echo '[IPv4 DNS NAT OUTPUT]'"); + commands.add(iptables + " -t nat -S OUTPUT 2>&1 | grep 'afwall-dns' || true"); + commands.add("echo '[IPv4 DNS NAT chains]'"); + commands.add(iptables + " -t nat -S " + CHAIN_V4 + " 2>&1 || true"); + commands.add(iptables + " -t nat -S " + CHAIN_V4_PRE + " 2>&1 || true"); + commands.add("echo '[IPv6 DNS NAT OUTPUT]'"); + commands.add(ip6tables + " -t nat -S OUTPUT 2>&1 | grep 'afwall-dns6' || true"); + commands.add("echo '[IPv6 DNS NAT chains]'"); + commands.add(ip6tables + " -t nat -S " + CHAIN_V6 + " 2>&1 || true"); + commands.add(ip6tables + " -t nat -S " + CHAIN_V6_PRE + " 2>&1 || true"); + return commands; + } + + private static void failSupervisorAction(Context context, RootCommand.Callback callback, String message) { + ApplicationErrorLog.add(context, message); + if (callback == null) { + return; + } + RootCommand state = new RootCommand(); + state.exitCode = 1; + state.res = new StringBuilder(message).append('\n'); + callback.cbFunc(state); + } + + private static String queryControl(Context context, String command) { + File socketFile = new File(workDir(context), SOCKET); + if (!socketFile.exists()) { + return "control socket missing\n"; + } + try (LocalSocket socket = new LocalSocket()) { + socket.setSoTimeout(1500); + socket.connect(new LocalSocketAddress(socketFile.getAbsolutePath(), LocalSocketAddress.Namespace.FILESYSTEM)); + OutputStream output = socket.getOutputStream(); + output.write((command + "\n").getBytes(StandardCharsets.UTF_8)); + output.flush(); + socket.shutdownOutput(); + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + InputStream input = socket.getInputStream(); + byte[] chunk = new byte[4096]; + int read; + while ((read = input.read(chunk)) != -1) { + buffer.write(chunk, 0, read); + } + String result = buffer.toString("UTF-8"); + return result.trim().isEmpty() ? "empty response\n" : result; + } catch (IOException e) { + return "control socket error: " + e.getMessage() + "\n"; + } + } + + private static void appendFileInfo(StringBuilder out, String label, File file) { + out.append(label).append('=').append(file.getAbsolutePath()); + out.append(" exists=").append(file.exists()); + if (file.exists()) { + out.append(" size=").append(file.length()); + out.append(" canExecute=").append(file.canExecute()); + } + out.append('\n'); + } + + private static String normalizeSupervisorAction(String action) { + if ("start".equals(action) || "stop".equals(action) + || "restart".equals(action) || "reload".equals(action) + || "status".equals(action)) { + return action; + } + return null; + } + private static void appendRedirectRules(List commands, boolean ipv6) { int port = G.dnsHijackPort(DEFAULT_PORT); String chain = ipv6 ? CHAIN_V6 : CHAIN_V4; diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fb9fe6ae2..6d7ff3842 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -323,6 +323,14 @@ Regular expressions that allow matching queries. Regex block rules Regular expressions that block matching queries. + DNS daemon diagnostics + Loading DNS daemon diagnostics + Reload DNS daemon + Restart DNS daemon + Stop DNS daemon + DNS daemon reload requested. + DNS daemon restart requested. + DNS daemon stop requested. Log Hide app icons Improve performance by disabling app icons in the main view From 27e3d879df7316a8f3acd0d8d6017415b988cc68 Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 14:06:25 -0700 Subject: [PATCH 004/108] Add DNS blocklist import support --- .../main/assets/dnsd/arm64-v8a/afwall_dnsd | Bin 20264 -> 21496 bytes .../main/assets/dnsd/armeabi-v7a/afwall_dnsd | Bin 15552 -> 16288 bytes app/src/main/assets/dnsd/x86/afwall_dnsd | Bin 19168 -> 20560 bytes app/src/main/assets/dnsd/x86_64/afwall_dnsd | Bin 20784 -> 22128 bytes .../ufirewall/dns/DnsBlocklistManager.java | 394 ++++++++++++++++++ .../ufirewall/dns/DnsHijackManager.java | 10 + .../preferences/RulesPreferenceFragment.java | 104 ++++- .../java/dev/ukanth/ufirewall/util/G.java | 5 + app/src/main/res/values/strings.xml | 10 + app/src/main/res/xml/rules_preferences.xml | 24 ++ dnsdaemon/jni/afwall_dnsd.c | 57 ++- 11 files changed, 602 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/dev/ukanth/ufirewall/dns/DnsBlocklistManager.java diff --git a/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd b/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd index 3e5522fc20d45374fe8f5d10d10473aa6c485648..8726bc7cffa4101245d6b60931a985c78f27804d 100755 GIT binary patch delta 9436 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 delta 8173 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 RlIgLf79A-Gi+m2o{6CVr8S(%C diff --git a/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd b/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd index 5fa8c3b8df26a2975d343268250892d16fa292cf..df8d47ef9f5f8396c826d7b2bf2dc7bd8d63f778 100755 GIT binary patch delta 6151 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 I7#Q{U-`bz{CjbBd delta 5382 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 ARsaA1 diff --git a/app/src/main/assets/dnsd/x86/afwall_dnsd b/app/src/main/assets/dnsd/x86/afwall_dnsd index 5a71ac57bdaf4a49a0a4df555931194914b6a744..3a167362aa9135151477ee32455a2d48abe7f604 100755 GIT binary patch delta 8189 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 PMnrFB>=V8{ecb;63RhBt delta 6795 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 diff --git a/app/src/main/assets/dnsd/x86_64/afwall_dnsd b/app/src/main/assets/dnsd/x86_64/afwall_dnsd index 7df4384fd2132203935d507645781c5c5c0d6068..56c5b6c5a8dfbb126f04eea4ea96d48dc9003d75 100755 GIT binary patch delta 10842 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 300) { + result.invalid++; + result.notes.append(urlString).append(": HTTP ").append(code).append('\n'); + return; + } + parseStream(connection.getInputStream(), result); + } catch (IOException e) { + result.invalid++; + result.notes.append(urlString).append(": ").append(e.getMessage()).append('\n'); + } finally { + if (connection != null) { + connection.disconnect(); + } + } + } + + private static void parseStream(InputStream input, Result result) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); + String line; + while ((line = reader.readLine()) != null) { + parseLine(line, result); + } + } + + private static void parseLine(String raw, Result result) { + result.lines++; + String line = raw == null ? "" : raw.trim(); + if (line.isEmpty() || line.startsWith("#") || line.startsWith("!") || line.startsWith("[")) { + result.skipped++; + return; + } + + if (line.startsWith("@@")) { + result.skipped++; + return; + } + + if (line.startsWith("||")) { + String domain = normalizeDomain(line.substring(2).replaceFirst("[\\^/$].*$", "")); + addDomain(result.suffixRules, domain, result); + return; + } + + if (line.startsWith("0.0.0.0 ") || line.startsWith("127.0.0.1 ") + || line.startsWith("::1 ") || line.startsWith(":: ")) { + String[] parts = line.split("\\s+"); + if (parts.length >= 2) { + String domain = normalizeDomain(parts[1]); + addDomain(result.exactRules, domain, result); + return; + } + } + + String[] parts = line.split("\\s+"); + if (parts.length > 1 && isAddressToken(parts[0])) { + String domain = normalizeDomain(parts[1]); + addDomain(result.exactRules, domain, result); + return; + } + + String candidate = line.split("[#\\s]")[0]; + if (candidate.startsWith("*.") || candidate.startsWith(".")) { + addDomain(result.suffixRules, normalizeDomain(candidate), result); + } else { + addDomain(result.exactRules, normalizeDomain(candidate), result); + } + } + + private static void addDomain(Set target, String domain, Result result) { + if (domain == null || domain.isEmpty() || !DOMAIN_PATTERN.matcher(domain).matches() + || "localhost".equals(domain)) { + result.invalid++; + return; + } + if (!target.add(domain)) { + result.duplicates++; + } + } + + private static String normalizeDomain(String raw) { + if (raw == null) { + return ""; + } + String domain = raw.trim().toLowerCase(Locale.US); + domain = domain.replaceFirst("^https?://", ""); + domain = domain.replaceFirst("/.*$", ""); + domain = domain.replaceFirst("^\\*\\.", ""); + domain = domain.replaceFirst("^\\.", ""); + domain = domain.replaceFirst("\\.$", ""); + return domain; + } + + private static boolean isAddressToken(String token) { + return token.matches("^[0-9.]+$") || token.contains(":"); + } + + private static void activate(Context context, Result result) throws IOException { + if (!result.hasRules()) { + result.failed = true; + result.message = "No valid DNS blocklist entries found"; + return; + } + + File dir = blocklistDir(context); + if (!dir.exists() && !dir.mkdirs()) { + throw new IOException("Unable to create DNS blocklist directory"); + } + File exact = new File(dir, EXACT_FILE); + File suffix = new File(dir, SUFFIX_FILE); + copyIfExists(exact, new File(dir, EXACT_BACKUP)); + copyIfExists(suffix, new File(dir, SUFFIX_BACKUP)); + writeRuleFile(new File(dir, EXACT_FILE + ".tmp"), exact, result.exactRules); + writeRuleFile(new File(dir, SUFFIX_FILE + ".tmp"), suffix, result.suffixRules); + writeMetadata(context, result.sourceLabel, result.exactRules.size(), result.suffixRules.size(), + result.duplicates, result.invalid, result.skipped); + result.message = "Activated DNS blocklist: " + result.exactRules.size() + + " exact, " + result.suffixRules.size() + " wildcard"; + ApplicationErrorLog.add(context, result.message); + } + + private static void writeRuleFile(File tmp, File target, Set rules) throws IOException { + if (tmp.exists() && !tmp.delete()) { + throw new IOException("Unable to replace temporary " + tmp.getName()); + } + try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(tmp, false), StandardCharsets.UTF_8)) { + for (String rule : rules) { + writer.write(rule); + writer.write('\n'); + } + } + if (target.exists() && !target.delete()) { + throw new IOException("Unable to replace " + target.getName()); + } + if (!tmp.renameTo(target)) { + throw new IOException("Unable to activate " + target.getName()); + } + } + + private static void writeMetadata(Context context, String source, int exact, int suffix, + int duplicates, int invalid, int skipped) throws IOException { + File meta = new File(blocklistDir(context), META_FILE); + String timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US).format(new Date()); + try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(meta, false), StandardCharsets.UTF_8)) { + writer.write("updated="); + writer.write(timestamp); + writer.write('\n'); + writer.write("source="); + writer.write(source == null ? "unknown" : source); + writer.write('\n'); + writer.write("exact="); + writer.write(String.valueOf(exact)); + writer.write('\n'); + writer.write("wildcard="); + writer.write(String.valueOf(suffix)); + writer.write('\n'); + writer.write("duplicates="); + writer.write(String.valueOf(duplicates)); + writer.write('\n'); + writer.write("invalid="); + writer.write(String.valueOf(invalid)); + writer.write('\n'); + writer.write("skipped="); + writer.write(String.valueOf(skipped)); + writer.write('\n'); + } + } + + private static int countLines(File file) throws IOException { + if (!file.exists()) { + return 0; + } + int count = 0; + try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) { + while (reader.readLine() != null) { + count++; + } + } + return count; + } + + private static void copyIfExists(File source, File target) throws IOException { + if (!source.exists()) { + return; + } + try (FileInputStream input = new FileInputStream(source); + FileOutputStream output = new FileOutputStream(target, false)) { + byte[] buffer = new byte[8192]; + int read; + while ((read = input.read(buffer)) != -1) { + output.write(buffer, 0, read); + } + } + } + + private static File blocklistDir(Context context) { + return context.getApplicationContext().getDir(DIR, Context.MODE_PRIVATE); + } + + public static final class Result { + private final Set exactRules = new LinkedHashSet<>(); + private final Set suffixRules = new LinkedHashSet<>(); + private final StringBuilder notes = new StringBuilder(); + private final String sourceLabel; + public int lines; + public int duplicates; + public int invalid; + public int skipped; + public int sources; + public boolean failed; + public String message = ""; + + private Result(String sourceLabel) { + this.sourceLabel = sourceLabel; + } + + public boolean hasRules() { + return !exactRules.isEmpty() || !suffixRules.isEmpty(); + } + + public String summary() { + StringBuilder summary = new StringBuilder(); + summary.append(message); + summary.append("\nExact: ").append(exactRules.size()); + summary.append("\nWildcard: ").append(suffixRules.size()); + summary.append("\nDuplicates: ").append(duplicates); + summary.append("\nInvalid: ").append(invalid); + summary.append("\nSkipped: ").append(skipped); + if (notes.length() > 0) { + summary.append("\n\n").append(notes); + } + return summary.toString(); + } + } +} diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java index bf6645150..c9b9a3a3e 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java @@ -123,6 +123,8 @@ public static String collectLocalDiagnostics(Context context) { out.append("fail_open=").append(G.dnsHijackFailOpen()).append('\n'); out.append("strict_mode=").append(G.dnsHijackStrictMode()).append('\n'); out.append("timeout_ms=").append(G.dnsHijackTimeoutMs()).append('\n'); + out.append("\n[blocklists]\n"); + out.append(DnsBlocklistManager.getSummary(context)).append('\n'); appendFileInfo(out, "work_dir", dir); appendFileInfo(out, "daemon", daemon); appendFileInfo(out, "supervisor", supervisor); @@ -331,10 +333,18 @@ private static String buildConfig(Context context) { appendConfigEntries(config, "block_suffix", G.dnsHijackBlockSuffix()); appendConfigEntries(config, "allow_regex", G.dnsHijackAllowRegex()); appendConfigEntries(config, "block_regex", G.dnsHijackBlockRegex()); + appendConfigFile(config, "block_exact_file", DnsBlocklistManager.exactBlockFile(context)); + appendConfigFile(config, "block_suffix_file", DnsBlocklistManager.suffixBlockFile(context)); return config.toString(); } + private static void appendConfigFile(StringBuilder config, String key, File file) { + if (file.exists() && file.length() > 0) { + config.append(key).append('=').append(file.getAbsolutePath()).append('\n'); + } + } + private static void appendConfigEntries(StringBuilder config, String key, String raw) { if (raw == null) { return; diff --git a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java index 9f20a620f..8e8fae0b2 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java +++ b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java @@ -1,21 +1,29 @@ package dev.ukanth.ufirewall.preferences; import android.app.Activity; +import android.content.ActivityNotFoundException; import android.content.Context; +import android.content.Intent; import android.content.SharedPreferences; +import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; import android.preference.CheckBoxPreference; import android.preference.Preference; import android.preference.PreferenceFragment; import android.preference.SwitchPreference; +import com.afollestad.materialdialogs.MaterialDialog; + import java.io.File; import java.util.regex.Matcher; import java.util.regex.Pattern; import dev.ukanth.ufirewall.Api; import dev.ukanth.ufirewall.R; +import dev.ukanth.ufirewall.dns.DnsBlocklistManager; import dev.ukanth.ufirewall.dns.DnsHijackManager; import dev.ukanth.ufirewall.service.RootCommand; import dev.ukanth.ufirewall.util.G; @@ -23,6 +31,7 @@ public class RulesPreferenceFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener { + private static final int REQUEST_DNS_BLOCKLIST_FILE = 5301; private Context ctx; @@ -46,6 +55,34 @@ public void onCreate(Bundle savedInstanceState) { CheckBoxPreference roamPreference = (CheckBoxPreference) findPreference("enableRoam"); roamPreference.setEnabled(true); } + + wireDnsBlocklistActions(); + } + + private void wireDnsBlocklistActions() { + Preference importBlocklist = findPreference("dnsHijackImportBlocklist"); + if (importBlocklist != null) { + importBlocklist.setOnPreferenceClickListener(preference -> { + openDnsBlocklistPicker(); + return true; + }); + } + + Preference updateBlocklists = findPreference("dnsHijackUpdateBlocklists"); + if (updateBlocklists != null) { + updateBlocklists.setOnPreferenceClickListener(preference -> { + runDnsBlocklistUpdate(); + return true; + }); + } + + Preference rollbackBlocklist = findPreference("dnsHijackRollbackBlocklist"); + if (rollbackBlocklist != null) { + rollbackBlocklist.setOnPreferenceClickListener(preference -> { + runDnsBlocklistRollback(); + return true; + }); + } } private void updateRuleStatus() { @@ -140,6 +177,70 @@ public void onAttach(Activity activity) { } } + private void openDnsBlocklistPicker() { + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType("text/*"); + try { + startActivityForResult(intent, REQUEST_DNS_BLOCKLIST_FILE); + } catch (ActivityNotFoundException e) { + Intent fallback = new Intent(Intent.ACTION_GET_CONTENT); + fallback.addCategory(Intent.CATEGORY_OPENABLE); + fallback.setType("*/*"); + startActivityForResult(fallback, REQUEST_DNS_BLOCKLIST_FILE); + } + } + + private void runDnsBlocklistUpdate() { + runBlocklistTask(() -> DnsBlocklistManager.updateFromConfiguredUrls(ctx)); + } + + private void runDnsBlocklistRollback() { + runBlocklistTask(() -> DnsBlocklistManager.restorePrevious(ctx)); + } + + private void runBlocklistTask(BlocklistTask task) { + new Thread(() -> { + DnsBlocklistManager.Result result = task.run(); + new Handler(Looper.getMainLooper()).post(() -> handleBlocklistResult(result)); + }).start(); + } + + private void handleBlocklistResult(DnsBlocklistManager.Result result) { + if (getActivity() == null || result == null) { + return; + } + if (!result.failed) { + Api.setRulesUpToDate(false); + if (G.enableDnsHijack()) { + DnsHijackManager.requestReload(ctx); + } + Api.toast(ctx, getString(R.string.dns_hijack_blocklist_active)); + } else { + Api.toast(ctx, getString(R.string.dns_hijack_blocklist_failed)); + } + new MaterialDialog.Builder(getActivity()) + .title(result.failed ? R.string.dns_hijack_blocklist_failed : R.string.dns_hijack_blocklist_active) + .content(result.summary()) + .positiveText(R.string.OK) + .show(); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == REQUEST_DNS_BLOCKLIST_FILE && resultCode == Activity.RESULT_OK && data != null) { + Uri uri = data.getData(); + if (uri != null) { + runBlocklistTask(() -> DnsBlocklistManager.importFromUri(ctx, uri)); + } + } + } + + private interface BlocklistTask { + DnsBlocklistManager.Result run(); + } + @Override public void onResume() { super.onResume(); @@ -333,6 +434,7 @@ private boolean isDnsHijackPreference(String key) { || key.equals("dnsHijackBlockExact") || key.equals("dnsHijackBlockSuffix") || key.equals("dnsHijackAllowRegex") - || key.equals("dnsHijackBlockRegex")); + || key.equals("dnsHijackBlockRegex") + || key.equals("dnsHijackBlocklistUrls")); } } diff --git a/app/src/main/java/dev/ukanth/ufirewall/util/G.java b/app/src/main/java/dev/ukanth/ufirewall/util/G.java index b31ffd4a9..e6c76066a 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/util/G.java +++ b/app/src/main/java/dev/ukanth/ufirewall/util/G.java @@ -182,6 +182,7 @@ public static Context getContext() { private static final String DNS_HIJACK_BLOCK_SUFFIX = "dnsHijackBlockSuffix"; private static final String DNS_HIJACK_ALLOW_REGEX = "dnsHijackAllowRegex"; private static final String DNS_HIJACK_BLOCK_REGEX = "dnsHijackBlockRegex"; + private static final String DNS_HIJACK_BLOCKLIST_URLS = "dnsHijackBlocklistUrls"; private static final String SHOW_ALL_APPS = "showAllApps"; @@ -320,6 +321,10 @@ public static String dnsHijackBlockRegex() { return gPrefs.getString(DNS_HIJACK_BLOCK_REGEX, ""); } + public static String dnsHijackBlocklistUrls() { + return gPrefs.getString(DNS_HIJACK_BLOCKLIST_URLS, ""); + } + private static int readIntPreference(String key, int fallback, int min, int max) { String value = gPrefs.getString(key, String.valueOf(fallback)); try { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6d7ff3842..cd54624f6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -323,6 +323,16 @@ Regular expressions that allow matching queries. Regex block rules Regular expressions that block matching queries. + Blocklist URLs + One remote hosts, domain, Pi-hole, or AdBlock-style list URL per line. + Import DNS blocklist file + Use the system picker to import a hosts, domain, Pi-hole, or AdBlock-style list. + Update DNS blocklists + Download configured URLs, compile them, and reload the daemon. + Rollback DNS blocklist + Restore the previous compiled DNS blocklist files. + DNS blocklist activated. Reapply firewall rules if DNS capture is not already running. + DNS blocklist update failed. DNS daemon diagnostics Loading DNS daemon diagnostics Reload DNS daemon diff --git a/app/src/main/res/xml/rules_preferences.xml b/app/src/main/res/xml/rules_preferences.xml index 6aa692637..f8b5cdb79 100644 --- a/app/src/main/res/xml/rules_preferences.xml +++ b/app/src/main/res/xml/rules_preferences.xml @@ -147,6 +147,30 @@ android:key="dnsHijackBlockRegex" android:summary="@string/dns_hijack_block_regex_summary" android:title="@string/dns_hijack_block_regex_title" /> + + + + + + + + diff --git a/dnsdaemon/jni/afwall_dnsd.c b/dnsdaemon/jni/afwall_dnsd.c index d923df2e9..141bed828 100644 --- a/dnsdaemon/jni/afwall_dnsd.c +++ b/dnsdaemon/jni/afwall_dnsd.c @@ -31,7 +31,7 @@ #define MAX_PACKET 4096 #define MAX_DOMAIN 256 -#define MAX_RULES 8192 +#define MAX_RULES 32768 #define MAX_REGEX 128 #define MAX_UPSTREAMS 8 #define CACHE_SIZE 1024 @@ -678,6 +678,9 @@ static bool parse_upstream(config_t *cfg, const char *value) { return true; } +static void load_string_rule_file(string_rule_t *rules, int *count, const char *path); +static void load_regex_rule_file(regex_rule_t *rules, int *count, const char *path); + static bool load_config(const char *path, config_t *new_cfg) { FILE *fp; char line[1024]; @@ -727,16 +730,28 @@ static bool load_config(const char *path, config_t *new_cfg) { parse_upstream(new_cfg, value); } else if (strcmp(key, "allow_exact") == 0) { add_string_rule(new_cfg->exact_allow, &new_cfg->exact_allow_count, value); + } else if (strcmp(key, "allow_exact_file") == 0) { + load_string_rule_file(new_cfg->exact_allow, &new_cfg->exact_allow_count, value); } else if (strcmp(key, "allow_suffix") == 0) { add_string_rule(new_cfg->suffix_allow, &new_cfg->suffix_allow_count, value); + } else if (strcmp(key, "allow_suffix_file") == 0) { + load_string_rule_file(new_cfg->suffix_allow, &new_cfg->suffix_allow_count, value); } else if (strcmp(key, "block_exact") == 0) { add_string_rule(new_cfg->exact_block, &new_cfg->exact_block_count, value); + } else if (strcmp(key, "block_exact_file") == 0) { + load_string_rule_file(new_cfg->exact_block, &new_cfg->exact_block_count, value); } else if (strcmp(key, "block_suffix") == 0) { add_string_rule(new_cfg->suffix_block, &new_cfg->suffix_block_count, value); + } else if (strcmp(key, "block_suffix_file") == 0) { + load_string_rule_file(new_cfg->suffix_block, &new_cfg->suffix_block_count, value); } else if (strcmp(key, "allow_regex") == 0) { add_regex_rule(new_cfg->regex_allow, &new_cfg->regex_allow_count, value); + } else if (strcmp(key, "allow_regex_file") == 0) { + load_regex_rule_file(new_cfg->regex_allow, &new_cfg->regex_allow_count, value); } else if (strcmp(key, "block_regex") == 0) { add_regex_rule(new_cfg->regex_block, &new_cfg->regex_block_count, value); + } else if (strcmp(key, "block_regex_file") == 0) { + load_regex_rule_file(new_cfg->regex_block, &new_cfg->regex_block_count, value); } } fclose(fp); @@ -749,6 +764,46 @@ static bool load_config(const char *path, config_t *new_cfg) { return true; } +static void load_string_rule_file(string_rule_t *rules, int *count, const char *path) { + FILE *fp; + char line[1024]; + if (path == NULL || path[0] == '\0') { + return; + } + fp = fopen(path, "r"); + if (fp == NULL) { + return; + } + while (fgets(line, sizeof(line), fp) != NULL) { + trim(line); + if (line[0] == '\0' || line[0] == '#') { + continue; + } + add_string_rule(rules, count, line); + } + fclose(fp); +} + +static void load_regex_rule_file(regex_rule_t *rules, int *count, const char *path) { + FILE *fp; + char line[1024]; + if (path == NULL || path[0] == '\0') { + return; + } + fp = fopen(path, "r"); + if (fp == NULL) { + return; + } + while (fgets(line, sizeof(line), fp) != NULL) { + trim(line); + if (line[0] == '\0' || line[0] == '#') { + continue; + } + add_regex_rule(rules, count, line); + } + fclose(fp); +} + static bool reload_config(void) { config_t next; if (!load_config(g_config_path, &next)) { From fefbd857e0b6959ae86e483732c7eed312257a73 Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 14:13:00 -0700 Subject: [PATCH 005/108] Add DNS live query viewer --- app/src/main/AndroidManifest.xml | 3 + .../activity/DnsQueriesActivity.java | 197 ++++++++++++++++++ .../ufirewall/activity/LogHubActivity.java | 16 ++ .../ufirewall/dns/DnsHijackManager.java | 103 +++++++++ .../java/dev/ukanth/ufirewall/util/G.java | 43 ++++ .../main/res/layout/activity_dns_queries.xml | 35 ++++ app/src/main/res/layout/log_hub.xml | 52 +++++ app/src/main/res/values/strings.xml | 9 + 8 files changed, 458 insertions(+) create mode 100644 app/src/main/java/dev/ukanth/ufirewall/activity/DnsQueriesActivity.java create mode 100644 app/src/main/res/layout/activity_dns_queries.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8bb863f3e..c4e9665a3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -162,6 +162,9 @@ + diff --git a/app/src/main/java/dev/ukanth/ufirewall/activity/DnsQueriesActivity.java b/app/src/main/java/dev/ukanth/ufirewall/activity/DnsQueriesActivity.java new file mode 100644 index 000000000..058eb0ffd --- /dev/null +++ b/app/src/main/java/dev/ukanth/ufirewall/activity/DnsQueriesActivity.java @@ -0,0 +1,197 @@ +package dev.ukanth.ufirewall.activity; + +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.view.Menu; +import android.view.MenuItem; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import android.widget.TextView; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; + +import com.afollestad.materialdialogs.MaterialDialog; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import dev.ukanth.ufirewall.Api; +import dev.ukanth.ufirewall.R; +import dev.ukanth.ufirewall.dns.DnsHijackManager; +import dev.ukanth.ufirewall.util.G; +import dev.ukanth.ufirewall.util.ThemeHelper; + +public class DnsQueriesActivity extends AppCompatActivity { + + private static final int MENU_REFRESH = 1; + private static final int MENU_COPY = 2; + private static final long REFRESH_MS = 2500L; + + private final Handler handler = new Handler(Looper.getMainLooper()); + private final ExecutorService executor = Executors.newSingleThreadExecutor(); + private final List entries = new ArrayList<>(); + private ArrayAdapter adapter; + private TextView status; + + private final Runnable autoRefresh = new Runnable() { + @Override + public void run() { + loadQueries(false); + handler.postDelayed(this, REFRESH_MS); + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setTheme(G.getSelectedThemeStyle(this)); + setContentView(R.layout.activity_dns_queries); + + Toolbar toolbar = findViewById(R.id.dns_queries_toolbar); + setSupportActionBar(toolbar); + setTitle(getString(R.string.dns_queries_title)); + toolbar.setNavigationOnClickListener(v -> finish()); + if (getSupportActionBar() != null) { + getSupportActionBar().setHomeButtonEnabled(true); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + ThemeHelper.apply(this); + + status = findViewById(R.id.dns_queries_status); + ListView list = findViewById(R.id.dns_queries_list); + adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, new ArrayList<>()); + list.setAdapter(adapter); + list.setOnItemClickListener((parent, view, position, id) -> showQueryActions(entries.get(position))); + loadQueries(true); + } + + @Override + protected void onResume() { + super.onResume(); + handler.postDelayed(autoRefresh, REFRESH_MS); + } + + @Override + protected void onPause() { + handler.removeCallbacks(autoRefresh); + super.onPause(); + } + + @Override + protected void onDestroy() { + executor.shutdownNow(); + super.onDestroy(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + menu.add(0, MENU_REFRESH, 0, R.string.refresh).setIcon(R.drawable.ic_refresh); + menu.add(0, MENU_COPY, 0, R.string.copy).setIcon(R.drawable.ic_copy); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + case MENU_REFRESH: + loadQueries(true); + return true; + case MENU_COPY: + Api.copyToClipboard(this, buildTextDump()); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + private void loadQueries(boolean showLoading) { + if (executor.isShutdown()) { + return; + } + if (showLoading) { + status.setText(R.string.loading); + } + executor.execute(() -> { + List latest = DnsHijackManager.getRecentQueries(this); + runOnUiThread(() -> updateQueries(latest)); + }); + } + + private void updateQueries(List latest) { + entries.clear(); + adapter.clear(); + for (int i = latest.size() - 1; i >= 0; i--) { + DnsHijackManager.QueryEntry entry = latest.get(i); + entries.add(entry); + adapter.add(formatEntry(entry)); + } + adapter.notifyDataSetChanged(); + status.setText(getString(R.string.dns_queries_status, latest.size())); + } + + private String formatEntry(DnsHijackManager.QueryEntry entry) { + String time = entry.timestamp > 0 + ? new SimpleDateFormat("HH:mm:ss", Locale.US).format(new Date(entry.timestamp * 1000L)) + : "--:--:--"; + return time + " " + entry.action + " " + entry.domain + " " + entry.latency; + } + + private void showQueryActions(DnsHijackManager.QueryEntry entry) { + if (entry == null || !entry.hasDomain()) { + return; + } + new MaterialDialog.Builder(this) + .title(entry.domain) + .items(new CharSequence[]{ + getString(R.string.dns_query_allow_exact), + getString(R.string.dns_query_allow_suffix), + getString(R.string.dns_query_block_exact), + getString(R.string.dns_query_block_suffix) + }) + .itemsCallback((dialog, view, which, text) -> applyQueryAction(entry, which)) + .negativeText(R.string.Cancel) + .show(); + } + + private void applyQueryAction(DnsHijackManager.QueryEntry entry, int which) { + int action; + switch (which) { + case 0: + action = DnsHijackManager.RULE_ALLOW_EXACT; + break; + case 1: + action = DnsHijackManager.RULE_ALLOW_SUFFIX; + break; + case 2: + action = DnsHijackManager.RULE_BLOCK_EXACT; + break; + case 3: + action = DnsHijackManager.RULE_BLOCK_SUFFIX; + break; + default: + return; + } + boolean added = DnsHijackManager.addRuleFromQuery(this, entry, action); + Api.setRulesUpToDate(false); + Api.toast(this, getString(added ? R.string.dns_query_rule_added : R.string.dns_query_rule_exists)); + loadQueries(false); + } + + private String buildTextDump() { + StringBuilder dump = new StringBuilder(); + for (DnsHijackManager.QueryEntry entry : entries) { + dump.append(entry.displayLine()).append('\n'); + } + return dump.toString(); + } +} diff --git a/app/src/main/java/dev/ukanth/ufirewall/activity/LogHubActivity.java b/app/src/main/java/dev/ukanth/ufirewall/activity/LogHubActivity.java index c9108024b..e4803eeda 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/activity/LogHubActivity.java +++ b/app/src/main/java/dev/ukanth/ufirewall/activity/LogHubActivity.java @@ -41,6 +41,7 @@ import dev.ukanth.ufirewall.BuildConfig; import dev.ukanth.ufirewall.R; import dev.ukanth.ufirewall.Api; +import dev.ukanth.ufirewall.dns.DnsHijackManager; import dev.ukanth.ufirewall.log.Log; import dev.ukanth.ufirewall.log.LogInfo; import dev.ukanth.ufirewall.service.RootCommand; @@ -56,6 +57,7 @@ public class LogHubActivity extends AppCompatActivity { private static final int EXPORT_IPTABLES_IPV6 = 2; private static final int EXPORT_APPLICATION_LOG = 3; private static final int EXPORT_APPLICATION_ERRORS = 4; + private static final int EXPORT_DNS_QUERIES = 5; @Override protected void onCreate(Bundle savedInstanceState) { @@ -75,6 +77,7 @@ protected void onCreate(Bundle savedInstanceState) { } findViewById(R.id.log_hub_blocked_requests).setOnClickListener(v -> openBlockedRequests()); + findViewById(R.id.log_hub_dns_queries).setOnClickListener(v -> startActivity(new Intent(this, DnsQueriesActivity.class))); findViewById(R.id.log_hub_iptables).setOnClickListener(v -> startActivity(new Intent(this, RulesActivity.class))); findViewById(R.id.log_hub_diagnostics).setOnClickListener(v -> startActivity(new Intent(this, DiagnosticsActivity.class))); findViewById(R.id.log_hub_application_log).setOnClickListener(v -> startActivity(new Intent(this, ApplicationLogActivity.class))); @@ -93,6 +96,8 @@ private void showExportLogSelection() { items.add(getString(R.string.log_hub_blocked_requests)); itemValues.add(EXPORT_BLOCKED_REQUESTS); + items.add(getString(R.string.dns_queries_title)); + itemValues.add(EXPORT_DNS_QUERIES); items.add(getString(R.string.export_logs_iptables_ipv4)); itemValues.add(EXPORT_IPTABLES_IPV4); if (G.enableIPv6()) { @@ -340,11 +345,22 @@ private String buildExportContent(Integer[] selectedSections) { appendExportSection(builder, getString(R.string.application_errors_title), errors.trim().isEmpty() ? getString(R.string.application_errors_empty) : errors); break; + case EXPORT_DNS_QUERIES: + appendExportSection(builder, getString(R.string.dns_queries_title), buildDnsQueryExport()); + break; } } return builder.toString(); } + private String buildDnsQueryExport() { + StringBuilder dns = new StringBuilder(); + for (DnsHijackManager.QueryEntry entry : DnsHijackManager.getRecentQueries(this)) { + dns.append(entry.displayLine()).append('\n'); + } + return dns.toString(); + } + private String fetchIptablesExport(boolean ipv6) { CountDownLatch latch = new CountDownLatch(1); StringBuilder rules = new StringBuilder(); diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java index c9b9a3a3e..fc581a974 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java @@ -40,6 +40,10 @@ public final class DnsHijackManager { private static final String CHAIN_V6 = "afwall-dns6"; private static final String CHAIN_V6_PRE = "afwall-dns6-pre"; private static final int DEFAULT_PORT = 5354; + public static final int RULE_ALLOW_EXACT = 1; + public static final int RULE_ALLOW_SUFFIX = 2; + public static final int RULE_BLOCK_EXACT = 3; + public static final int RULE_BLOCK_SUFFIX = 4; private DnsHijackManager() { } @@ -142,6 +146,48 @@ public static String collectLocalDiagnostics(Context context) { return out.toString(); } + public static List getRecentQueries(Context context) { + List entries = new ArrayList<>(); + String logs = queryControl(context, "logs"); + String[] lines = logs.split("\\r?\\n"); + for (String line : lines) { + QueryEntry entry = QueryEntry.parse(line); + if (entry != null) { + entries.add(entry); + } + } + return entries; + } + + public static boolean addRuleFromQuery(Context context, QueryEntry entry, int action) { + if (entry == null || !entry.hasDomain()) { + return false; + } + String domain = entry.domain; + boolean added; + switch (action) { + case RULE_ALLOW_EXACT: + added = G.appendDnsHijackAllowExact(domain); + break; + case RULE_ALLOW_SUFFIX: + added = G.appendDnsHijackAllowSuffix(domain); + break; + case RULE_BLOCK_EXACT: + added = G.appendDnsHijackBlockExact(domain); + break; + case RULE_BLOCK_SUFFIX: + added = G.appendDnsHijackBlockSuffix(domain); + break; + default: + return false; + } + if (added) { + ApplicationErrorLog.add(context, "DNS query action added rule for " + domain); + requestReload(context); + } + return added; + } + public static List buildRootDiagnosticsCommands(Context context) { List commands = new ArrayList<>(); String supervisor = shellQuote(supervisorPath(context)); @@ -222,6 +268,63 @@ private static String normalizeSupervisorAction(String action) { return null; } + public static final class QueryEntry { + public final long timestamp; + public final String action; + public final String domain; + public final String latency; + + private QueryEntry(long timestamp, String action, String domain, String latency) { + this.timestamp = timestamp; + this.action = action; + this.domain = domain; + this.latency = latency; + } + + private static QueryEntry parse(String line) { + if (line == null) { + return null; + } + String[] parts = line.trim().split("\\s+"); + if (parts.length < 4) { + return null; + } + try { + long timestamp = Long.parseLong(parts[0]); + String action = parts[1]; + String domain = normalizeDomain(parts[2]); + if (domain.isEmpty()) { + return null; + } + return new QueryEntry(timestamp, action, domain, parts[3]); + } catch (NumberFormatException e) { + return null; + } + } + + public boolean hasDomain() { + return domain != null && !domain.isEmpty() && !"unknown".equals(domain); + } + + public String displayLine() { + return timestamp + " " + action + " " + domain + " " + latency; + } + } + + private static String normalizeDomain(String raw) { + if (raw == null) { + return ""; + } + String domain = raw.trim().toLowerCase(Locale.US); + domain = domain.replaceFirst("^\\*\\.", ""); + domain = domain.replaceFirst("^\\.", ""); + domain = domain.replaceFirst("\\.$", ""); + if (!domain.matches("^(?=.{1,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$")) { + return ""; + } + return domain; + } + private static void appendRedirectRules(List commands, boolean ipv6) { int port = G.dnsHijackPort(DEFAULT_PORT); String chain = ipv6 ? CHAIN_V6 : CHAIN_V4; diff --git a/app/src/main/java/dev/ukanth/ufirewall/util/G.java b/app/src/main/java/dev/ukanth/ufirewall/util/G.java index e6c76066a..801d13480 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/util/G.java +++ b/app/src/main/java/dev/ukanth/ufirewall/util/G.java @@ -51,6 +51,7 @@ import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.regex.Matcher; @@ -325,6 +326,48 @@ public static String dnsHijackBlocklistUrls() { return gPrefs.getString(DNS_HIJACK_BLOCKLIST_URLS, ""); } + public static boolean appendDnsHijackAllowExact(String domain) { + return appendLinePreference(DNS_HIJACK_ALLOW_EXACT, domain); + } + + public static boolean appendDnsHijackAllowSuffix(String domain) { + return appendLinePreference(DNS_HIJACK_ALLOW_SUFFIX, domain); + } + + public static boolean appendDnsHijackBlockExact(String domain) { + return appendLinePreference(DNS_HIJACK_BLOCK_EXACT, domain); + } + + public static boolean appendDnsHijackBlockSuffix(String domain) { + return appendLinePreference(DNS_HIJACK_BLOCK_SUFFIX, domain); + } + + private static boolean appendLinePreference(String key, String rawValue) { + if (rawValue == null) { + return false; + } + String value = rawValue.trim().toLowerCase(java.util.Locale.US); + if (value.isEmpty()) { + return false; + } + LinkedHashSet values = new LinkedHashSet<>(); + String existing = gPrefs.getString(key, ""); + if (existing != null) { + String[] lines = existing.split("[\\r\\n,]+"); + for (String line : lines) { + String existingValue = line == null ? "" : line.trim().toLowerCase(java.util.Locale.US); + if (!existingValue.isEmpty()) { + values.add(existingValue); + } + } + } + boolean added = values.add(value); + if (added) { + gPrefs.edit().putString(key, android.text.TextUtils.join("\n", values)).commit(); + } + return added; + } + private static int readIntPreference(String key, int fallback, int min, int max) { String value = gPrefs.getString(key, String.valueOf(fallback)); try { diff --git a/app/src/main/res/layout/activity_dns_queries.xml b/app/src/main/res/layout/activity_dns_queries.xml new file mode 100644 index 000000000..93b8612b7 --- /dev/null +++ b/app/src/main/res/layout/activity_dns_queries.xml @@ -0,0 +1,35 @@ + + + + + + + + + diff --git a/app/src/main/res/layout/log_hub.xml b/app/src/main/res/layout/log_hub.xml index a85234001..0a101d50e 100644 --- a/app/src/main/res/layout/log_hub.xml +++ b/app/src/main/res/layout/log_hub.xml @@ -77,6 +77,58 @@ + + + + + + + + + + + + + + + DNS daemon reload requested. DNS daemon restart requested. DNS daemon stop requested. + DNS Queries + View recent daemon DNS queries and quickly add allow or block rules. + %1$d DNS queries loaded. + Allow this domain + Allow this domain and subdomains + Block this domain + Block this domain and subdomains + DNS rule added and daemon reload requested. + DNS rule already exists. Log Hide app icons Improve performance by disabling app icons in the main view From 2c5a0072268e3611555c97b84746811c4824ab94 Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 14:20:29 -0700 Subject: [PATCH 006/108] Improve DNS daemon cache stats --- .../main/assets/dnsd/arm64-v8a/afwall_dnsd | Bin 21496 -> 22792 bytes .../main/assets/dnsd/armeabi-v7a/afwall_dnsd | Bin 16288 -> 18452 bytes app/src/main/assets/dnsd/x86/afwall_dnsd | Bin 20560 -> 22760 bytes app/src/main/assets/dnsd/x86_64/afwall_dnsd | Bin 22128 -> 23952 bytes dnsdaemon/jni/afwall_dnsd.c | 176 ++++++++++++++++-- 5 files changed, 162 insertions(+), 14 deletions(-) diff --git a/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd b/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd index 8726bc7cffa4101245d6b60931a985c78f27804d..8a09e16c29adf6fc78e069260ec129ff175deaed 100755 GIT binary patch literal 22792 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 BlcE3s literal 21496 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 SwH1%5{h!t%@y^?E^#1_=+u}3; diff --git a/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd b/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd index df8d47ef9f5f8396c826d7b2bf2dc7bd8d63f778..d8a3ca1215d493a065382e4abef14578b0fd7c70 100755 GIT binary patch literal 18452 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 literal 16288 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 diff --git a/app/src/main/assets/dnsd/x86/afwall_dnsd b/app/src/main/assets/dnsd/x86/afwall_dnsd index 3a167362aa9135151477ee32455a2d48abe7f604..80a765422df6e0ce1efcc6d6cb154a2476fbf2a2 100755 GIT binary patch literal 22760 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 diff --git a/app/src/main/assets/dnsd/x86_64/afwall_dnsd b/app/src/main/assets/dnsd/x86_64/afwall_dnsd index 56c5b6c5a8dfbb126f04eea4ea96d48dc9003d75..395a5b241c5af66a7a9ba330a258da64d81bfb26 100755 GIT binary patch literal 23952 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 literal 22128 zcmcJ14}4U`wg25sRsupU{sE&UvdZ#LA!H%ZtR$KZ8*&#mHVXc!MU$}ECDCLz-E07> zLgH?K+hrA7+Tzo`$LpuH{`!1fdOs-Zd&wE8su&_dRoGlAFL< zfBp0~aPOIO=FFLyGc)JRpPOA<>RD(unIsX?q-!O@axc;;#XKRmf=2*~r2=UT-WN+* z(mBA>8BI?w)&WxWkZT?eGdMjBkn%P1^pS7^=MzxWkf4R9oedN()~NzY<8_?!QC$VS z`1_oX!z`*0LMK&qP`E!z1j=#PY3(lysI6#_JV&_0M+|KJTyGY zuD?kNj{be~?Ca0_^zECTdf%J*@JrLSUBY|(>?Kfpc$W-g7?*;6NecR9Dd@Q===mw= zg(>K+6!b+Y=r^RGe=h~SDg}K-3OY@*v+3>b6!bMI=rpFz!!t6dAe>G9rWEv_r=b5L z1^u@v=)X@v?@U48pMrig1^x9D^uMK`e~^Oy_Y`ys2K3qVc5VuKRtkD{3i{L(^tmbM zjuiCb6m%s8y&?tu_7rqq3i=OH(CQuCIUrs z@DL=MWDG>7XCj^~Jk#-rFik`Za4O=ooXEs;1*eltnwOLDOu{n-&lo%x+6<#E9(MvVX3mxySlovI_z5wq`}wF ztM&(h6U=5f0Yh7^(||{gU5XA8Z0^ z-HJeUz0?%+-UVS0NU>mJSc0>zk#rsuu~4e7gAWf#%>nY@lDD=YSc9?`x+<5HE~TQ8 zx8CQa`hezMBB&vsccniRY@p()Zb5%d_1)kN)P#fJ^@T!#pj7Sk`cP!Zx56Lt`B;;x zy?2q+N`G}-z2rycCPofTs}*8b}1BKp9*Gq!(&5(&|xPU=6{QK9cPXLMKdJ zNMJ%h^sV-JsczLZHPDMcD0zc{0JVc^GDuw66yR#3&d6yBN*;H~0_bFUeQ*V#h&6Cn zQ%?~Jhn6ugIEKagx;8MJ-pSY9$2dRryU~B0;&hr1#xW?}uFE01aqMOo=*Ial-at2w z?JNVG#<>Vq1Kqe@oME6-*&^f`=wjYdT7iL1^Hzjn1D))E2#SGDb6bQ81Kl|PZZ*)! zPKZ!tppzXEq1HgBxhF!Sfi7$jrL8v5jq|z1K&Lq^!UhAK=CTNz40N%_p|mXqI@wnd zwi@Vsh_Ix`4Ro@_B5X6zg-xZj9R|A5u6G*fM*FkRKqosb!XX1aTMz+{8R%rwMCdcn z$>xio8R%9)1ROBX$^MCO%0MSOKN#-NV>AZImxz#Ipp%afVZ4D({z-%^1KsG$tOojY z!3;RVKqns~Lau>MzDR@u16}w+N-H+d$&ZPk80bcyS7D$V{aST>eQ;G}Q?uV+x4P0_ zR}Z5E>p6t`gkTOs&4EB&U`3IA3>-qy)cTq+&5dN65v^|?v%(kfg{s4K!GMncpxGCy z^EK%RE6PWiz{$!Hh_~8X>#MA-3v*KnRtbG@&r(zm+W z8?I!Mi>B6$(TTkFBd9tnEB6f65maW|M@rR+gPc+zSc#f71_SVftN~KB6uir-SJFCC z6B4!BI<<-YuW4u+BMob$uSRNas$Su{hSF!xh9mLUt*{n0R)=e^1#950KyXz6GHQnM zNnD?jJ%|01xJo6FT_XQi$=q;_WN1C3`)aJ=pq2D#)eEDN$4Kz0!4PkQziNCsrLfPc`*&Zc$r=n;8-t;+6@4L1t&u{~oSN!z^&AYU>iRk1hQ>M7{#B@V zWlf-|2CmL~7dcno>Pl93QeRUz*w}~xHb&yTsHd!w>H;gP>#+twFnuR&{uV&8r@P>c zo&+2V=d%xR65wlqg@6Nq_X19W<2wN6t$?0vN%}irJzxeL-xHTgQU#y~MrJkO2Y`DAY;q!>*!czd6u;*kaZY4TsC{~h6GRHeJvz(dMNZJGDJ1I84 zBvY5rg5)TkTfyrlhsM&fN;0h_nKMcrxq;CY;i5j+<<2jo-KH`y4=Vl zRiM}m=-7sZNHaO-v(;gn79BsV7E8yRy%xl%ukV*ZW(AxLx{L)E-i@Fw1FZm1`Y!2# z+Um@lfd)k^8`B?1d(dqD0inEQP*nGUgD)78*kLFa6=#Pyo^sI!eNejYWV`fNr1N0I;LZ&{!GZ>SH+8-TngFlSECBI#`X zyfw|(K6BUEo3|BHitV|I5m}ZaN$Y`2<_hCL|AFX-?t{8+>%rRz-r(8W;>z4=GM1fo zLyESLU7)$S3-bErNYc|(c3Ebh$-IrG0d+YWBd;O71rzo-rK7E7nFE(a%;r8mT?Q^A z`iNlvP*LAgBJT`nP?Y4~q(nX_kZo; z(#JO=u7X90PiRACMSaVDLi-XG@cVP*$u!G}ITdtU1zccJ$v@yf}96N2fgMY3*5vY3r2R=m^B=_)v~N zh{)nt-bWs_PiZ?5-p3l@QQy=4iwcZe{z@YM&{Fhj)MS?AXcgEsItYk%%F!PJX(@70 z`@)52S1w{`R|a&U-AmcqI>R=%+M}%{#Cr&7pPWQR)syy4?Hyr<0iPNPfcazi(63EljkWLffyr?aVGzEo6 zi3h=tIN9|v5~Z$2%-_|W;a4BEg@`l$Buje;GlJ&PJt4b3Xyz zQuO4FNRy+_;myVh>ozp0ROjCCd%a1RBQbE&_`U}zN_-dV8eUcECF;5RIs7q)zvS=_ z9PZ)pAfV`Tlhkn+%Gg;?1??as;8EYzu9}6J7`43)#$o**0IuyvBARv{HH{6uV~h~4 zrDp9yJT~Fr4MY8WelhFkt3P97p%CfJ9KnQ*)lJy^jm(6}ZA)QEl-9ju<-YG+=Dgi` zhqLnbZkPIXOVLIMl;pN!r<2M4t(da+0pHz@>S^~tpsKk>53Jtca(q^*e&&+D`(df$ zc&Yr|*%IX(Kl7dmzRh${Qt_6?Li28hfaKN3&uN74qnKSL~r;#9gt6Nr$nAJ$S?SWVqms z;`vv7LgwRrSFGN4p`v!#JC`_@IB!gbZMk@g@l+)9FF`TM{ITqPdM(8V*!yj~wPs9r zIEX5U)4oS_rIu(foF_?AXm`v5yy z@N%gq74;2mE{b8edYsTH0!1$qegV~@*JYc*#t0(0$cntgY(HY(?};N#`x<*_vR`|U zW)%LJPLFrrL7Z6?x@yWmQXO;KVlTd{Jb%T`gh zU&A6s>3HGflE41?k-b*sC&!qcYQF*Y1->F9f(=-rk9!H8^{x*VeWmc zZ%MHHGxsT5l)7W2VkKs|7%WP%6W&y&SbUt6EX9yaKUawto~uN9Gnfz5{V~Se)gQyK z_I8m6(fn8|z$w0Py42hgO&bMyKnv59)?V5-bjZM+JH|3<{^o(9d^vi)pX>Q9qI@p( zS7}*@K<}70*A;p z`XK>Lj<$kZJ#Ie%<2M6?od!(+BqzET<3d5n%x4V%T6p{v5fR`G!6|jnUQmfY%3PqL z{>8Zi!${J`pa4u8orR9_hLVosq{#lNA7OC4rbNCpt(vXG^Cl^go?7NWm6@*~zkPqH zy^}`IBFIxr-57vtk0f@IyvUbkx$S=tlec38`@1?b(38iLNqPJJ*3W5IEZ_eSQeE

VXHt|mFO#kK^0908=Iiz;OmK|Q$^4-`pne6mx-C8*RG=}TphL_ zifyztfn|5Nxk<8rJi1GcR)3L9avu93dHY7TW{G^?~UTWvRJ8GuhqxB~1i5>O`{IW%^5ea~4hW z!Fe(Bu;SgX)P1ba^3B(>sf3P%w;Fq`(%MBc6uo_IhAX!5TAF!!$&>Vwm!V`7_SqMu z=9uO9_(1!s{pTymZpFLL-P*%i z<@nQmQ=Bcksby059a=r#1Yypeb&SF#^#92jdyw2_+x|5RNz@}uR2CC;n2WM^DvlTB z_%m3J4+?yP1f~xY$mH}tYwt|_6r9>gRG06nhV7?L%`=&YZKVc4AkUB`Hd5K7E0-;6 z;oiiH8E1!t;56# zjX>NmuBF4c*y%2AXNe02iOGt59ANT1!#Hu6UWZfi25_QwjIs6OV2w{=ymY!L>ZR;t z_pHrf(Ud0E6kiaOh9*fgC3{#FagaT-x|bNaI@oD7&g&IsUU?;Oc&}F?kH!Y{$>=-j zOrM4XB$7UvlI@4(_RY2yrm^Rg(R<|RHl9cC16_VoGtbk^`+!|+3|9Qd$Rcl#GBJKR z(CL?hx_G~QeB8%4H377Yeve>(mtQWp2&44Z#$r0yadgUN#Quq9)EVXP)aCz!W+>m( zjB9u^N*Ek$hTT{U?~M>NOwNw?1`gu&-ne{NGw6K&ANK~E-C{;?HKmgOF&`OvZ+|QK zZ5Mn+K4X`y3TBubd<{A{@dyObJUu#DlHy9T_4CtkW%By>;O22~mX&w|5oSRsCz*aS zBNtz)8$vVYe`41#4v>iBWVX%$=~Cj~z(Hk%P=`A zOQ=p8&cUp2{d^*>2Ich?NI|u1i84eKuWo~t$f;5CgZZF1TMBLP%U4jM+NE^8HA;!6 zx5DeD!|O5=t&X)}fOdW=uZ^Z}LFHIvgNUpaky;TUv%+{35uwS>D7rkCEu%M@{y2yf z(3;)X0BS#nhL|CxlbM#)Ce-Rq#1wUpXXe{V>lZCxk|V8HK(O^cjwp8$iLI#Mv7kb1 zDzs`yDZ#G25hRH%&73=k%@ecPP!wCGk$>ZRf*Wy|>xr6@5G}r%aYNP^rx))d_z&Zh-$IdPf}$?f~&H$0;rEN(ey zjeK!QvD|)CUT}CrMN)3hfKHe;0ih7nBlPW%?7k={I`S^%H4 zRe;!k57U+sD}~T{u0A>|zTOsksCziz$CSb3H=UrLn6`0XGKM$aRTfWrGFb(d*#SW9uu( z8PHBOYO6(bXo<+yb!bAV{hj`c*m*A&07DB!x8uObh2ku9##t7M>)ArFb4@8EqJIyX%pFpTOTtOP`4@wfv@`|K zwzgO0pLPyA!J?I8^Z7WvqBW)A^h&!21sYEDBT17SU4^r-NKy`4B1v=em|jclTABos zgtPyaqW?rqU;tY1W@rCPmsEIS`L>J7a27Rn0zkRr-SBOw+}*6o`6v3Y9()$xmcW99 zORy+(Cwt1#YbIF2a>wa%x$LyN^(&gZ<#NesoFg2bSY~!RdRJafgJ2hBj9H!r4F?Om z39x&JWpwz~jdRCGJ}Nciocq5~O22~plw_Au*F~m%QEao7*6)krW37Cfa(&!o%~%-Q zXr*lmq~jPI`wh2V#BEe;vKJ+^VbWWnaTxm%Ri+$nq<#tb6GV-}K{6VDalgQ_gceWcHY|*i$M&HKH;U-iC(sGTV$Cr4# zr`%odWh{!PU#F;tb$_aUsi?iU`%%<`+CH3LdDH>e`uRy@#uhA7@qVr#i`;(U{OFNz zF3#ZK$0nn*1J$j`1wOB^7OQpLf^!Tv- zQ3kX=Y=6WS9n=CkLSmIZjq(-sQ#W0M<=^)vS(cZztLcD^b{u_3b>n~lj*ewj_h|QA z#M5>mtvntuxz%_2FNf9E?|;ZA601l3LaPw0bb3Ore=<(pYABuT)yU zCRen!N9p=ohC5!E!}R6cp$mCec)J>${5X4}IZR=(3l!bcIN@r}fvaipm^8gVzm220 zAW@DHM|-?AkUFHG`B58{%FF<%&S(b0PzjAu*8lgTJ+X5lr`E2$2TBaD9J=E}H*fLO z_0ep&KAtz-t-j1=26nh^^)ncuIL^2h#S5q4xX;QON|$3hK*V5}G8ws`C!AiM?tt5r zvxvW3*sP*hQOe9 z&KL%_gM)?vSJiR&dtFsDJ}_e2>d~{rz|@sYODy9(y%`z5T~GfA${@|^VVHhvQDqkv zvz~IA6CT@mb{71Zd&Grq71)%>>2Y%85z=2c*%<-j<@y7iA@_SN3$iRX<67foDw{c%_TtSHmb z!&M&BN7{XK^od4ofUxGG#33YO;Lu?y4nC@o=y&4y#@reqfRzy^;FuwiPW4egMMgQg zg^68|t~fM#eT)gg;SQ?~4m3QrD%c2|^|)-+-@-m9xM0e1;w(5@@?-lk28)J?ek>Z| zv$tP`{*OIPS4pL9sA!F?zys#uHEy``gIH_R3ZzOqhI4Cl;I-xPAR3$fN30I8zVT4n zrgF#M!ZW#3+6F$QwOc}`VA+F-{&xR)Xr_&t*?-bev@BQzD&J^btfZvbs;cw#|h2Sm)E=M&)K-QPd*!&o+*? za>v)Y__2%Q>9ertbK{z=^;r^+nQ97`DmdPG4`UYh>2Q;Z<5<%HC3deZ*E18hOdn|< z;O+r6-{E$=5x&@c@+ghQ+>(~U+??iL^=F_pG{#Z1<(_=f-8MRFENwfn#;?S;&|zaa zEaS;Hoqsercjh4b~wSP$Wg$gS0MIKdP2i^EVXKNbJGw*?<#GgWcV#Q89cPUx}H6>qW zxAxJ8si4;GybQ@ieJMI|xc>eYriB=NG0?{*nXx~q^X^{)DOiF15QUY-9xF!qbVSL! za2LivY1=#U1HU0P4eP=Rcl>vGqgqTf&T`S0&g~|>Bm1uy(vN3;y)73S>OFh+&8P00 zfii}=?|JIJ3f_IQQDtaqCv~69yRSm;zF#{}^qNrbJ@cSoTrbRi1X@X~Lp4id?X>Pj zH_8wET<_gqfQfn(`xV}!Px8ttaq7`&;{37P@fm8n7qy)u2HQ}7PEOIEztIO-xAVka z6V2n8Em`o*ZTjlp2Uqdblk`Vr9RHfM}}mx74A9Y=_;1UsJn#iUl4 zgYPKurMBu#um|?8x~`v?B$M2ZslEqW(SEG54#K?W+V|CUQcBlH8EV)z);{2>8z3A5 z0e5F_VQ8brux+~9OXdOXr0r%_f0ognCiglcUuDSAN3kwm5Ko^rHHmexr%tnCj4o)| zRWynGfgHUL$z_fwi?V<=Kc`oHfg@T(6S28talCL2&9*gEB$a_a`}JbSqebJvE#-zC5^wbT|goGM$-^P7r%wh*8+dW#QBeqygzZTWM zmM%EiBopg9rP(Vd{(=QdiG+Xzjhnp@GzVyY=o4PN3ab-F#JubtFklaoJN`~7hV_v6B zIGr;1oIzKcv|LzaGP~8Bm}UOx6nfzoznDQ;Z!x`G3{G7yGGdF=^m$kb&if|41W_i| ze)E`K7_+VyEY+`j5qo`13*7tSR$x$*MLY+)>MiMw&ZC_i1&mia(s0*1k4$Fb8H_?U z2`w}LdvKC)ugycBQ?=sM1-*$Y#RBXe>ANj?{ZBBysO?!|Hr){^dIi1^Lyx`z#tI@q zf3FuQdX|VRul&FrlqsJ5lexrzEdpIn-GM5w9lqsJaKf}k!S8nLmE*bKj!jsO;xJ&@ zhg8~mP<>nH>KB}950+chovi-{Zz=y1!qB;^9~0jjVA(L3i0`Q(=~*f?f%_Gu?ZY+e zc=y487*=HR{eFxrxci&Z@hUyX-?b;hPg|sYtp3fWo#esnSXb?HJG7>0ZrqKR!ID^{ z^0xiqE1WH#cQ#GL`?^)sD4on>8eNZS{mUx-HskPPJaZ7r4`QDMqzWg z4NGP0t$W8qUTng2u(LaI?Jtl9wREf9?D`wJgKxWIP&0RuIwGgc&70vfNvob%jV+7q z==t5ULKSfI$!$R_vCwx$f9H;TWm+|BQ9RFv`}Jk40Gx5EZw`v@$8dC;_M&6fzL>~? z0OY{+x(zY1YRlLVqP^w$jH0!EO<#-1>(lhI6!m?`lh?h6MI21pEQ92Sh9v(b@n>4` zB`v>LhVK%Krs10^DU9zZvR{6Iu1Nc>EHaR#(y9^@zJNrBpbt|dFSp+A;?eq|0$IkZ#H#6@kx7< zb{W$=ai^&igL~YWgS*_c4}%!PdF4xPtnM@E2nTr-x$GbYeR*6N<8~xgEm$CL_gFIg zU0oUYdIA#yEUR+LVlE42*FLA?kW(%>M1#M#`GI(e3Bxcn9_QmXnD7-My;v^2orVBgo;S+_hfNIjw+gU4OS zJnlm1k~v_yR6gSf&afYkd{C>t#E!0pHoVyFRMGcFII^VG{`wXGy6CTfZ^yh zv9r>LcE$9{RhQ9+0QfXeiDPM{AHZk}P_3tEYS5{|3nT_6C952}t>|`OiuYNiZr_XL z%V9vCQ@Y;2PU-r5n(45|`LQ z%5cVR8LLeMquLFl-A9Z44BAwVhZ{s~^{=8l>c{+RsITBKL<){P;0{E}+emT8R#_ns zd9|OQL$L|XM3g?IXHDsECA*lVtw-9B&gMgB&F87dpzB)0;eghPN*%yg>&I9z^u+|$ z#4~X2YG+!LXVQXl=2BaQJad_?N}gFm-z`32YXQ4F^GW{Q;x5}(;6sJsO5qR)3O@Tr zw3DLosI8BYqP86bcUbYx<&g&`#>7=Ah7nCeoZnBkWYjtzm7$YuEXgwq-zD+m|QqX>u{tDrE z(0+y=Asl6({S1GOaGH9FO$^^d_(Z~67~VlRPQKB8hW~+ZvPX$3hX0muTtlG!4F4tJ zxMV{68UAmCjqoXiZ)5n4gxd(;%J4;mPbGX4!%GOCMtBRuuOWOo;f)NR zOZW`Js~CO-;WG)ZVEE;PUqN^=!!IHHO2Tu2(?F&03my^prV;pWM&SR$aZ(Hg8h{k= zu|SX@k{O9Q(imvqQeYzxP~=k>Rbsz|K~d^Z3hzG&p3RH!*&jPI6TVXyBwb2@Eo@;aUzG)IJ}C( zg&f|@p`XK*9IoT=XB|4o`4+&SG9ZhtoK`ibJ7qGIoUlN3ioG5zkj(ucW#Yi z`P{4K&cqMm;Fnm!5+vgVi4DF0B7tDomm>#^lcO;S$H-2r^q zC*}BREB&GB2K@be4X_n~<{aLdN}%|;7GJ25=S7ZT47!ZF8+2lAbyF>43(pJ<>zq*0r7De3nKqW=tL^1T;vyiLO|gsbSb(H zMVw#&56Kkyg&!1iHg+uai_K7^fY;fLxrcs- zOHi*Kk-w2ET);!3VLZdg_IHC$W%Fq#3I8m9ms6~pX#P+T^%rtz?o$0le(}3Xhdji6 zW_?9|Jyri*Fk^nP>X%#rPHcBlG_p2}Bd+-+G76dF%B$e4K^&^Al%FI?-0L3s*}$cf3#7d@^g8*03!bZLEuo-UqDJ1Z8x$i P-_@~qj6}pmK0*G! g_stats.max_latency_ms) { + g_stats.max_latency_ms = latency; + } +} + +static int cache_entry_count(void) { + int count = 0; + int i; + time_t now = time(NULL); + for (i = 0; i < CACHE_SIZE; i++) { + if (g_cache[i].used && g_cache[i].expires_at > now) { + count++; + } + } + return count; +} + static void add_log(const char *domain, const char *action, int latency_ms) { log_entry_t *entry = &g_logs[g_log_pos % LOG_RING]; entry->seq = ++g_log_seq; @@ -491,12 +533,13 @@ static bool cache_lookup(const char *domain, uint16_t qtype, const uint8_t *quer for (i = 0; i < 8; i++) { cache_entry_t *entry = &g_cache[(start + i) % CACHE_SIZE]; if (!entry->used) { - return false; + continue; } if (entry->hash == h && entry->qtype == qtype && strcmp(entry->domain, domain) == 0) { if (entry->expires_at <= now) { entry->used = false; - return false; + g_stats.cache_expired++; + continue; } memcpy(out, entry->response, entry->response_len); out[0] = query[0]; @@ -508,12 +551,29 @@ static bool cache_lookup(const char *domain, uint16_t qtype, const uint8_t *quer return false; } +static bool response_cacheable(const uint8_t *response, size_t response_len) { + uint16_t flags; + uint16_t rcode; + if (response_len < 12) { + return false; + } + flags = read_u16(response + 2); + rcode = flags & 0x000fu; + if ((flags & 0x8000u) == 0) { + return false; + } + return rcode == 0 || rcode == 3; +} + static void cache_store(const char *domain, uint16_t qtype, const uint8_t *response, size_t response_len) { uint32_t h; uint32_t slot; uint32_t ttl; cache_entry_t *entry; - if (response_len < 12 || response_len > MAX_PACKET) { + uint32_t i; + time_t now = time(NULL); + bool evicting = false; + if (response_len < 12 || response_len > MAX_PACKET || !response_cacheable(response, response_len)) { return; } ttl = extract_min_ttl(response, response_len); @@ -522,15 +582,39 @@ static void cache_store(const char *domain, uint16_t qtype, const uint8_t *respo } h = hash_domain(domain, qtype); slot = h % CACHE_SIZE; - entry = &g_cache[slot]; + entry = NULL; + for (i = 0; i < 8; i++) { + cache_entry_t *candidate = &g_cache[(slot + i) % CACHE_SIZE]; + if (candidate->used && candidate->hash == h + && candidate->qtype == qtype + && strcmp(candidate->domain, domain) == 0) { + entry = candidate; + break; + } + if (!candidate->used || candidate->expires_at <= now) { + if (candidate->used) { + g_stats.cache_expired++; + } + entry = candidate; + break; + } + } + if (entry == NULL) { + entry = &g_cache[slot]; + evicting = entry->used && entry->expires_at > now; + } + if (evicting) { + g_stats.cache_evictions++; + } memset(entry, 0, sizeof(*entry)); safe_copy(entry->domain, sizeof(entry->domain), domain); entry->qtype = qtype; entry->hash = h; memcpy(entry->response, response, response_len); entry->response_len = response_len; - entry->expires_at = time(NULL) + ttl; + entry->expires_at = now + ttl; entry->used = true; + g_stats.cache_stores++; } static int connect_upstream(const upstream_t *upstream, int socktype, int timeout_ms) { @@ -805,12 +889,17 @@ static void load_regex_rule_file(regex_rule_t *rules, int *count, const char *pa } static bool reload_config(void) { - config_t next; - if (!load_config(g_config_path, &next)) { + config_t *next = (config_t *) calloc(1, sizeof(config_t)); + if (next == NULL) { + return false; + } + if (!load_config(g_config_path, next)) { + free(next); return false; } free_regex_rules(&g_cfg); - g_cfg = next; + g_cfg = *next; + free(next); memset(g_cache, 0, sizeof(g_cache)); g_stats.reloads++; return true; @@ -894,6 +983,15 @@ static int create_control_socket(const char *path) { return fd; } +static void finish_dns_query(const char *domain, const char *action, const struct timeval *start) { + struct timeval end; + int latency_ms; + gettimeofday(&end, NULL); + latency_ms = elapsed_ms(start, &end); + record_query_latency(latency_ms); + add_log(domain, action, latency_ms); +} + static void handle_dns_query(const config_t *cfg, const uint8_t *query, size_t query_len, uint8_t *response, size_t *response_len, const char **action_out, int tcp) { @@ -901,47 +999,71 @@ static void handle_dns_query(const config_t *cfg, const uint8_t *query, size_t q uint16_t qtype = 0; const char *reason = "parse"; ssize_t forwarded; + struct timeval start; + struct timeval upstream_start; + struct timeval upstream_end; + int upstream_latency_ms; + gettimeofday(&start, NULL); + g_stats.queries++; + if (tcp) { + g_stats.tcp_queries++; + } else { + g_stats.udp_queries++; + } if (!parse_qname(query, query_len, domain, sizeof(domain), &qtype)) { *response_len = build_block_response(query, query_len, response, MAX_PACKET); *action_out = "invalid"; + g_stats.invalid_queries++; + g_stats.blocked++; + finish_dns_query("unknown", "invalid", &start); return; } - g_stats.queries++; if (evaluate_domain(cfg, domain, &reason) == DECISION_BLOCK) { *response_len = build_block_response(query, query_len, response, MAX_PACKET); g_stats.blocked++; *action_out = reason; - add_log(domain, "blocked", 0); + finish_dns_query(domain, reason, &start); return; } if (cache_lookup(domain, qtype, query, response, response_len)) { g_stats.cache_hits++; g_stats.allowed++; *action_out = "cache"; - add_log(domain, "cache", 0); + finish_dns_query(domain, "cache", &start); return; } + g_stats.cache_misses++; + g_stats.upstream_requests++; + gettimeofday(&upstream_start, NULL); forwarded = tcp ? forward_tcp(cfg, query, query_len, response, MAX_PACKET) : forward_udp(cfg, query, query_len, response, MAX_PACKET); + gettimeofday(&upstream_end, NULL); + upstream_latency_ms = elapsed_ms(&upstream_start, &upstream_end); + if (upstream_latency_ms > 0) { + g_stats.upstream_latency_ms += (uint64_t) upstream_latency_ms; + } if (forwarded > 0) { *response_len = (size_t) forwarded; cache_store(domain, qtype, response, *response_len); g_stats.allowed++; + g_stats.upstream_successes++; *action_out = "upstream"; - add_log(domain, "allowed", 0); + finish_dns_query(domain, "upstream", &start); return; } g_stats.upstream_failures++; if (cfg->fail_open) { *response_len = 0; *action_out = "upstream_failed"; + g_stats.fail_open_drops++; } else { *response_len = build_block_response(query, query_len, response, MAX_PACKET); g_stats.blocked++; *action_out = "fail_closed"; + g_stats.fail_closed_blocks++; } - add_log(domain, *action_out, 0); + finish_dns_query(domain, *action_out, &start); } static void handle_udp(int fd) { @@ -1037,15 +1159,41 @@ static void handle_control(int fd) { trim(cmd); if (strcmp(cmd, "status") == 0 || strcmp(cmd, "stats") == 0) { write_control_response(client, - "running=1\npid=%ld\nuptime=%llu\ngeneration=%llu\nqueries=%llu\nallowed=%llu\nblocked=%llu\ncache_hits=%llu\nupstream_failures=%llu\nreloads=%llu\nrules_exact_allow=%d\nrules_suffix_allow=%d\nrules_exact_block=%d\nrules_suffix_block=%d\nrules_regex_allow=%d\nrules_regex_block=%d\n", + "running=1\npid=%ld\nuptime=%llu\ngeneration=%llu\n" + "queries=%llu\nudp_queries=%llu\ntcp_queries=%llu\ninvalid_queries=%llu\n" + "allowed=%llu\nblocked=%llu\nfail_open_drops=%llu\nfail_closed_blocks=%llu\n" + "cache_size=%d\ncache_entries=%d\ncache_hits=%llu\ncache_misses=%llu\n" + "cache_hit_rate_ppm=%llu\ncache_stores=%llu\ncache_expired=%llu\ncache_evictions=%llu\n" + "upstream_requests=%llu\nupstream_successes=%llu\nupstream_failures=%llu\n" + "avg_latency_ms=%llu\nmax_latency_ms=%llu\nupstream_avg_latency_ms=%llu\n" + "reloads=%llu\nrules_exact_allow=%d\nrules_suffix_allow=%d\nrules_exact_block=%d\n" + "rules_suffix_block=%d\nrules_regex_allow=%d\nrules_regex_block=%d\n", (long) getpid(), (unsigned long long) (now_seconds() - g_stats.start_time), (unsigned long long) g_cfg.generation, (unsigned long long) g_stats.queries, + (unsigned long long) g_stats.udp_queries, + (unsigned long long) g_stats.tcp_queries, + (unsigned long long) g_stats.invalid_queries, (unsigned long long) g_stats.allowed, (unsigned long long) g_stats.blocked, + (unsigned long long) g_stats.fail_open_drops, + (unsigned long long) g_stats.fail_closed_blocks, + CACHE_SIZE, + cache_entry_count(), (unsigned long long) g_stats.cache_hits, + (unsigned long long) g_stats.cache_misses, + (unsigned long long) div_u64(g_stats.cache_hits * 1000000ULL, + g_stats.cache_hits + g_stats.cache_misses), + (unsigned long long) g_stats.cache_stores, + (unsigned long long) g_stats.cache_expired, + (unsigned long long) g_stats.cache_evictions, + (unsigned long long) g_stats.upstream_requests, + (unsigned long long) g_stats.upstream_successes, (unsigned long long) g_stats.upstream_failures, + (unsigned long long) div_u64(g_stats.total_latency_ms, g_stats.queries), + (unsigned long long) g_stats.max_latency_ms, + (unsigned long long) div_u64(g_stats.upstream_latency_ms, g_stats.upstream_requests), (unsigned long long) g_stats.reloads, g_cfg.exact_allow_count, g_cfg.suffix_allow_count, From 3ebc12148fe730cf791282ac8d35f5239b8edb33 Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 14:28:02 -0700 Subject: [PATCH 007/108] Add DNS boot persistence --- .../ufirewall/dns/DnsHijackManager.java | 140 +++++++++++++++++- .../preferences/RulesPreferenceFragment.java | 9 +- .../java/dev/ukanth/ufirewall/util/G.java | 10 ++ app/src/main/res/values/strings.xml | 2 + app/src/main/res/xml/rules_preferences.xml | 7 + 5 files changed, 166 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java index fc581a974..84ee62765 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java @@ -35,6 +35,8 @@ public final class DnsHijackManager { private static final String SOCKET = "afwall_dnsd.sock"; private static final String QUERY_LOG = "afwall_dnsd.log"; private static final String SUPERVISOR_LOG = "afwall_dnsd_supervisor.log"; + private static final String BOOT_SCRIPT = "afwall_dnsd_boot.sh"; + private static final String BOOT_LOG = "afwall_dnsd_boot.log"; private static final String CHAIN_V4 = "afwall-dns"; private static final String CHAIN_V4_PRE = "afwall-dns-pre"; private static final String CHAIN_V6 = "afwall-dns6"; @@ -53,6 +55,7 @@ public static void appendApplyCommands(Context context, List commands, b if (!G.enableDnsHijack()) { if (!ipv6) { appendStopCommand(context, commands); + appendRemoveBootPersistenceCommand(commands); } return; } @@ -67,6 +70,7 @@ public static void appendApplyCommands(Context context, List commands, b if (!ipv6) { ApplicationErrorLog.add(context, "DNS hijacker enabled; daemon start and DNS redirect rules queued"); commands.add("#LITERAL# " + shellQuote(supervisorPath(context)) + " start"); + appendBootPersistenceCommand(context, commands); } appendRedirectRules(commands, ipv6); } @@ -75,6 +79,7 @@ public static void appendPurgeCommands(Context context, List commands, b appendPurgeRules(commands, ipv6); if (!ipv6) { appendStopCommand(context, commands); + appendRemoveBootPersistenceCommand(commands); } } @@ -121,8 +126,11 @@ public static String collectLocalDiagnostics(Context context) { File socket = new File(dir, SOCKET); File queryLog = new File(dir, QUERY_LOG); File supervisorLog = new File(dir, SUPERVISOR_LOG); + File bootScript = new File(dir, BOOT_SCRIPT); + File bootLog = new File(dir, BOOT_LOG); out.append("enabled_pref=").append(G.enableDnsHijack()).append('\n'); + out.append("boot_persistence_pref=").append(G.dnsHijackBootPersistence()).append('\n'); out.append("port=").append(G.dnsHijackPort(DEFAULT_PORT)).append('\n'); out.append("fail_open=").append(G.dnsHijackFailOpen()).append('\n'); out.append("strict_mode=").append(G.dnsHijackStrictMode()).append('\n'); @@ -137,6 +145,8 @@ public static String collectLocalDiagnostics(Context context) { appendFileInfo(out, "control_socket", socket); appendFileInfo(out, "query_log", queryLog); appendFileInfo(out, "supervisor_log", supervisorLog); + appendFileInfo(out, "boot_script", bootScript); + appendFileInfo(out, "boot_log", bootLog); out.append("\n[control status]\n"); out.append(queryControl(context, "status")); @@ -208,6 +218,12 @@ public static List buildRootDiagnosticsCommands(Context context) { commands.add("echo '[IPv6 DNS NAT chains]'"); commands.add(ip6tables + " -t nat -S " + CHAIN_V6 + " 2>&1 || true"); commands.add(ip6tables + " -t nat -S " + CHAIN_V6_PRE + " 2>&1 || true"); + commands.add("echo '[DNS boot persistence]'"); + commands.add("for f in /data/adb/service.d/" + BOOT_SCRIPT + + " /su/su.d/" + BOOT_SCRIPT + + " /system/su.d/" + BOOT_SCRIPT + + " /system/etc/init.d/" + BOOT_SCRIPT + + "; do if [ -f \"$f\" ]; then ls -l \"$f\"; fi; done"); return commands; } @@ -325,6 +341,45 @@ private static String normalizeDomain(String raw) { return domain; } + private static void appendBootPersistenceCommand(Context context, List commands) { + if (!G.dnsHijackBootPersistence()) { + appendRemoveBootPersistenceCommand(commands); + return; + } + File bootScript = new File(workDir(context), BOOT_SCRIPT); + commands.add("#LITERAL# " + buildInstallBootPersistenceCommand(bootScript)); + ApplicationErrorLog.add(context, "DNS hijacker boot persistence install queued"); + } + + private static String buildInstallBootPersistenceCommand(File bootScript) { + return "SRC=" + shellQuote(bootScript.getAbsolutePath()) + "; " + + "NAME=" + shellQuote(BOOT_SCRIPT) + "; " + + "installed=0; " + + "for DIR in /data/adb/service.d /su/su.d /system/su.d /system/etc/init.d; do " + + "if [ -d \"$DIR\" ]; then " + + "cp \"$SRC\" \"$DIR/$NAME\" 2>/dev/null && chmod 755 \"$DIR/$NAME\" 2>/dev/null " + + "&& echo \"DNS boot persistence installed at $DIR/$NAME\" && installed=1 && break; " + + "fi; " + + "done; " + + "if [ \"$installed\" = 0 ] && [ -d /data/adb ]; then " + + "mkdir -p /data/adb/service.d 2>/dev/null " + + "&& cp \"$SRC\" /data/adb/service.d/\"$NAME\" 2>/dev/null " + + "&& chmod 755 /data/adb/service.d/\"$NAME\" 2>/dev/null " + + "&& echo \"DNS boot persistence installed at /data/adb/service.d/$NAME\" " + + "&& installed=1; " + + "fi; " + + "if [ \"$installed\" = 0 ]; then echo 'DNS boot persistence: no supported root boot directory found'; fi; " + + "true"; + } + + private static void appendRemoveBootPersistenceCommand(List commands) { + commands.add("#LITERAL# for FILE in /data/adb/service.d/" + BOOT_SCRIPT + + " /su/su.d/" + BOOT_SCRIPT + + " /system/su.d/" + BOOT_SCRIPT + + " /system/etc/init.d/" + BOOT_SCRIPT + + "; do [ -e \"$FILE\" ] && rm -f \"$FILE\" 2>/dev/null; done; true"); + } + private static void appendRedirectRules(List commands, boolean ipv6) { int port = G.dnsHijackPort(DEFAULT_PORT); String chain = ipv6 ? CHAIN_V6 : CHAIN_V4; @@ -397,6 +452,11 @@ private static boolean prepareDaemon(Context context) { if (!supervisor.setExecutable(true, false)) { Log.w(TAG, "Unable to mark supervisor executable from app context; root start will chmod it"); } + File bootScript = new File(dir, BOOT_SCRIPT); + writeText(bootScript, buildBootScript(context, dir)); + if (!bootScript.setExecutable(true, false)) { + Log.w(TAG, "Unable to mark DNS boot script executable from app context; root install will chmod it"); + } return true; } catch (IOException e) { Log.e(TAG, "Unable to prepare DNS daemon", e); @@ -462,6 +522,84 @@ private static void appendConfigEntries(StringBuilder config, String key, String } } + private static String buildBootScript(Context context, File dir) { + String supervisor = new File(dir, SUPERVISOR).getAbsolutePath(); + String log = new File(dir, BOOT_LOG).getAbsolutePath(); + String iptables = Api.getBinaryPath(context, false); + String ip6tables = Api.getBinaryPath(context, true); + int port = G.dnsHijackPort(DEFAULT_PORT); + + return "#!/system/bin/sh\n" + + "PATH=/system/bin:/system/xbin:/vendor/bin:/sbin:/su/bin:/data/adb/magisk:$PATH\n" + + "SUPERVISOR=" + shellQuote(supervisor) + "\n" + + "IPTABLES=" + shellQuote(iptables) + "\n" + + "IP6TABLES=" + shellQuote(ip6tables) + "\n" + + "PORT=" + port + "\n" + + "LOG=" + shellQuote(log) + "\n" + + "CHAIN4=" + CHAIN_V4 + "\n" + + "PRE4=" + CHAIN_V4_PRE + "\n" + + "CHAIN6=" + CHAIN_V6 + "\n" + + "PRE6=" + CHAIN_V6_PRE + "\n" + + "log_msg() {\n" + + " echo \"$(date +%s) $*\" >> \"$LOG\" 2>/dev/null\n" + + "}\n" + + "ipt() {\n" + + " if [ -x \"$IPTABLES\" ]; then \"$IPTABLES\" \"$@\"; else iptables \"$@\"; fi\n" + + "}\n" + + "ip6t() {\n" + + " if [ -x \"$IP6TABLES\" ]; then \"$IP6TABLES\" \"$@\"; elif command -v ip6tables >/dev/null 2>&1; then ip6tables \"$@\"; else return 0; fi\n" + + "}\n" + + "restore_v4() {\n" + + " ipt -t nat -D OUTPUT -p udp --dport 53 -j \"$CHAIN4\" >/dev/null 2>&1\n" + + " ipt -t nat -D OUTPUT -p tcp --dport 53 -j \"$CHAIN4\" >/dev/null 2>&1\n" + + " ipt -t nat -D PREROUTING -p udp --dport 53 -j \"$PRE4\" >/dev/null 2>&1\n" + + " ipt -t nat -D PREROUTING -p tcp --dport 53 -j \"$PRE4\" >/dev/null 2>&1\n" + + " ipt -t nat -N \"$CHAIN4\" >/dev/null 2>&1\n" + + " ipt -t nat -N \"$PRE4\" >/dev/null 2>&1\n" + + " ipt -t nat -F \"$CHAIN4\" >/dev/null 2>&1\n" + + " ipt -t nat -F \"$PRE4\" >/dev/null 2>&1\n" + + " ipt -t nat -A \"$CHAIN4\" -o lo -j RETURN >> \"$LOG\" 2>&1\n" + + " ipt -t nat -A \"$CHAIN4\" -m owner --uid-owner 0 -j RETURN >> \"$LOG\" 2>&1\n" + + " ipt -t nat -A \"$CHAIN4\" -p udp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" + + " ipt -t nat -A \"$CHAIN4\" -p tcp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" + + " ipt -t nat -A \"$PRE4\" -i lo -j RETURN >> \"$LOG\" 2>&1\n" + + " ipt -t nat -A \"$PRE4\" -p udp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" + + " ipt -t nat -A \"$PRE4\" -p tcp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" + + " ipt -t nat -I OUTPUT 1 -p udp --dport 53 -j \"$CHAIN4\" >> \"$LOG\" 2>&1\n" + + " ipt -t nat -I OUTPUT 1 -p tcp --dport 53 -j \"$CHAIN4\" >> \"$LOG\" 2>&1\n" + + " ipt -t nat -I PREROUTING 1 -p udp --dport 53 -j \"$PRE4\" >> \"$LOG\" 2>&1\n" + + " ipt -t nat -I PREROUTING 1 -p tcp --dport 53 -j \"$PRE4\" >> \"$LOG\" 2>&1\n" + + "}\n" + + "restore_v6() {\n" + + " ip6t -t nat -D OUTPUT -p udp --dport 53 -j \"$CHAIN6\" >/dev/null 2>&1\n" + + " ip6t -t nat -D OUTPUT -p tcp --dport 53 -j \"$CHAIN6\" >/dev/null 2>&1\n" + + " ip6t -t nat -D PREROUTING -p udp --dport 53 -j \"$PRE6\" >/dev/null 2>&1\n" + + " ip6t -t nat -D PREROUTING -p tcp --dport 53 -j \"$PRE6\" >/dev/null 2>&1\n" + + " ip6t -t nat -N \"$CHAIN6\" >/dev/null 2>&1\n" + + " ip6t -t nat -N \"$PRE6\" >/dev/null 2>&1\n" + + " ip6t -t nat -F \"$CHAIN6\" >/dev/null 2>&1\n" + + " ip6t -t nat -F \"$PRE6\" >/dev/null 2>&1\n" + + " ip6t -t nat -A \"$CHAIN6\" -o lo -j RETURN >> \"$LOG\" 2>&1\n" + + " ip6t -t nat -A \"$CHAIN6\" -m owner --uid-owner 0 -j RETURN >> \"$LOG\" 2>&1\n" + + " ip6t -t nat -A \"$CHAIN6\" -p udp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" + + " ip6t -t nat -A \"$CHAIN6\" -p tcp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" + + " ip6t -t nat -A \"$PRE6\" -i lo -j RETURN >> \"$LOG\" 2>&1\n" + + " ip6t -t nat -A \"$PRE6\" -p udp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" + + " ip6t -t nat -A \"$PRE6\" -p tcp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" + + " ip6t -t nat -I OUTPUT 1 -p udp --dport 53 -j \"$CHAIN6\" >> \"$LOG\" 2>&1\n" + + " ip6t -t nat -I OUTPUT 1 -p tcp --dport 53 -j \"$CHAIN6\" >> \"$LOG\" 2>&1\n" + + " ip6t -t nat -I PREROUTING 1 -p udp --dport 53 -j \"$PRE6\" >> \"$LOG\" 2>&1\n" + + " ip6t -t nat -I PREROUTING 1 -p tcp --dport 53 -j \"$PRE6\" >> \"$LOG\" 2>&1\n" + + "}\n" + + "log_msg 'DNS boot restore starting'\n" + + "sleep 15\n" + + "if [ ! -x \"$SUPERVISOR\" ]; then log_msg 'supervisor missing or not executable'; exit 0; fi\n" + + "\"$SUPERVISOR\" start >> \"$LOG\" 2>&1\n" + + "restore_v4\n" + + "restore_v6\n" + + "log_msg 'DNS boot restore complete'\n"; + } + private static String buildSupervisorScript(File dir, File daemon) { String marker = new File(dir, ENABLED_MARKER).getAbsolutePath(); String config = new File(dir, CONF).getAbsolutePath(); @@ -485,7 +623,7 @@ private static String buildSupervisorScript(File dir, File daemon) { + " touch \"$MARKER\"\n" + " if is_running; then exit 0; fi\n" + " ( while [ -f \"$MARKER\" ]; do\n" - + " \"$DAEMON\" \"$CONF\" >> \"$LOG\" 2>&1\n" + + " \"$DAEMON\" --config \"$CONF\" >> \"$LOG\" 2>&1\n" + " sleep 2\n" + " done ) >/dev/null 2>&1 &\n" + " sleep 1\n" diff --git a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java index 8e8fae0b2..6df5ec58a 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java +++ b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java @@ -280,6 +280,10 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, if (enableDnsHijack != null) { enableDnsHijack.setChecked(false); } + CheckBoxPreference dnsBootPersistence = (CheckBoxPreference) findPreference("dnsHijackBootPersistence"); + if (dnsBootPersistence != null) { + dnsBootPersistence.setChecked(false); + } G.enableRoam(false); G.enableLAN(false); @@ -288,6 +292,7 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, G.enableTor(false); G.enableCustomRules(false); G.enableDnsHijack(false); + G.dnsHijackBootPersistence(false); } } @@ -415,7 +420,8 @@ public void cbFunc(RootCommand state) { if (isDnsHijackPreference(key)) { Api.setRulesUpToDate(false); - if (!key.equals("enableDnsHijack") && !key.equals("dnsHijackPort") && G.enableDnsHijack()) { + if (!key.equals("enableDnsHijack") && !key.equals("dnsHijackPort") + && !key.equals("dnsHijackBootPersistence") && G.enableDnsHijack()) { DnsHijackManager.requestReload(ctx); } } @@ -428,6 +434,7 @@ private boolean isDnsHijackPreference(String key) { || key.equals("dnsHijackUpstreams") || key.equals("dnsHijackFailOpen") || key.equals("dnsHijackStrictMode") + || key.equals("dnsHijackBootPersistence") || key.equals("dnsHijackTimeoutMs") || key.equals("dnsHijackAllowExact") || key.equals("dnsHijackAllowSuffix") diff --git a/app/src/main/java/dev/ukanth/ufirewall/util/G.java b/app/src/main/java/dev/ukanth/ufirewall/util/G.java index 801d13480..bb4c99633 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/util/G.java +++ b/app/src/main/java/dev/ukanth/ufirewall/util/G.java @@ -176,6 +176,7 @@ public static Context getContext() { private static final String DNS_HIJACK_UPSTREAMS = "dnsHijackUpstreams"; private static final String DNS_HIJACK_FAIL_OPEN = "dnsHijackFailOpen"; private static final String DNS_HIJACK_STRICT_MODE = "dnsHijackStrictMode"; + private static final String DNS_HIJACK_BOOT_PERSISTENCE = "dnsHijackBootPersistence"; private static final String DNS_HIJACK_TIMEOUT_MS = "dnsHijackTimeoutMs"; private static final String DNS_HIJACK_ALLOW_EXACT = "dnsHijackAllowExact"; private static final String DNS_HIJACK_ALLOW_SUFFIX = "dnsHijackAllowSuffix"; @@ -294,6 +295,15 @@ public static boolean dnsHijackStrictMode() { return gPrefs.getBoolean(DNS_HIJACK_STRICT_MODE, false); } + public static boolean dnsHijackBootPersistence() { + return gPrefs.getBoolean(DNS_HIJACK_BOOT_PERSISTENCE, false); + } + + public static boolean dnsHijackBootPersistence(boolean val) { + gPrefs.edit().putBoolean(DNS_HIJACK_BOOT_PERSISTENCE, val).commit(); + return val; + } + public static int dnsHijackTimeoutMs() { return readIntPreference(DNS_HIJACK_TIMEOUT_MS, 2500, 250, 10000); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index acc2048ac..5c82650cd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -309,6 +309,8 @@ Allow upstream DNS when filtering cannot complete instead of blocking the query. Strict allow/block priority When enabled, exact and wildcard block rules can override allow rules. + Restore DNS filtering at boot + Install a root boot script that restarts the DNS daemon and restores DNS redirect rules before opening the app. Upstream timeout DNS upstream timeout in milliseconds. Exact allow domains diff --git a/app/src/main/res/xml/rules_preferences.xml b/app/src/main/res/xml/rules_preferences.xml index f8b5cdb79..e7ab1743c 100644 --- a/app/src/main/res/xml/rules_preferences.xml +++ b/app/src/main/res/xml/rules_preferences.xml @@ -105,6 +105,13 @@ android:summary="@string/dns_hijack_strict_summary" android:title="@string/dns_hijack_strict_title" /> + + Date: Fri, 26 Jun 2026 14:32:06 -0700 Subject: [PATCH 008/108] Add DNS protection repair action --- .../activity/DiagnosticsActivity.java | 23 ++++++ .../ufirewall/dns/DnsHijackManager.java | 76 ++++++++++++++++++- app/src/main/res/values/strings.xml | 2 + 3 files changed, 98 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/dev/ukanth/ufirewall/activity/DiagnosticsActivity.java b/app/src/main/java/dev/ukanth/ufirewall/activity/DiagnosticsActivity.java index 063a31fda..be58a8f16 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/activity/DiagnosticsActivity.java +++ b/app/src/main/java/dev/ukanth/ufirewall/activity/DiagnosticsActivity.java @@ -15,6 +15,7 @@ public class DiagnosticsActivity extends RulesActivity { private static final int MENU_DNS_RELOAD = 101; private static final int MENU_DNS_RESTART = 102; private static final int MENU_DNS_STOP = 103; + private static final int MENU_DNS_REPAIR = 104; @Override protected void onCreate(Bundle savedInstanceState) { @@ -25,6 +26,7 @@ protected void onCreate(Bundle savedInstanceState) { @Override protected void populateMenu(SubMenu sub) { super.populateMenu(sub); + sub.add(0, MENU_DNS_REPAIR, 0, R.string.dns_diagnostics_repair).setIcon(R.drawable.ic_apply_menu); sub.add(0, MENU_DNS_RELOAD, 0, R.string.dns_diagnostics_reload).setIcon(R.drawable.ic_refresh); sub.add(0, MENU_DNS_RESTART, 0, R.string.dns_diagnostics_restart).setIcon(R.drawable.ic_apply_menu); sub.add(0, MENU_DNS_STOP, 0, R.string.dns_diagnostics_stop).setIcon(R.drawable.ic_clearlog); @@ -81,6 +83,9 @@ public void cbFunc(RootCommand state) { @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case MENU_DNS_REPAIR: + runDnsRepair(); + return true; case MENU_DNS_RELOAD: runDnsAction("reload", getString(R.string.dns_diagnostics_reload_queued)); return true; @@ -95,6 +100,24 @@ public boolean onOptionsItemSelected(MenuItem item) { } } + private void runDnsRepair() { + String successMessage = getString(R.string.dns_diagnostics_repair_queued); + updateLoadingState(successMessage); + DnsHijackManager.repairDnsProtection(this, new RootCommand.Callback() { + @Override + public void cbFunc(RootCommand state) { + runOnUiThread(() -> { + if (state.exitCode == 0) { + Api.toast(DiagnosticsActivity.this, successMessage); + } else { + Api.toast(DiagnosticsActivity.this, getString(R.string.error_apply)); + } + populateData(DiagnosticsActivity.this); + }); + } + }); + } + private void runDnsAction(String action, String successMessage) { updateLoadingState(successMessage); DnsHijackManager.runSupervisorAction(this, action, new RootCommand.Callback() { diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java index 84ee62765..1899aa738 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java @@ -116,6 +116,29 @@ public static void runSupervisorAction(Context context, String action, RootComma .run(context.getApplicationContext(), commands); } + public static void repairDnsProtection(Context context, RootCommand.Callback callback) { + if (context == null) { + return; + } + if (!G.enableDnsHijack()) { + failSupervisorAction(context, callback, "DNS hijacker repair requested while DNS capture is disabled"); + return; + } + if (!prepareDaemon(context)) { + failSupervisorAction(context, callback, "DNS hijacker repair requested but daemon files could not be prepared"); + return; + } + + List commands = buildRootRepairCommands(context); + ApplicationErrorLog.add(context, "DNS hijacker repair queued: daemon start and DNS redirect reinstall"); + new RootCommand() + .setLogging(true) + .setReopenShell(true) + .setFailureToast(R.string.error_apply) + .setCallback(callback) + .run(context.getApplicationContext(), commands); + } + public static String collectLocalDiagnostics(Context context) { StringBuilder out = new StringBuilder(); File dir = workDir(context); @@ -372,12 +395,59 @@ private static String buildInstallBootPersistenceCommand(File bootScript) { + "true"; } - private static void appendRemoveBootPersistenceCommand(List commands) { - commands.add("#LITERAL# for FILE in /data/adb/service.d/" + BOOT_SCRIPT + private static String buildRemoveBootPersistenceCommand() { + return "for FILE in /data/adb/service.d/" + BOOT_SCRIPT + " /su/su.d/" + BOOT_SCRIPT + " /system/su.d/" + BOOT_SCRIPT + " /system/etc/init.d/" + BOOT_SCRIPT - + "; do [ -e \"$FILE\" ] && rm -f \"$FILE\" 2>/dev/null; done; true"); + + "; do [ -e \"$FILE\" ] && rm -f \"$FILE\" 2>/dev/null; done; true"; + } + + private static void appendRemoveBootPersistenceCommand(List commands) { + commands.add("#LITERAL# " + buildRemoveBootPersistenceCommand()); + } + + private static List buildRootRepairCommands(Context context) { + List commands = new ArrayList<>(); + File bootScript = new File(workDir(context), BOOT_SCRIPT); + commands.add(shellQuote(supervisorPath(context)) + " start"); + appendRootRedirectRepairCommands(context, commands, false); + if (G.enableIPv6()) { + appendRootRedirectRepairCommands(context, commands, true); + } + if (G.dnsHijackBootPersistence()) { + commands.add(buildInstallBootPersistenceCommand(bootScript)); + } else { + commands.add(buildRemoveBootPersistenceCommand()); + } + return commands; + } + + private static void appendRootRedirectRepairCommands(Context context, List commands, boolean ipv6) { + String iptables = shellQuote(Api.getBinaryPath(context, ipv6)); + int port = G.dnsHijackPort(DEFAULT_PORT); + String chain = ipv6 ? CHAIN_V6 : CHAIN_V4; + String preChain = ipv6 ? CHAIN_V6_PRE : CHAIN_V4_PRE; + + commands.add(iptables + " -t nat -D OUTPUT -p udp --dport 53 -j " + chain + " >/dev/null 2>&1 || true"); + commands.add(iptables + " -t nat -D OUTPUT -p tcp --dport 53 -j " + chain + " >/dev/null 2>&1 || true"); + commands.add(iptables + " -t nat -D PREROUTING -p udp --dport 53 -j " + preChain + " >/dev/null 2>&1 || true"); + commands.add(iptables + " -t nat -D PREROUTING -p tcp --dport 53 -j " + preChain + " >/dev/null 2>&1 || true"); + commands.add(iptables + " -t nat -N " + chain + " >/dev/null 2>&1 || true"); + commands.add(iptables + " -t nat -N " + preChain + " >/dev/null 2>&1 || true"); + commands.add(iptables + " -t nat -F " + chain); + commands.add(iptables + " -t nat -F " + preChain); + commands.add(iptables + " -t nat -A " + chain + " -o lo -j RETURN"); + commands.add(iptables + " -t nat -A " + chain + " -m owner --uid-owner 0 -j RETURN"); + commands.add(iptables + " -t nat -A " + chain + " -p udp --dport 53 -j REDIRECT --to-ports " + port); + commands.add(iptables + " -t nat -A " + chain + " -p tcp --dport 53 -j REDIRECT --to-ports " + port); + commands.add(iptables + " -t nat -A " + preChain + " -i lo -j RETURN"); + commands.add(iptables + " -t nat -A " + preChain + " -p udp --dport 53 -j REDIRECT --to-ports " + port); + commands.add(iptables + " -t nat -A " + preChain + " -p tcp --dport 53 -j REDIRECT --to-ports " + port); + commands.add(iptables + " -t nat -I OUTPUT 1 -p udp --dport 53 -j " + chain); + commands.add(iptables + " -t nat -I OUTPUT 1 -p tcp --dport 53 -j " + chain); + commands.add(iptables + " -t nat -I PREROUTING 1 -p udp --dport 53 -j " + preChain); + commands.add(iptables + " -t nat -I PREROUTING 1 -p tcp --dport 53 -j " + preChain); } private static void appendRedirectRules(List commands, boolean ipv6) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5c82650cd..729a7412b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -337,9 +337,11 @@ DNS blocklist update failed. DNS daemon diagnostics Loading DNS daemon diagnostics + Repair DNS protection Reload DNS daemon Restart DNS daemon Stop DNS daemon + DNS protection repair requested. DNS daemon reload requested. DNS daemon restart requested. DNS daemon stop requested. From e6b22df8c584cf6bdb5bc3403dca6e6631c0fa7e Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 14:37:40 -0700 Subject: [PATCH 009/108] Add temporary DNS query rules --- .../main/assets/dnsd/arm64-v8a/afwall_dnsd | Bin 22792 -> 24064 bytes .../main/assets/dnsd/armeabi-v7a/afwall_dnsd | Bin 18452 -> 19384 bytes app/src/main/assets/dnsd/x86/afwall_dnsd | Bin 22760 -> 24092 bytes app/src/main/assets/dnsd/x86_64/afwall_dnsd | Bin 23952 -> 25184 bytes .../activity/DnsQueriesActivity.java | 12 ++- .../ufirewall/dns/DnsHijackManager.java | 34 +++++- .../java/dev/ukanth/ufirewall/util/G.java | 93 ++++++++++++++++ app/src/main/res/values/strings.xml | 2 + dnsdaemon/jni/afwall_dnsd.c | 100 +++++++++++++++++- 9 files changed, 235 insertions(+), 6 deletions(-) diff --git a/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd b/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd index 8a09e16c29adf6fc78e069260ec129ff175deaed..1ae2440f970ddadfc32c10f265af65dbad212af0 100755 GIT binary patch delta 12347 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 a#@j0_I{Ys8r)2T2+Y2qnV-%-=vHd@Z4jPaE delta 11117 zcmc&)d3aPswy%3{r*k`rp_6pFvjCliC224LOhN(zH$flrH)MrRpqo>eM->PSveW;1!|md7&dG)1J%pqQo24<5fMs@ONJq2aT55bzzTOT`uqz+T7SSzc#z2Dp@q~PXFlNdBRS(je%EAx7 zdz%IAW`_>`xAw_6nmxJilrTeZ{LJ6={-*QOf3fn#x)U$G{=4d)$M!7e8RGDLKIx<+ ztl<-_E@8d?_g?+)cKz=o^p{7HeWL{?u*WcW!g}o1E0QpQ$ev8-L(K$!yX@lKlEps( zP-#K|QnCQ`N>mz?g=&=1iH-~HNYoru8Ff6WQD8wf4s{r632Hg2Q4$_!9s?0?r?WD2 zlE02*!0!j6zM*dyI|c>*Xw7Am&t(%gn_FfEJpLnrbGXe+4RqiUU@4@wK)z z-g~nQDQQ<00$YSS0yP8GFkv?OZq$5KCn}YceHke$1imS?$-i(#93_zfQH=1u>3_ic zzJX_X@o{W@yfx%JoiJKcf?t4qvrpRMcs~>UK2jWK%#x$gum=oKL`;M!H5nT z7d7F@??yRk!c&YGWypl5Fuq)T@g7;!hzi2U!278~1PU3W*nROH;f=gRm>d&6kq>mn z0u!FX%_t?lc#q^5p+}erU*Y|XHl=fsE4Ri}z>%We%gP^Tm6FcN<8wcbV`7CVaqzr;TcqHoq_4 zB|)@%jnd(Z_XuBXAkqHBgdb(Xcbf1K22j2=%1K|mNBDAN z!z|uwe{SDH8Mlc%$MLaW$d{&ef+GvH3oHkS8+qV;G!C?%qMbl_0l8-z+6uHC2=>ir z8xb3?qTP)4eQFUB4&qL@NDN*N%f$o@#~y3 zt!db)uiE&0=P0qw#$Ry`ceWw)4OdlTTs2gFERUaXP7!_i+~e|yf63=JxXQ%k!}0;9e{u@`7Xc@^bxu&PrV?+m(AB8wRp3Wc4sk8nC;44@1KjwI>Y0$c&jElKbtn<*_ zR?h2ktE_G4c23~;<(64rL06v0pU=I1W(VS;gB@pg$iX>U=`(Y*5pV`FHJCO4%W9R2uv$mq({|NY$JBmzz*`Ky zQI>#rjmW}2E4x^TF(oYEJtC&PrSsmDuJU#Hjs_P9UDg05a)kdYG{H zU!oL~?~_!Yk7F@AJoq$!Yxa{31V%mbY9} z)8$|lCq%Y0kj<*F`d<0ayc$_#6$R+C?le_br6)uEJeBQK1h)UI#6n-7FK$-2PJ76r zMkGgw=+q9OB`q3*%pMT}-ag>Yznu~vkL3}3CYAYj79@a5w13ASgjTPD0kwdg#kJvn z*fjQXX87DyV)#bjKLJmtG&K2GvZ59y1-x}qzh`OB$50_7ZZW6lFvi3lNUM1OxVU~!&lVQ&d)t9flE`RI z&o=aF_lPi>9v2sesqzbRGhY_cB z0gFm<7K4w%hPGjFtNoTCw_qFGGMhEVQWZ5elV`e%ZQU02P*uRYI+ag%yZjlo;lGJ; zOV8o9yyyxcJTR42$e3UWgs{@?Y1EG_4oqXCyQf7K1g6zMf#cXlM=|Mun`x_eC|dhR z0dMpw7EXoL2A-H7{8n?zfz*!!-s3J?kZ_S?IT(?Kd%g{PJMht83OfFyCs^1&;8(PN zp#jl=_v5GHLO#m!2Ja#qT%)h_Rf{?fg1*?t!uOF7;D=sjVZwdrUKDHr?$Qw!J~<~j zICzwW2k%g{6Em#APs%O9=(vT!PbVh@qY~5P05-`l5zgaScvlMT#^HWX7EHF>qPwP7 zhBdH~3W|-sBUXJkh<5Cdtyeq~*_w_z4AuUO6Jz4^Y!A^hFT+k9P6r%aQ5%jd?w&?` z$G0Y_*dL)|s4R(PM3x1n*}&sV@()cmPb340PmBr~LMgb8W4nIH6N<1_F9djCzHsb4 zrU~G6Ti7YYSmPJSIgw(kp2%ZZSwB)h1mllAVO8sp0*>EGG*{?DjQ?p8R(>o==RNBu z=JyosFcQ~?zpM@SVIWOfh(WZ|X~MsQXD0l93a!kPusegT@BBR0c)g$p<6gP6Hr$lV zDx*gfZQ!V)JytCAesWK3c(A=ToIX0>l?B_;0qy61`~mQ5nqN8HAf(PsEfzXjw#e$_ z;CJ6X-4~0UEL>|*cjO#DO?g$dihkcwUmxvnGd0s&U$F+r`fak zRYgTgc9MouUt0^kB1INe7t<}O{TM<+x1o)VwA9>2bXY!ii=}2LPY4s-2JsPo?>v{k ztvDrY_T^)s`ci1iW_##dB)>fcT(@m#a%4gGG|F3)?^=<6ET}`sDY4g?7WqM7+U?+r z=d~O?ukA_jd>i;LNCPW7)g`dTDBMycxsFDpoGgzZxZ26gw5{NuP#}d*FU}Vh^QFb* z8GZ0w0xt-|+t;MGm z)9DUPNc0RK#oY+i2tN^R+zjy$o&{Jr7K0g_m(9=!TxWl5autPU|FD1_j)r;{V27*0 zKp{D|FV;x8)xD;mn!@l&2}-@ln@1JrzE~F?*f?vGTS#eXN)LDog!;P!IGREI#i)_Z z0mO0?EDwJ6uy^2CL(L~^pWPq}DGdlA4=yYfL~H*3_v5rHp4~uc#h`Z$V-#>Vn@Hp=fs;njQ3EiuKbJ4Tsf!qOZJH(F)}5N2%X`pTbveSG2*6iY7^^M}PI( zn9g(C7Dd}8|KZV9mtw9vnSPE`$yfueSzo7JQcI8lS2Z^cT{#N+?EqsN_820~W9%=v zupyj=JxI6PFRUyhCR)}<_`_o+_%}`1pXcaIF-J7~3_mI3Q;N2q1p_{<3G_d_qq#L?( zo32_NVHcUgRJwomV|fx}>pZw~`s%=g=%@QBr6;d{x~1mM zNy*{&!ASSeZg`d9MAip9X;+OqX$17htoRKvk36}RsX~CRPL9wN2=hb6Rb-MHeyJpH zM9ztay*Hlt-RaHG{Py%a<9~O0%^!!WP45m@Z~FeT8~%e=mKGPj2!S-YS&$O~B9&}E z;a2iZrS3_?fGM~X+mG8%h_HWivg$_NMb3~HZM0Yk4{)VM7IO5B)|SiPEFB}3C zMiUu9G#(jm;eQ%8K`a;!;y59nPZ|%Fe0~d>XdZu%pge;7^6}UU@*3`yVGy4vx3}T2 z??&_@5rw8;y|RTZatrw_J^ispAHED6hzMUDj14*+9nP2`$%9WP(TAJp+_HL@N- z&d^xM!WY;2X!7p7rW6(yJd{w8NXJa{3gvv$#AT~-TRRy2$m1k*R)w!#l?GG2@b6g zf}h_g;;UBDziNM2EbRRe>i)c0+I!Af+HTP`*eSBc0*qtb&@2|~EtDm78|IAQRBf{| zyE<@5Iz{<|?$TI1r&{^lm388;llZSI=Zn8d;^|dog2<;;J&=v( z7F`Gl?1!EG_gQL^`3F^j!i1#NU?@mt`|+)YYo(E-vO_N?@w+FF6!#_ZM<;J^dcf5O zDs2uD^EZfjA&D1N7m3wLe0KFDVI$u@rFb&E4}5|50Lnk~VG_Aj&@Z27q$JM;$r3s* zNg)mTQ?8y1ndE*P()@2z<`?y5sCVJ!z6DiB7mBK_P|;EZh=Cc|S_@w=H9PZZTrl)+ z9%+UC$@BOf{CiW2{AY3Wb7bgqlBm9qFXF?^8>^eFOl`HYiWL{I_rHuaW(i`uA1-f0 z|4%rccYi6JDnWk-_zpBzRMW9O067)l+YPVRYq7>o(bj$lxoHx#rLi+F#u_Uu?1du; z`dAe^B_Vv;gaCJ4J!e`j{093-IUy&wOV)LGXWYsTlq9oFGhA%bQy6hZl0!Ss#`ZU5 zGSw}(220My8V8{9j5QT}*VPmKZTP;TZ8UIDu+#R|@|jk#rs+UW^TxY&Td|5P7H%;D zc3~lGE2^9EMZ@q&aR!?I(8}JzcUwoz;?e3sF>5e@O+!2pDL1qMd^M6q-H6o|#A22B zp~Mjz#=>}i$A_kVZ}2SNx4B>?qtcQYH0yX&3uN63k}Xst$nB&Y5}I0Lf5M`=CCA`7UAvsY zPF`5+_J=UNg6Z-4=D@lT$hJ@$>_Q@T!VV;U9K@6J$k=j0=Z1hJx7#s}9MfjqqEGuM zoI|vqg0@1+`I>W*z)Q{{HOM)nMJtwyjO6bv{B62A5tGaKa5fx3lMi7sQs6!eCMB?= zbR`C);n-y?Bu}6Nj!7EYRm$;sMh^A&BWkeFvehN|cG(Y4_cJ3c>$DPdX2!uLS7r)wDBP}}U! zx;Hf+sYA~w8k`hDW@*4zXZH1qHWgDlMzwk$D{iG1FpZv8C>SZttZ2EqI{SL2&2Y2z zHOVaFJXD!cjAJI5H8zR4sX3!rX5P5{yXspuS4S_!DrEHK+(luxkkzshaZ2#ORK*W{ z>hP&!YdM5~jBmNT&}t}TD8eqrDs|>mMU!{bYjm7^b{+zt7_F6Tn>DU$7hQu_-CwV* zOtGkMV0;fQ4Rm2>6Io496yx6#45j3;lOOZgi#+#s_Le^wPq&iKolT_Furb9DGjyih_-`J`zRZbH6j= zxjirj@iYKWFT+jV`Y;}w*UwF1jWmXmuby^}*wsopgTaSg?U{;sn!Ih{oiKJymZDCgH;-9NTZyx$2~Qnl16pq*4c%B5BzTd&CcM|;cr()c6ka&fRf&%bmokp> zSgxlJ7H?YI7N+nzh}DK*xi-A;v?5~ZDWPkFyo=SQsS$qttg*sMe($Vee=QbB7Q_}l z)rN#!CpnI;6dmm(&-_~OE@a~xd&J`Di)4z}-lgbA5n=!Zdd> zJ2i+jLl&g3ZL;F^JUDx*;Nc(6Zt+7u2dvsF*Gek3*-2Xlq6Uvf`rR&rX(9bt*&Ram z*jv~wscE`Zovz^zbw8ZvMMdrOnL z_Z^*+BwY6r6j=I%NN>QQdO>c$7VM>5AR|ZMd7;6D_Ussz8O8q2!v4O~^YX5)=FQdh zc)o2yKfb?REr;NYCO+cY{M-Y$LK{->yoiSeXQ)I1H(zwE+fN}v(e^`6*RD3?n6Bog zYB;ijw)UCC)@}nWzU|rIXI9pz>v%*|=@h2%#CNt>(R1^KKhy>5r8q3(Qe2O)q;SLs zHVozVh>&|PG>WI0>~#HONPj^q2zc+|LW6ti8IZ}2J49#uIK*AbBD@kmC~G^Q-c!w` z)z?Dof%|36wn*Ovy|R$7cc+CfYsf96TNoWR+b+ahq}IC#3yL2sYbVm6>m~kh0~em- zg>x4RYx$jXXC_mml=eyd;M@^z>X&S1+K=({_aG{+!@W6MWi?vV5T1({z4LR69C*>Q zZDT|GaSzikr}&;b$0yDkD-7}_^YW8%&hG>}zh_>)kivgF?@D1je{J5a!dzZ@-HpP( z^DWmEUyEaC=P~_On)S6exaWc2lBsB|nMxQpXwMiZ-K_^+mS-PmS@`YXI2J^01VL29 zKfA76c$bfuKVJNaozI75yW?MJD(Yz;!101mIOB_%z^F6Z|>gJtp`|z=!=N#3dm5FT=eV z_%XvS;`#z>K*8P&E8rp%oB|lX_g$u^172l<;W2xw33dYBV}kPl`wyECBZ25Q!9{>Y z;j0P804_4Y9>8@bxD4ueogwVyrHf}2l_399!3|z7 z3-Rqw1y^motXsh!Ts(czr+Bxcf)hnA^bZ46&RxPQEJ{5t98?mc*=-5zZdIeFJH2Ba)uFeM!S$d zzO+0efRshWXfN=-W$s6o*)zWR-BpM85L@;%GS zGQJsM48qG(F8_b(bv$o*Rm#E@aghrb@TJSEGS(%)bqnI?HvahX^2{M$92!~}Z{=aU we|cHT&^iOn^KP!n%2^)=9k{eoDfnPEzxC!y(Xog>dh>K!B!NE8`|R%j0$*WE?*IS* diff --git a/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd b/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd index d8a3ca1215d493a065382e4abef14578b0fd7c70..82646a1dd03b9ed828bf8eddb30d61d025711f50 100755 GIT binary patch delta 11323 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 delta 10422 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%0Dc(E5r@vLQD6mY>6S$e@G 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 diff --git a/app/src/main/assets/dnsd/x86/afwall_dnsd b/app/src/main/assets/dnsd/x86/afwall_dnsd index 80a765422df6e0ce1efcc6d6cb154a2476fbf2a2..0b64565e8605d7bce729e13280d9ed87992bd9ee 100755 GIT binary patch literal 24092 zcmcJ14`5W)neUx2z<>jH)TmKY9qXv!ftZ1ai9{VRLR>>TQB3H{HiTrtB!)~jnS|IP zB;E<;_U2;xz&^KiUwPG9w)J)C!V3sg5@3^{RzY2~)>_(H_fErZgLNUOW!~?1&fLi` z;%?u*_XbYR`Of*ycfRwT@B7Z*nT_|9Epa#;iv5|SOi~C1vK6HOalv28k^;r6Ojq)h zE0r8&3iH!K02LUV$YYp<5Cv?9O93;m4A~+eN_~!2C!n3H9KTQ$s z+U3y|px+?_swf4=zLZ72Se}I_z5WPb29}eD`+pa$O)t0U+x!Jlo&!2|cph~aSk6$6 zazvl`i1v|7oF4FOhy8#V?E1H~KGGTut-WP+ebX(C^-T|lS`@{F@)!c;v#6=IB~o9j zT!wVZyxVFJ{ii?vc?Gu><@*c&vjoU9R6&gC(l0%zWIs24&(3A<-eF#~=f|&fzjf$^ zy$_J(^FHYrm!M=uS}EbHGT`en;QS2u)(p5f11`yc{~`k}&w#&@0k6t{*JQv=8So<+ z@P-VS<7j^_Mnbm%#O!}x2K?VL;J?j)f0zOPBm*AEfRALr$1~txX28G8fKO(?A7#Lk z(*~IRac97nWWd*Ez&B>VvoqlN88Cf|{b74cGvKleI9(%&|4>GGO$OYU0Y8!fcV)n4 z2K;0O{JjjA9_j!0KLj44>Enc-Mtn0ux^2_P`w`MVJ^)h@=##&I@Lv%4p--_t*CBBYLJmTnor!pE zGJQQ_`k@;UZb7&SfuA`t5`R_vy&?_%KS?GKVC%B(_p2ls(_=9_(MUbJ%X}a(R||Dy|pPRQV!JI z)`(Je@8Y{5uhor_H3X4bn~ZB4nRp5l3&;KGWV|gIcVHdE{AU4Af#U5#JQYg0hcOIi zKVul;0Am=!Va71R5ymjcR~S#lnujq6y~!Ac{5E4K)w_(LfF~G3q2Ff=!?hSg*-tWt z0gW++(tgAkj&qzbjQUf?G}tg=D7TX_l-I==M(1V>H*ID-PlFqA^ZF#cl3a3lf7FrpI1a0aD}Z&H*p#(9boWDKXZ zoG~2D3dV43D;dLCtYQqORm&L8CCnHOrI9h5TQlPf2euL2PXACN*HyK))z#H^RMkO8 z(~TU6^mFMSC<8Ql0zZ^qh%|Jwz9w1)s|qRUw3VhvRZFO~Ino4Ut*NdFqgaVN>}?4( zMyhMQYeG$-mg;DIr0I?u8XMcDEBx!dp;i2^UE4Zcp#fD12hi4xMnctVg-wNO70FVl zqZ%6B)>^$LbUSO^d^5DXu6~WTxVbtSzH>S({^6#`x~3$$FblL&i-IIQ1#8&mDnTvD zxzIRa_#iCX1WE*eP(a|x-HaFA8M6_ZMDr+=Ve4| zGBWC$+N&GU=y_P8-4NS?cm$I+kdjOlmf6k8Rz#+7d$qDl$$TODs@D3ifz{gS5(+h8 z(8!*h5w4G(hrYJHwbf={Rslv8#w%3S+`Lw@lq4LDV3gByLLJTZEjFvk_S&H$80sXR zEq~|-dfaL^oyu-)gIk?oAeGN9wxwFDZeLT?2#%U+9;sTJq`bDe<1=}w>KCdYwJ}+{ zrL8g4S|#+VN=Tmql9@^U&&ZXiVr)Kxnvp9sE0e0s%)k^%nbFXMqOu*uKUe${b7rIs z#@9*@A8m;=Rwd^{+Zd!3NwrYY*cJJqT5mMs73L^Shjuhw!PFLMN!qCmC2gq+^Um7p zCa}Pc(55YnyMWu3Lxx zRn<1N)?!wvd04@GBMnZ7BI#^6&4oIW<_X8q8jUnJ!vv=*$-xlF$~q-!JxLRmZUO7W zt0yho4*x{AU&uKJaS!4##M=?)V19ZVG1uNXn2XjU4r313&V2anH<|ClT*7?#YA+mP z4t#Yf;ys9)5f{Q&KaJQzd>C;UzIu%1@X@)L?>g=TK4RBhz(>3%0DQ!Gi!t{h?m;|; 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 SaVf#CD9Ue;XMc#p&;JIUB`SUZ literal 22760 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 l|12Zl1ZMsHCc%Iv|0ZO55 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 diff --git a/app/src/main/java/dev/ukanth/ufirewall/activity/DnsQueriesActivity.java b/app/src/main/java/dev/ukanth/ufirewall/activity/DnsQueriesActivity.java index 058eb0ffd..af926ac54 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/activity/DnsQueriesActivity.java +++ b/app/src/main/java/dev/ukanth/ufirewall/activity/DnsQueriesActivity.java @@ -155,8 +155,10 @@ private void showQueryActions(DnsHijackManager.QueryEntry entry) { .items(new CharSequence[]{ getString(R.string.dns_query_allow_exact), getString(R.string.dns_query_allow_suffix), + getString(R.string.dns_query_temp_allow), getString(R.string.dns_query_block_exact), - getString(R.string.dns_query_block_suffix) + getString(R.string.dns_query_block_suffix), + getString(R.string.dns_query_temp_block) }) .itemsCallback((dialog, view, which, text) -> applyQueryAction(entry, which)) .negativeText(R.string.Cancel) @@ -173,11 +175,17 @@ private void applyQueryAction(DnsHijackManager.QueryEntry entry, int which) { action = DnsHijackManager.RULE_ALLOW_SUFFIX; break; case 2: - action = DnsHijackManager.RULE_BLOCK_EXACT; + action = DnsHijackManager.RULE_TEMP_ALLOW; break; case 3: + action = DnsHijackManager.RULE_BLOCK_EXACT; + break; + case 4: action = DnsHijackManager.RULE_BLOCK_SUFFIX; break; + case 5: + action = DnsHijackManager.RULE_TEMP_BLOCK; + break; default: return; } diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java index 1899aa738..42c1ab6b2 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java @@ -46,6 +46,9 @@ public final class DnsHijackManager { public static final int RULE_ALLOW_SUFFIX = 2; public static final int RULE_BLOCK_EXACT = 3; public static final int RULE_BLOCK_SUFFIX = 4; + public static final int RULE_TEMP_ALLOW = 5; + public static final int RULE_TEMP_BLOCK = 6; + private static final long TEMP_RULE_DURATION_SECONDS = 15L * 60L; private DnsHijackManager() { } @@ -158,6 +161,8 @@ public static String collectLocalDiagnostics(Context context) { out.append("fail_open=").append(G.dnsHijackFailOpen()).append('\n'); out.append("strict_mode=").append(G.dnsHijackStrictMode()).append('\n'); out.append("timeout_ms=").append(G.dnsHijackTimeoutMs()).append('\n'); + out.append("temporary_allow_entries=").append(countLines(G.dnsHijackTempAllow())).append('\n'); + out.append("temporary_block_entries=").append(countLines(G.dnsHijackTempBlock())).append('\n'); out.append("\n[blocklists]\n"); out.append(DnsBlocklistManager.getSummary(context)).append('\n'); appendFileInfo(out, "work_dir", dir); @@ -211,11 +216,17 @@ public static boolean addRuleFromQuery(Context context, QueryEntry entry, int ac case RULE_BLOCK_SUFFIX: added = G.appendDnsHijackBlockSuffix(domain); break; + case RULE_TEMP_ALLOW: + added = G.appendDnsHijackTempAllow(domain, temporaryRuleExpiresAt()); + break; + case RULE_TEMP_BLOCK: + added = G.appendDnsHijackTempBlock(domain, temporaryRuleExpiresAt()); + break; default: return false; } if (added) { - ApplicationErrorLog.add(context, "DNS query action added rule for " + domain); + ApplicationErrorLog.add(context, "DNS query action added rule for " + domain + " action=" + action); requestReload(context); } return added; @@ -307,6 +318,24 @@ private static String normalizeSupervisorAction(String action) { return null; } + private static long temporaryRuleExpiresAt() { + return (System.currentTimeMillis() / 1000L) + TEMP_RULE_DURATION_SECONDS; + } + + private static int countLines(String raw) { + int count = 0; + if (raw == null || raw.trim().isEmpty()) { + return 0; + } + String[] lines = raw.split("\\r?\\n"); + for (String line : lines) { + if (line != null && !line.trim().isEmpty()) { + count++; + } + } + return count; + } + public static final class QueryEntry { public final long timestamp; public final String action; @@ -551,6 +580,7 @@ private static void copyDaemonAsset(Context context, File target) throws IOExcep private static String buildConfig(Context context) { File dir = workDir(context); StringBuilder config = new StringBuilder(); + G.pruneExpiredDnsHijackTemporaryRules(); config.append("port=").append(G.dnsHijackPort(DEFAULT_PORT)).append('\n'); config.append("control_socket=").append(new File(dir, SOCKET).getAbsolutePath()).append('\n'); config.append("pid_file=").append(new File(dir, PID).getAbsolutePath()).append('\n'); @@ -566,6 +596,8 @@ private static String buildConfig(Context context) { appendConfigEntries(config, "block_suffix", G.dnsHijackBlockSuffix()); appendConfigEntries(config, "allow_regex", G.dnsHijackAllowRegex()); appendConfigEntries(config, "block_regex", G.dnsHijackBlockRegex()); + appendConfigEntries(config, "temp_allow", G.dnsHijackTempAllow()); + appendConfigEntries(config, "temp_block", G.dnsHijackTempBlock()); appendConfigFile(config, "block_exact_file", DnsBlocklistManager.exactBlockFile(context)); appendConfigFile(config, "block_suffix_file", DnsBlocklistManager.suffixBlockFile(context)); diff --git a/app/src/main/java/dev/ukanth/ufirewall/util/G.java b/app/src/main/java/dev/ukanth/ufirewall/util/G.java index bb4c99633..a38215c74 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/util/G.java +++ b/app/src/main/java/dev/ukanth/ufirewall/util/G.java @@ -184,6 +184,8 @@ public static Context getContext() { private static final String DNS_HIJACK_BLOCK_SUFFIX = "dnsHijackBlockSuffix"; private static final String DNS_HIJACK_ALLOW_REGEX = "dnsHijackAllowRegex"; private static final String DNS_HIJACK_BLOCK_REGEX = "dnsHijackBlockRegex"; + private static final String DNS_HIJACK_TEMP_ALLOW = "dnsHijackTempAllow"; + private static final String DNS_HIJACK_TEMP_BLOCK = "dnsHijackTempBlock"; private static final String DNS_HIJACK_BLOCKLIST_URLS = "dnsHijackBlocklistUrls"; private static final String SHOW_ALL_APPS = "showAllApps"; @@ -332,6 +334,14 @@ public static String dnsHijackBlockRegex() { return gPrefs.getString(DNS_HIJACK_BLOCK_REGEX, ""); } + public static String dnsHijackTempAllow() { + return gPrefs.getString(DNS_HIJACK_TEMP_ALLOW, ""); + } + + public static String dnsHijackTempBlock() { + return gPrefs.getString(DNS_HIJACK_TEMP_BLOCK, ""); + } + public static String dnsHijackBlocklistUrls() { return gPrefs.getString(DNS_HIJACK_BLOCKLIST_URLS, ""); } @@ -352,6 +362,19 @@ public static boolean appendDnsHijackBlockSuffix(String domain) { return appendLinePreference(DNS_HIJACK_BLOCK_SUFFIX, domain); } + public static boolean appendDnsHijackTempAllow(String domain, long expiresAtSeconds) { + return appendTemporaryLinePreference(DNS_HIJACK_TEMP_ALLOW, domain, expiresAtSeconds); + } + + public static boolean appendDnsHijackTempBlock(String domain, long expiresAtSeconds) { + return appendTemporaryLinePreference(DNS_HIJACK_TEMP_BLOCK, domain, expiresAtSeconds); + } + + public static void pruneExpiredDnsHijackTemporaryRules() { + pruneExpiredTemporaryPreference(DNS_HIJACK_TEMP_ALLOW); + pruneExpiredTemporaryPreference(DNS_HIJACK_TEMP_BLOCK); + } + private static boolean appendLinePreference(String key, String rawValue) { if (rawValue == null) { return false; @@ -378,6 +401,76 @@ private static boolean appendLinePreference(String key, String rawValue) { return added; } + private static boolean appendTemporaryLinePreference(String key, String rawValue, long expiresAtSeconds) { + if (rawValue == null || expiresAtSeconds <= (System.currentTimeMillis() / 1000L)) { + return false; + } + String value = rawValue.trim().toLowerCase(java.util.Locale.US); + if (value.isEmpty()) { + return false; + } + LinkedHashSet values = new LinkedHashSet<>(); + String prefix = value + "|"; + String existing = gPrefs.getString(key, ""); + boolean changed = false; + if (existing != null) { + String[] lines = existing.split("[\\r\\n]+"); + long now = System.currentTimeMillis() / 1000L; + for (String line : lines) { + String existingValue = line == null ? "" : line.trim().toLowerCase(java.util.Locale.US); + if (existingValue.isEmpty() || isExpiredTemporaryLine(existingValue, now)) { + changed = true; + continue; + } + if (existingValue.startsWith(prefix)) { + changed = true; + continue; + } + values.add(existingValue); + } + } + String entry = value + "|" + expiresAtSeconds; + boolean added = values.add(entry); + if (added || changed) { + gPrefs.edit().putString(key, android.text.TextUtils.join("\n", values)).commit(); + } + return added || changed; + } + + private static void pruneExpiredTemporaryPreference(String key) { + String existing = gPrefs.getString(key, ""); + if (existing == null || existing.trim().isEmpty()) { + return; + } + LinkedHashSet values = new LinkedHashSet<>(); + boolean changed = false; + long now = System.currentTimeMillis() / 1000L; + String[] lines = existing.split("[\\r\\n]+"); + for (String line : lines) { + String value = line == null ? "" : line.trim().toLowerCase(java.util.Locale.US); + if (value.isEmpty() || isExpiredTemporaryLine(value, now)) { + changed = true; + continue; + } + values.add(value); + } + if (changed) { + gPrefs.edit().putString(key, android.text.TextUtils.join("\n", values)).commit(); + } + } + + private static boolean isExpiredTemporaryLine(String value, long nowSeconds) { + int separator = value.lastIndexOf('|'); + if (separator <= 0 || separator + 1 >= value.length()) { + return true; + } + try { + return Long.parseLong(value.substring(separator + 1)) <= nowSeconds; + } catch (NumberFormatException e) { + return true; + } + } + private static int readIntPreference(String key, int fallback, int min, int max) { String value = gPrefs.getString(key, String.valueOf(fallback)); try { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 729a7412b..78044454f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -350,8 +350,10 @@ %1$d DNS queries loaded. Allow this domain Allow this domain and subdomains + Temporarily allow this domain Block this domain Block this domain and subdomains + Temporarily block this domain DNS rule added and daemon reload requested. DNS rule already exists. Log diff --git a/dnsdaemon/jni/afwall_dnsd.c b/dnsdaemon/jni/afwall_dnsd.c index c024e6f52..0b828b744 100644 --- a/dnsdaemon/jni/afwall_dnsd.c +++ b/dnsdaemon/jni/afwall_dnsd.c @@ -33,6 +33,7 @@ #define MAX_DOMAIN 256 #define MAX_RULES 32768 #define MAX_REGEX 128 +#define MAX_TEMP_RULES 1024 #define MAX_UPSTREAMS 8 #define CACHE_SIZE 1024 #define LOG_RING 256 @@ -54,6 +55,11 @@ typedef struct { bool valid; } regex_rule_t; +typedef struct { + char value[MAX_DOMAIN]; + uint64_t expires_at; +} temp_rule_t; + typedef struct { char host[128]; int port; @@ -81,6 +87,10 @@ typedef struct { regex_rule_t regex_block[MAX_REGEX]; int regex_allow_count; int regex_block_count; + temp_rule_t temp_allow[MAX_TEMP_RULES]; + temp_rule_t temp_block[MAX_TEMP_RULES]; + int temp_allow_count; + int temp_block_count; uint64_t generation; } config_t; @@ -296,6 +306,64 @@ static bool add_string_rule(string_rule_t *rules, int *count, const char *value) return true; } +static bool valid_domain_rule(const char *value) { + const char *p = value; + size_t label_len = 0; + bool dot_seen = false; + if (value == NULL || value[0] == '\0' || strlen(value) >= MAX_DOMAIN) { + return false; + } + while (*p) { + unsigned char c = (unsigned char) *p; + if (c == '.') { + if (label_len == 0 || label_len > 63) { + return false; + } + dot_seen = true; + label_len = 0; + } else if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-') { + label_len++; + } else { + return false; + } + p++; + } + return dot_seen && label_len > 0 && label_len <= 63; +} + +static bool add_temp_rule(temp_rule_t *rules, int *count, const char *value) { + char line[512]; + char *sep; + char *domain; + char *expires; + uint64_t expires_at; + if (*count >= MAX_TEMP_RULES || value == NULL || value[0] == '\0') { + return false; + } + safe_copy(line, sizeof(line), value); + sep = strchr(line, '|'); + if (sep == NULL) { + sep = strchr(line, ' '); + } + if (sep == NULL) { + return false; + } + *sep = '\0'; + domain = line; + expires = sep + 1; + trim(domain); + trim(expires); + lower_ascii(domain); + expires_at = (uint64_t) strtoull(expires, NULL, 10); + if (!valid_domain_rule(domain) || expires_at <= now_seconds()) { + return false; + } + safe_copy(rules[*count].value, sizeof(rules[*count].value), domain); + rules[*count].expires_at = expires_at; + (*count)++; + return true; +} + static bool add_regex_rule(regex_rule_t *rules, int *count, const char *value) { regex_rule_t *rule; if (*count >= MAX_REGEX || value == NULL || value[0] == '\0') { @@ -322,6 +390,16 @@ static bool exact_match(const string_rule_t *rules, int count, const char *domai return false; } +static bool temp_match(const temp_rule_t *rules, int count, const char *domain, uint64_t now) { + int i; + for (i = 0; i < count; i++) { + if (rules[i].expires_at > now && strcmp(rules[i].value, domain) == 0) { + return true; + } + } + return false; +} + static bool suffix_match(const string_rule_t *rules, int count, const char *domain) { int i; size_t domain_len = strlen(domain); @@ -351,12 +429,17 @@ static bool regex_match_rules(const regex_rule_t *rules, int count, const char * } static decision_t evaluate_domain(const config_t *cfg, const char *domain, const char **reason) { + uint64_t now = now_seconds(); + bool temp_allow = temp_match(cfg->temp_allow, cfg->temp_allow_count, domain, now); bool exact_allow = exact_match(cfg->exact_allow, cfg->exact_allow_count, domain); bool suffix_allow = suffix_match(cfg->suffix_allow, cfg->suffix_allow_count, domain); bool regex_allow = regex_match_rules(cfg->regex_allow, cfg->regex_allow_count, domain); bool block = false; - if (exact_match(cfg->exact_block, cfg->exact_block_count, domain)) { + if (temp_match(cfg->temp_block, cfg->temp_block_count, domain, now)) { + *reason = "temp_block"; + block = true; + } else if (exact_match(cfg->exact_block, cfg->exact_block_count, domain)) { *reason = "exact_block"; block = true; } else if (suffix_match(cfg->suffix_block, cfg->suffix_block_count, domain)) { @@ -370,6 +453,10 @@ static decision_t evaluate_domain(const config_t *cfg, const char *domain, const if (block && cfg->strict_mode) { return DECISION_BLOCK; } + if (temp_allow) { + *reason = "temp_allow"; + return DECISION_ALLOW; + } if (exact_allow) { *reason = "exact_allow"; return DECISION_ALLOW; @@ -836,6 +923,10 @@ static bool load_config(const char *path, config_t *new_cfg) { add_regex_rule(new_cfg->regex_block, &new_cfg->regex_block_count, value); } else if (strcmp(key, "block_regex_file") == 0) { load_regex_rule_file(new_cfg->regex_block, &new_cfg->regex_block_count, value); + } else if (strcmp(key, "temp_allow") == 0) { + add_temp_rule(new_cfg->temp_allow, &new_cfg->temp_allow_count, value); + } else if (strcmp(key, "temp_block") == 0) { + add_temp_rule(new_cfg->temp_block, &new_cfg->temp_block_count, value); } } fclose(fp); @@ -1167,7 +1258,8 @@ static void handle_control(int fd) { "upstream_requests=%llu\nupstream_successes=%llu\nupstream_failures=%llu\n" "avg_latency_ms=%llu\nmax_latency_ms=%llu\nupstream_avg_latency_ms=%llu\n" "reloads=%llu\nrules_exact_allow=%d\nrules_suffix_allow=%d\nrules_exact_block=%d\n" - "rules_suffix_block=%d\nrules_regex_allow=%d\nrules_regex_block=%d\n", + "rules_suffix_block=%d\nrules_regex_allow=%d\nrules_regex_block=%d\n" + "rules_temp_allow=%d\nrules_temp_block=%d\n", (long) getpid(), (unsigned long long) (now_seconds() - g_stats.start_time), (unsigned long long) g_cfg.generation, @@ -1200,7 +1292,9 @@ static void handle_control(int fd) { g_cfg.exact_block_count, g_cfg.suffix_block_count, g_cfg.regex_allow_count, - g_cfg.regex_block_count); + g_cfg.regex_block_count, + g_cfg.temp_allow_count, + g_cfg.temp_block_count); } else if (strcmp(cmd, "reload") == 0) { if (reload_config()) { write_control_response(client, "ok reload generation=%llu\n", (unsigned long long) g_cfg.generation); From c1284ef9c8441a14bc6a3a5c856389c7a9670c68 Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 14:41:51 -0700 Subject: [PATCH 010/108] Add DNS daemon health probe --- .../main/assets/dnsd/arm64-v8a/afwall_dnsd | Bin 24064 -> 25120 bytes .../main/assets/dnsd/armeabi-v7a/afwall_dnsd | Bin 19384 -> 20408 bytes app/src/main/assets/dnsd/x86/afwall_dnsd | Bin 24092 -> 25580 bytes app/src/main/assets/dnsd/x86_64/afwall_dnsd | Bin 25184 -> 26480 bytes .../ufirewall/dns/DnsHijackManager.java | 2 + dnsdaemon/jni/afwall_dnsd.c | 111 ++++++++++++++++++ 6 files changed, 113 insertions(+) diff --git a/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd b/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd index 1ae2440f970ddadfc32c10f265af65dbad212af0..895daeaa563eccbf8a3196cc4a3c50295087981e 100755 GIT binary patch delta 9204 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 LA@(%u)fxW>gig1* delta 8090 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 EpP?1vlK=n! diff --git a/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd b/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd index 82646a1dd03b9ed828bf8eddb30d61d025711f50..232f554929195c2f9114a9a4eaffe4a93ac54095 100755 GIT binary patch delta 7254 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 B(pLZg delta 6268 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 AsQ>@~ delta 6759 zcmb_heNYrvw(n_XkYNo23Wy(s5e6P=l$op$h`=(`fDMkyDpA(e4H`tuT0+H<2!@wy+>-4x8oca`Lz**P6GWVd@x>^&%$i-^10T78d z%v(1xJBIcMO&*BS@L&BZ)@Xdiv-jgHW-d%$&Z8(VH^fc(VH@&OhK%wb(wgtTHcefn zr{YsjjS<)vuZlVhd}3H;i2urAS{o{Dyw-kX`}%~_X?gZ3i7q*gpB1Q%*d68VsMEZ{ z zcvF}p+^h*y4|OX1MCo|ag`Zd*AH{jYG{+_B6y^zI)1W_&(-k{ zgn4SeNT-MiD}aKIx9Io^9nY4ns;$!TQ*`##I)18-uLG}+pTffykE(9aIV9*Dp3(7% zI=)HAPt)rK_R>G+vC`*s~4-eIKf(DBJS`%WGIpvtrP z59$;tI)`2zZ`JXAI)1i}@7M9EI(|UMr|Edbt5eu?iV+>3uH(mbe1?wap40@I%Ky;u zQ93?T$Hy|>OAd2%iX@%GTpe%K@$+x;w;}>uo{;{V>r^pJEKtadb zk+-JGZLv*(^tcPWti)gPKFw|3+PHqp<{G4(nGuWLfCnw*Hl&DN;0W*|Af<*8fE8#& zeyRrAfo)jFcY#HiEjRL0HLx1khFNL{7GYBQfCDr+NK-`!dIhi#*b02qj;IcxV4sW1 zjd&mBxCUSca6izV&v6Q{t$^cl(V6N(j;jLV3}{SDozn+Z2}!P)BHGJ#ypy4hA`TC6 zF1%54cj8n-ynHz^Er!PB!`<5v?PnGdD7lUzv(68%MrWyh|lEt)27)+T>RCT zaaVCnQ%P~mZoI7}u9$sz+wiuRERN|YDUInwIf%En#3k>Tma=GZOl#@ln0=+iF>R$K zG3_XK;O)d4#M_Iv4{tx-fl_zOh>LThBNYhX{&@MywDK8kD1Lz*r0p)P?{9+}Pmv3g ziX$o1BUX7=Qfj0PQLURTznL^QvJ%Dq+48ld^2pawR8r*y(;tnzfnsi&ymfkcc?8ADIUM(#{BcsEEYFy4&PQO29^trpmAO8{k+By{ zbuPypMUOf3-@tdoL^**FZFt{+p39SSX3mwZyiu;6nPp2}hIU(mFH9EvrneqPS#;TA z1%E;dECumn$EfmLo*bAtH|=F8ht}kATUh?`j0en2wc$T6{J;SixT~19fy&*PD4%JBWUsF&V*pj@2x5QXfy5$=r13 z7pnDL6|#rr)>-l1PMG(Y`e6>QTN||#7*+PJC)@1Q@ldGC3+3U8EoR=?NsCMIsXn$1 zs?SV7HcF0=vI9JtdH$T4Z~l(ovDJB$hvKi)1Gm56`dBFB_NQ-xc6h2K#f5fph?F&- z=9^FQdBe{aEs=KI9CwTNloHg_6124Z2A2NjyZzL9dIZq5opNm&(6oua-0rSw>YZWAEyzL@HGsNqbXJR z6oQoe^g6^8bHol*6x$4P+=ElCy-+)kVs=B$WAqne-Ax(BDV`Dhdu?`kYf7T`0E|eY zZQ&9_$EfZuYR%b6t4;Y8^p@2@OPtR}`$0hU3rUTq7G*2S(HvK%gxPsvZhTf-G;RRrLnhjjn zFVV>1E!0wH1=4_998~_i5F5;A^TY7IDc=fN5!B9YkE6k3b^8B`s@1%LTr^qBMT@X(Q!$2?#kkK3J5N!%`nhwhbDi@S&d1lCED^tJ zDp-OVVbOmt6dG>BPRxgV>=1&f{1X+rM8#zudFI8Eyl-9NH%`m)tIoXZfa}c#U;m68 zeGf$A&KWxC_P=hk(yH{&|K=St?-IAz;>EQ#^?9 z*VYPj1XnsMohzLyLLOTM-fFxJp|@>K(1o&{XU#lQG%!UcDc-ixSqunjFrWdY0gxPq z0$`R&nv`k4_??f{ahNeEt2DMwgJ(3@t-(GG+BN6|DF5kDCx#kuNeEduj2N7<^v8%5 zLa0#BE28K-xTY+6o)TTH_tI~#+ zn0$-m_z4*qcTh1xrc~As7r3hB0U$l%b+=a>bX;_tb^A37W$c-^?|Q_sz!Y zM{V(_stG1ka}rgHr;9E~=v6o!YPGgO>qgck52YQo;B>IObP-aScuMelkJ!fHi(~eG zNQX^Kc@`a~Xi}ngi=R+>qDH8bQNR+%S>-%FJ;++ooU6%MdQ~+OS}uCBU06%hq!y)# zt|+Cj9IAvyaii26mus~69>)e6nuObTbHUgu`IId`@sc3+3Ej$1%DTUp}%ErxwfQ>9Z0nUm{DN>89gH$+T1NOwPsfbLnZ$EniG% zMsS^m#=LkL-{XszhJK)nuSd}E5Dy&r*I`gD`qHdmXaz~8t6Syk=?{93Ze7lYmzaLS ze}}dxiHdM=iMJf1NcSIW-0tn*oCq^!iK0vom1$0JUscPrqUjOOXa^#$IOyPh)kY9M zaCTx+IVG3{dzbi`yfY)-{yTKh@u4M!6PoWBp0*4Ag|md6Jv0RMI2Gnxfu-YYi6cle zHOVfY$w)RN$)9GVcooNoZt-(iG^R5*nq$5BK?;!JBvy&{^6;kZ8)=fYb#PPgzsk&-gHJsxD`Far`vhkwI!&~Y%ZFBTm4rw)z+5wv1TvhV^a`M3X>S4{EoRzKBH0l+V~8Scso?Yjt#L;x#6AXyPj}(8pLhr$RAPcnrlt$M|5z+!2p{UmZVJ>piHQc8i7so~^oSAMZ zAwq38*+^rTl1-|VzCe{sSp=}FMy%$sa+M%u|8Ed{%cvXS-;HQ^B4@y0YPbB}yxHC) z_Y;^vVV)a@yOjMkESI+25X2+uG3plg+M3|u#!3H-8<&9w0e|WQ(POi^#Tr|M#rMr9 zvYKRii<-b0ZvI3aaB#{g??xQK9Mvw_j8p!1on*S#&V1e&rmV+%7MvTDKfyAvIlWT3RQlkVn}%w zh$cRSwepfyK94C=_4xh@fOkqS(j^DqrA15qf03_eO@BDe*>sGC!g+4cht9`vboT60 z8D>5FH>dP6U5Z-HzEDbT^X;=9dKaHa-+Nvo&(`}qRfplzj^NON+j66Q1OF#QzGBbj z2S1bJ9NB!a5)d43L_~KEghI8JTc*AN`QE~#(FP`(2Lh+F2aSCBHCQJGPCoia1Ha<~ z*^^(x|M-KzmHafGm#zdtg*OfSfAi41S6mPce%LC!TChCK}5XE?}klwss5)&YhYD&l_uau`v{ za23N^hK&q&F?@~TL57DI_Aq>(;UL3NhLNjT2N=>VB^22B_^^@BGRiAz7DP|{Vj=IT z$%$)9&>X^eNxo2H5C41<{$1jDo;+paf@muXv$axQZ%&k}H(H~=|EXrRyk}!hbohsj zjw<;bh`~Co@?e!5U7Itd;z>;m|6bE!l2_C&i2nX(n>F&D+MMWyXEm!WYvgxo3wc2F Srb2TreJtX+A-}Rd<^KRmI-9cq diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java index 42c1ab6b2..f8bbac42e 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java @@ -178,6 +178,8 @@ public static String collectLocalDiagnostics(Context context) { out.append("\n[control status]\n"); out.append(queryControl(context, "status")); + out.append("\n[control health]\n"); + out.append(queryControl(context, "health")); out.append("\n[recent queries]\n"); String logs = queryControl(context, "logs"); out.append(logs.trim().isEmpty() ? "no daemon query logs reported\n" : logs); diff --git a/dnsdaemon/jni/afwall_dnsd.c b/dnsdaemon/jni/afwall_dnsd.c index 0b828b744..92893c9a6 100644 --- a/dnsdaemon/jni/afwall_dnsd.c +++ b/dnsdaemon/jni/afwall_dnsd.c @@ -758,6 +758,38 @@ static ssize_t forward_udp(const config_t *cfg, const uint8_t *query, size_t que return -1; } +static ssize_t forward_udp_probe(const config_t *cfg, const uint8_t *query, size_t query_len, + uint8_t *response, size_t response_len, int *upstream_index) { + int i; + int timeout_ms = cfg->timeout_ms < 1000 ? cfg->timeout_ms : 1000; + if (timeout_ms < 250) { + timeout_ms = 250; + } + if (upstream_index != NULL) { + *upstream_index = -1; + } + for (i = 0; i < cfg->upstream_count; i++) { + int fd = connect_upstream(&cfg->upstreams[i], SOCK_DGRAM, timeout_ms); + ssize_t got; + if (fd < 0) { + continue; + } + if (send(fd, query, query_len, 0) < 0) { + close(fd); + continue; + } + got = recv(fd, response, response_len, 0); + close(fd); + if (got > 0) { + if (upstream_index != NULL) { + *upstream_index = i; + } + return got; + } + } + return -1; +} + static ssize_t read_full(int fd, uint8_t *buf, size_t len) { size_t got = 0; while (got < len) { @@ -1234,6 +1266,83 @@ static void write_control_response(int fd, const char *fmt, ...) { } } +static size_t build_health_query(uint8_t *out, size_t out_len) { + uint16_t id = (uint16_t) ((now_seconds() ^ (uint64_t) getpid()) & 0xffffu); + const uint8_t qname[] = { + 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 3, 'c', 'o', 'm', + 0 + }; + size_t pos = 12; + if (out_len < pos + sizeof(qname) + 4) { + return 0; + } + memset(out, 0, out_len); + out[0] = (uint8_t) ((id >> 8) & 0xffu); + out[1] = (uint8_t) (id & 0xffu); + out[2] = 0x01; + out[5] = 0x01; + memcpy(out + pos, qname, sizeof(qname)); + pos += sizeof(qname); + out[pos++] = 0x00; + out[pos++] = 0x01; + out[pos++] = 0x00; + out[pos++] = 0x01; + return pos; +} + +static int response_rcode(const uint8_t *response, size_t response_len) { + if (response_len < 4) { + return -1; + } + return response[3] & 0x0f; +} + +static void write_health_response(int client) { + uint8_t query[MAX_PACKET]; + uint8_t response[MAX_PACKET]; + struct timeval start; + struct timeval end; + size_t query_len; + ssize_t response_len; + int latency_ms; + int upstream_index = -1; + int rcode; + + query_len = build_health_query(query, sizeof(query)); + gettimeofday(&start, NULL); + response_len = query_len == 0 + ? -1 + : forward_udp_probe(&g_cfg, query, query_len, response, sizeof(response), &upstream_index); + gettimeofday(&end, NULL); + latency_ms = elapsed_ms(&start, &end); + rcode = response_len > 0 ? response_rcode(response, (size_t) response_len) : -1; + + write_control_response(client, + "health=1\nrunning=1\npid=%ld\nuptime=%llu\nlisten_port=%d\n" + "generation=%llu\nupstreams=%d\nupstream_probe=%s\n" + "upstream_probe_ms=%d\nupstream_probe_index=%d\nupstream_probe_rcode=%d\n" + "queries=%llu\nblocked=%llu\nallowed=%llu\ncache_entries=%d\n" + "rules_total=%d\n", + (long) getpid(), + (unsigned long long) (now_seconds() - g_stats.start_time), + g_cfg.listen_port, + (unsigned long long) g_cfg.generation, + g_cfg.upstream_count, + response_len > 0 ? "ok" : "fail", + latency_ms, + upstream_index, + rcode, + (unsigned long long) g_stats.queries, + (unsigned long long) g_stats.blocked, + (unsigned long long) g_stats.allowed, + cache_entry_count(), + g_cfg.exact_allow_count + g_cfg.suffix_allow_count + + g_cfg.exact_block_count + g_cfg.suffix_block_count + + g_cfg.regex_allow_count + g_cfg.regex_block_count + + g_cfg.temp_allow_count + g_cfg.temp_block_count); +} + static void handle_control(int fd) { int client = accept(fd, NULL, NULL); char cmd[128]; @@ -1295,6 +1404,8 @@ static void handle_control(int fd) { g_cfg.regex_block_count, g_cfg.temp_allow_count, g_cfg.temp_block_count); + } else if (strcmp(cmd, "health") == 0) { + write_health_response(client); } else if (strcmp(cmd, "reload") == 0) { if (reload_config()) { write_control_response(client, "ok reload generation=%llu\n", (unsigned long long) g_cfg.generation); From b94537bd5a7348b4f2cce661312e4d0f3a6a225b Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 14:48:55 -0700 Subject: [PATCH 011/108] Add scheduled DNS blocklist updates --- app/src/main/AndroidManifest.xml | 3 + .../broadcast/DnsBlocklistUpdateReceiver.java | 118 ++++++++++++++++++ .../ufirewall/broadcast/OnBootReceiver.java | 1 + .../ufirewall/dns/DnsHijackManager.java | 3 + .../preferences/RulesPreferenceFragment.java | 30 ++++- .../java/dev/ukanth/ufirewall/util/G.java | 10 ++ app/src/main/res/values/strings.xml | 4 + app/src/main/res/xml/rules_preferences.xml | 14 +++ 8 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/dev/ukanth/ufirewall/broadcast/DnsBlocklistUpdateReceiver.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c4e9665a3..7526ed642 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -227,6 +227,9 @@ + diff --git a/app/src/main/java/dev/ukanth/ufirewall/broadcast/DnsBlocklistUpdateReceiver.java b/app/src/main/java/dev/ukanth/ufirewall/broadcast/DnsBlocklistUpdateReceiver.java new file mode 100644 index 000000000..a71b3b911 --- /dev/null +++ b/app/src/main/java/dev/ukanth/ufirewall/broadcast/DnsBlocklistUpdateReceiver.java @@ -0,0 +1,118 @@ +package dev.ukanth.ufirewall.broadcast; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.SystemClock; +import android.util.Log; + +import dev.ukanth.ufirewall.Api; +import dev.ukanth.ufirewall.dns.DnsBlocklistManager; +import dev.ukanth.ufirewall.dns.DnsHijackManager; +import dev.ukanth.ufirewall.util.ApplicationErrorLog; +import dev.ukanth.ufirewall.util.G; + +public class DnsBlocklistUpdateReceiver extends BroadcastReceiver { + + private static final String TAG = "AFWallDnsBlocklistAlarm"; + private static final String ACTION_UPDATE = "dev.ukanth.ufirewall.action.DNS_BLOCKLIST_UPDATE"; + + @Override + public void onReceive(Context context, Intent intent) { + if (context == null || intent == null || !ACTION_UPDATE.equals(intent.getAction())) { + return; + } + + PendingResult pendingResult = goAsync(); + Context appContext = context.getApplicationContext(); + new Thread(() -> { + try { + runScheduledUpdate(appContext); + } finally { + pendingResult.finish(); + } + }, "AFWallDnsBlocklistUpdate").start(); + } + + public static void scheduleOrCancel(Context context) { + if (context == null) { + return; + } + if (!shouldSchedule()) { + cancel(context); + return; + } + + long interval = G.dnsHijackBlocklistUpdateIntervalHours() * 60L * 60L * 1000L; + long firstRun = SystemClock.elapsedRealtime() + interval; + AlarmManager alarmManager = (AlarmManager) context.getApplicationContext() + .getSystemService(Context.ALARM_SERVICE); + if (alarmManager == null) { + ApplicationErrorLog.add(context, "DNS blocklist scheduled updates could not be scheduled: AlarmManager unavailable"); + return; + } + + alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstRun, interval, + pendingIntent(context)); + ApplicationErrorLog.add(context, "DNS blocklist scheduled updates enabled every " + + G.dnsHijackBlocklistUpdateIntervalHours() + " hours"); + } + + public static void cancel(Context context) { + if (context == null) { + return; + } + AlarmManager alarmManager = (AlarmManager) context.getApplicationContext() + .getSystemService(Context.ALARM_SERVICE); + if (alarmManager != null) { + alarmManager.cancel(pendingIntent(context)); + } + } + + private static void runScheduledUpdate(Context context) { + if (!shouldSchedule()) { + cancel(context); + return; + } + + ApplicationErrorLog.add(context, "Scheduled DNS blocklist update started"); + try { + DnsBlocklistManager.Result result = DnsBlocklistManager.updateFromConfiguredUrls(context); + if (result.failed) { + ApplicationErrorLog.add(context, "Scheduled DNS blocklist update failed: " + + result.message); + return; + } + + Api.setRulesUpToDate(false); + if (G.enableDnsHijack()) { + DnsHijackManager.requestReload(context); + } + ApplicationErrorLog.add(context, "Scheduled DNS blocklist update completed: " + + result.message); + } catch (RuntimeException e) { + Log.e(TAG, "Scheduled DNS blocklist update crashed", e); + ApplicationErrorLog.add(context, "Scheduled DNS blocklist update crashed: " + + e.getMessage()); + } + } + + private static boolean shouldSchedule() { + return G.enableDnsHijack() + && G.dnsHijackScheduledBlocklistUpdates() + && !G.dnsHijackBlocklistUrls().trim().isEmpty(); + } + + private static PendingIntent pendingIntent(Context context) { + Intent intent = new Intent(context.getApplicationContext(), DnsBlocklistUpdateReceiver.class); + intent.setAction(ACTION_UPDATE); + int flags = PendingIntent.FLAG_UPDATE_CURRENT; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + flags |= PendingIntent.FLAG_IMMUTABLE; + } + return PendingIntent.getBroadcast(context.getApplicationContext(), 0, intent, flags); + } +} diff --git a/app/src/main/java/dev/ukanth/ufirewall/broadcast/OnBootReceiver.java b/app/src/main/java/dev/ukanth/ufirewall/broadcast/OnBootReceiver.java index ec745f8b4..2c5cc4a52 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/broadcast/OnBootReceiver.java +++ b/app/src/main/java/dev/ukanth/ufirewall/broadcast/OnBootReceiver.java @@ -48,6 +48,7 @@ public void onReceive(Context context, Intent intent) { // Use BootRuleManager for robust rule application BootRuleManager.initializeBootRuleApplication(context); + DnsBlocklistUpdateReceiver.scheduleOrCancel(context); //register private DNS change listener diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java index f8bbac42e..47ecc3c48 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java @@ -161,6 +161,9 @@ public static String collectLocalDiagnostics(Context context) { out.append("fail_open=").append(G.dnsHijackFailOpen()).append('\n'); out.append("strict_mode=").append(G.dnsHijackStrictMode()).append('\n'); out.append("timeout_ms=").append(G.dnsHijackTimeoutMs()).append('\n'); + out.append("scheduled_blocklist_updates=").append(G.dnsHijackScheduledBlocklistUpdates()).append('\n'); + out.append("blocklist_update_interval_hours=") + .append(G.dnsHijackBlocklistUpdateIntervalHours()).append('\n'); out.append("temporary_allow_entries=").append(countLines(G.dnsHijackTempAllow())).append('\n'); out.append("temporary_block_entries=").append(countLines(G.dnsHijackTempBlock())).append('\n'); out.append("\n[blocklists]\n"); diff --git a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java index 6df5ec58a..74a1d83d9 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java +++ b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java @@ -23,6 +23,7 @@ import dev.ukanth.ufirewall.Api; import dev.ukanth.ufirewall.R; +import dev.ukanth.ufirewall.broadcast.DnsBlocklistUpdateReceiver; import dev.ukanth.ufirewall.dns.DnsBlocklistManager; import dev.ukanth.ufirewall.dns.DnsHijackManager; import dev.ukanth.ufirewall.service.RootCommand; @@ -158,6 +159,7 @@ public void cbFunc(RootCommand state) { } getPreferenceScreen().removeAll(); addPreferencesFromResource(R.xml.rules_preferences); + wireDnsBlocklistActions(); } } })); @@ -215,6 +217,7 @@ private void handleBlocklistResult(DnsBlocklistManager.Result result) { if (G.enableDnsHijack()) { DnsHijackManager.requestReload(ctx); } + DnsBlocklistUpdateReceiver.scheduleOrCancel(ctx); Api.toast(ctx, getString(R.string.dns_hijack_blocklist_active)); } else { Api.toast(ctx, getString(R.string.dns_hijack_blocklist_failed)); @@ -420,8 +423,10 @@ public void cbFunc(RootCommand state) { if (isDnsHijackPreference(key)) { Api.setRulesUpToDate(false); - if (!key.equals("enableDnsHijack") && !key.equals("dnsHijackPort") - && !key.equals("dnsHijackBootPersistence") && G.enableDnsHijack()) { + if (isDnsHijackBlocklistSchedulePreference(key)) { + DnsBlocklistUpdateReceiver.scheduleOrCancel(ctx); + } + if (shouldReloadDnsHijackPreference(key) && G.enableDnsHijack()) { DnsHijackManager.requestReload(ctx); } } @@ -442,6 +447,25 @@ private boolean isDnsHijackPreference(String key) { || key.equals("dnsHijackBlockSuffix") || key.equals("dnsHijackAllowRegex") || key.equals("dnsHijackBlockRegex") - || key.equals("dnsHijackBlocklistUrls")); + || key.equals("dnsHijackBlocklistUrls") + || key.equals("dnsHijackScheduledBlocklistUpdates") + || key.equals("dnsHijackBlocklistUpdateIntervalHours")); + } + + private boolean isDnsHijackBlocklistSchedulePreference(String key) { + return key != null && (key.equals("enableDnsHijack") + || key.equals("dnsHijackBlocklistUrls") + || key.equals("dnsHijackScheduledBlocklistUpdates") + || key.equals("dnsHijackBlocklistUpdateIntervalHours")); + } + + private boolean shouldReloadDnsHijackPreference(String key) { + return key != null + && !key.equals("enableDnsHijack") + && !key.equals("dnsHijackPort") + && !key.equals("dnsHijackBootPersistence") + && !key.equals("dnsHijackBlocklistUrls") + && !key.equals("dnsHijackScheduledBlocklistUpdates") + && !key.equals("dnsHijackBlocklistUpdateIntervalHours"); } } diff --git a/app/src/main/java/dev/ukanth/ufirewall/util/G.java b/app/src/main/java/dev/ukanth/ufirewall/util/G.java index a38215c74..0ffb4698d 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/util/G.java +++ b/app/src/main/java/dev/ukanth/ufirewall/util/G.java @@ -187,6 +187,8 @@ public static Context getContext() { private static final String DNS_HIJACK_TEMP_ALLOW = "dnsHijackTempAllow"; private static final String DNS_HIJACK_TEMP_BLOCK = "dnsHijackTempBlock"; private static final String DNS_HIJACK_BLOCKLIST_URLS = "dnsHijackBlocklistUrls"; + private static final String DNS_HIJACK_SCHEDULED_BLOCKLIST_UPDATES = "dnsHijackScheduledBlocklistUpdates"; + private static final String DNS_HIJACK_BLOCKLIST_UPDATE_INTERVAL_HOURS = "dnsHijackBlocklistUpdateIntervalHours"; private static final String SHOW_ALL_APPS = "showAllApps"; @@ -346,6 +348,14 @@ public static String dnsHijackBlocklistUrls() { return gPrefs.getString(DNS_HIJACK_BLOCKLIST_URLS, ""); } + public static boolean dnsHijackScheduledBlocklistUpdates() { + return gPrefs.getBoolean(DNS_HIJACK_SCHEDULED_BLOCKLIST_UPDATES, false); + } + + public static int dnsHijackBlocklistUpdateIntervalHours() { + return readIntPreference(DNS_HIJACK_BLOCKLIST_UPDATE_INTERVAL_HOURS, 24, 1, 720); + } + public static boolean appendDnsHijackAllowExact(String domain) { return appendLinePreference(DNS_HIJACK_ALLOW_EXACT, domain); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 78044454f..cd5cd93b6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -327,6 +327,10 @@ Regular expressions that block matching queries. Blocklist URLs One remote hosts, domain, Pi-hole, or AdBlock-style list URL per line. + Scheduled blocklist updates + Periodically download configured DNS blocklist URLs and reload the daemon after a successful compile. + Blocklist update interval + How often scheduled DNS blocklist updates should run, in hours. Import DNS blocklist file Use the system picker to import a hosts, domain, Pi-hole, or AdBlock-style list. Update DNS blocklists diff --git a/app/src/main/res/xml/rules_preferences.xml b/app/src/main/res/xml/rules_preferences.xml index e7ab1743c..60748cca2 100644 --- a/app/src/main/res/xml/rules_preferences.xml +++ b/app/src/main/res/xml/rules_preferences.xml @@ -161,6 +161,20 @@ android:summary="@string/dns_hijack_blocklist_urls_summary" android:title="@string/dns_hijack_blocklist_urls_title" /> + + + + Date: Fri, 26 Jun 2026 14:56:14 -0700 Subject: [PATCH 012/108] Add profile DNS policy overrides --- .../ufirewall/dns/DnsBlocklistManager.java | 27 ++- .../ufirewall/dns/DnsHijackManager.java | 6 + .../preferences/RulesPreferenceFragment.java | 50 ++++- .../java/dev/ukanth/ufirewall/util/G.java | 192 +++++++++++++++--- app/src/main/res/values/strings.xml | 9 + app/src/main/res/xml/rules_preferences.xml | 19 ++ 6 files changed, 267 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsBlocklistManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsBlocklistManager.java index 13f830d41..bfa5eba5c 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsBlocklistManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsBlocklistManager.java @@ -141,6 +141,30 @@ public static String getSummary(Context context) { } } + public static boolean copyGlobalBlocklistToActiveProfile(Context context) { + File sourceDir = context.getApplicationContext().getDir(DIR, Context.MODE_PRIVATE); + File targetDir = blocklistDir(context); + if (sourceDir.equals(targetDir)) { + return true; + } + if (!targetDir.exists() && !targetDir.mkdirs()) { + ApplicationErrorLog.add(context, "Unable to create active profile DNS blocklist directory"); + return false; + } + try { + copyIfExists(new File(sourceDir, EXACT_FILE), new File(targetDir, EXACT_FILE)); + copyIfExists(new File(sourceDir, SUFFIX_FILE), new File(targetDir, SUFFIX_FILE)); + copyIfExists(new File(sourceDir, EXACT_BACKUP), new File(targetDir, EXACT_BACKUP)); + copyIfExists(new File(sourceDir, SUFFIX_BACKUP), new File(targetDir, SUFFIX_BACKUP)); + copyIfExists(new File(sourceDir, META_FILE), new File(targetDir, META_FILE)); + return true; + } catch (IOException e) { + Log.e(TAG, "DNS profile blocklist copy failed", e); + ApplicationErrorLog.add(context, "DNS profile blocklist copy failed: " + e.getMessage()); + return false; + } + } + static File exactBlockFile(Context context) { return new File(blocklistDir(context), EXACT_FILE); } @@ -353,7 +377,8 @@ private static void copyIfExists(File source, File target) throws IOException { } private static File blocklistDir(Context context) { - return context.getApplicationContext().getDir(DIR, Context.MODE_PRIVATE); + return context.getApplicationContext() + .getDir(G.dnsHijackBlocklistDirectoryName(DIR), Context.MODE_PRIVATE); } public static final class Result { diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java index 47ecc3c48..db39a84d3 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java @@ -156,6 +156,12 @@ public static String collectLocalDiagnostics(Context context) { File bootLog = new File(dir, BOOT_LOG); out.append("enabled_pref=").append(G.enableDnsHijack()).append('\n'); + out.append("active_profile=").append(G.activeDnsHijackPolicyProfile()).append('\n'); + out.append("profile_dns_overrides_enabled=").append(G.dnsHijackUseProfilePolicy()).append('\n'); + out.append("active_profile_dns_override_saved=") + .append(G.activeDnsHijackProfilePolicySaved()).append('\n'); + out.append("blocklist_storage=").append(G.dnsHijackBlocklistDirectoryName("dnsd_blocklists")) + .append('\n'); out.append("boot_persistence_pref=").append(G.dnsHijackBootPersistence()).append('\n'); out.append("port=").append(G.dnsHijackPort(DEFAULT_PORT)).append('\n'); out.append("fail_open=").append(G.dnsHijackFailOpen()).append('\n'); diff --git a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java index 74a1d83d9..699f183c1 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java +++ b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java @@ -84,6 +84,22 @@ private void wireDnsBlocklistActions() { return true; }); } + + Preference saveProfilePolicy = findPreference("dnsHijackSaveProfilePolicy"); + if (saveProfilePolicy != null) { + saveProfilePolicy.setOnPreferenceClickListener(preference -> { + saveDnsProfilePolicy(); + return true; + }); + } + + Preference clearProfilePolicy = findPreference("dnsHijackClearProfilePolicy"); + if (clearProfilePolicy != null) { + clearProfilePolicy.setOnPreferenceClickListener(preference -> { + clearDnsProfilePolicy(); + return true; + }); + } } private void updateRuleStatus() { @@ -201,6 +217,34 @@ private void runDnsBlocklistRollback() { runBlocklistTask(() -> DnsBlocklistManager.restorePrevious(ctx)); } + private void saveDnsProfilePolicy() { + boolean saved = G.saveActiveDnsHijackProfilePolicy() + && DnsBlocklistManager.copyGlobalBlocklistToActiveProfile(ctx); + handleDnsProfilePolicyResult(saved, + R.string.dns_hijack_profile_policy_saved); + } + + private void clearDnsProfilePolicy() { + handleDnsProfilePolicyResult(G.clearActiveDnsHijackProfilePolicy(), + R.string.dns_hijack_profile_policy_cleared); + } + + private void handleDnsProfilePolicyResult(boolean success, int successMessage) { + if (ctx == null) { + return; + } + if (success) { + Api.setRulesUpToDate(false); + DnsBlocklistUpdateReceiver.scheduleOrCancel(ctx); + if (G.enableDnsHijack()) { + DnsHijackManager.requestReload(ctx); + } + Api.toast(ctx, getString(successMessage)); + } else { + Api.toast(ctx, getString(R.string.dns_hijack_profile_policy_failed)); + } + } + private void runBlocklistTask(BlocklistTask task) { new Thread(() -> { DnsBlocklistManager.Result result = task.run(); @@ -449,14 +493,16 @@ private boolean isDnsHijackPreference(String key) { || key.equals("dnsHijackBlockRegex") || key.equals("dnsHijackBlocklistUrls") || key.equals("dnsHijackScheduledBlocklistUpdates") - || key.equals("dnsHijackBlocklistUpdateIntervalHours")); + || key.equals("dnsHijackBlocklistUpdateIntervalHours") + || key.equals("dnsHijackUseProfilePolicy")); } private boolean isDnsHijackBlocklistSchedulePreference(String key) { return key != null && (key.equals("enableDnsHijack") || key.equals("dnsHijackBlocklistUrls") || key.equals("dnsHijackScheduledBlocklistUpdates") - || key.equals("dnsHijackBlocklistUpdateIntervalHours")); + || key.equals("dnsHijackBlocklistUpdateIntervalHours") + || key.equals("dnsHijackUseProfilePolicy")); } private boolean shouldReloadDnsHijackPreference(String key) { diff --git a/app/src/main/java/dev/ukanth/ufirewall/util/G.java b/app/src/main/java/dev/ukanth/ufirewall/util/G.java index 0ffb4698d..a4a1e91a4 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/util/G.java +++ b/app/src/main/java/dev/ukanth/ufirewall/util/G.java @@ -189,6 +189,25 @@ public static Context getContext() { private static final String DNS_HIJACK_BLOCKLIST_URLS = "dnsHijackBlocklistUrls"; private static final String DNS_HIJACK_SCHEDULED_BLOCKLIST_UPDATES = "dnsHijackScheduledBlocklistUpdates"; private static final String DNS_HIJACK_BLOCKLIST_UPDATE_INTERVAL_HOURS = "dnsHijackBlocklistUpdateIntervalHours"; + private static final String DNS_HIJACK_USE_PROFILE_POLICY = "dnsHijackUseProfilePolicy"; + private static final String DNS_HIJACK_PROFILE_POLICY_SAVED = "dnsHijackProfilePolicySaved"; + private static final String[] DNS_HIJACK_PROFILE_POLICY_KEYS = new String[] { + DNS_HIJACK_UPSTREAMS, + DNS_HIJACK_FAIL_OPEN, + DNS_HIJACK_STRICT_MODE, + DNS_HIJACK_TIMEOUT_MS, + DNS_HIJACK_ALLOW_EXACT, + DNS_HIJACK_ALLOW_SUFFIX, + DNS_HIJACK_BLOCK_EXACT, + DNS_HIJACK_BLOCK_SUFFIX, + DNS_HIJACK_ALLOW_REGEX, + DNS_HIJACK_BLOCK_REGEX, + DNS_HIJACK_TEMP_ALLOW, + DNS_HIJACK_TEMP_BLOCK, + DNS_HIJACK_BLOCKLIST_URLS, + DNS_HIJACK_SCHEDULED_BLOCKLIST_UPDATES, + DNS_HIJACK_BLOCKLIST_UPDATE_INTERVAL_HOURS + }; private static final String SHOW_ALL_APPS = "showAllApps"; @@ -288,15 +307,15 @@ public static int dnsHijackPort(int fallback) { } public static String dnsHijackUpstreams() { - return gPrefs.getString(DNS_HIJACK_UPSTREAMS, "1.1.1.1:53\n8.8.8.8:53"); + return dnsPolicyPrefs().getString(DNS_HIJACK_UPSTREAMS, "1.1.1.1:53\n8.8.8.8:53"); } public static boolean dnsHijackFailOpen() { - return gPrefs.getBoolean(DNS_HIJACK_FAIL_OPEN, true); + return dnsPolicyPrefs().getBoolean(DNS_HIJACK_FAIL_OPEN, true); } public static boolean dnsHijackStrictMode() { - return gPrefs.getBoolean(DNS_HIJACK_STRICT_MODE, false); + return dnsPolicyPrefs().getBoolean(DNS_HIJACK_STRICT_MODE, false); } public static boolean dnsHijackBootPersistence() { @@ -309,83 +328,185 @@ public static boolean dnsHijackBootPersistence(boolean val) { } public static int dnsHijackTimeoutMs() { - return readIntPreference(DNS_HIJACK_TIMEOUT_MS, 2500, 250, 10000); + return readIntPreference(dnsPolicyPrefs(), DNS_HIJACK_TIMEOUT_MS, 2500, 250, 10000); } public static String dnsHijackAllowExact() { - return gPrefs.getString(DNS_HIJACK_ALLOW_EXACT, ""); + return dnsPolicyPrefs().getString(DNS_HIJACK_ALLOW_EXACT, ""); } public static String dnsHijackAllowSuffix() { - return gPrefs.getString(DNS_HIJACK_ALLOW_SUFFIX, ""); + return dnsPolicyPrefs().getString(DNS_HIJACK_ALLOW_SUFFIX, ""); } public static String dnsHijackBlockExact() { - return gPrefs.getString(DNS_HIJACK_BLOCK_EXACT, ""); + return dnsPolicyPrefs().getString(DNS_HIJACK_BLOCK_EXACT, ""); } public static String dnsHijackBlockSuffix() { - return gPrefs.getString(DNS_HIJACK_BLOCK_SUFFIX, ""); + return dnsPolicyPrefs().getString(DNS_HIJACK_BLOCK_SUFFIX, ""); } public static String dnsHijackAllowRegex() { - return gPrefs.getString(DNS_HIJACK_ALLOW_REGEX, ""); + return dnsPolicyPrefs().getString(DNS_HIJACK_ALLOW_REGEX, ""); } public static String dnsHijackBlockRegex() { - return gPrefs.getString(DNS_HIJACK_BLOCK_REGEX, ""); + return dnsPolicyPrefs().getString(DNS_HIJACK_BLOCK_REGEX, ""); } public static String dnsHijackTempAllow() { - return gPrefs.getString(DNS_HIJACK_TEMP_ALLOW, ""); + return dnsPolicyPrefs().getString(DNS_HIJACK_TEMP_ALLOW, ""); } public static String dnsHijackTempBlock() { - return gPrefs.getString(DNS_HIJACK_TEMP_BLOCK, ""); + return dnsPolicyPrefs().getString(DNS_HIJACK_TEMP_BLOCK, ""); } public static String dnsHijackBlocklistUrls() { - return gPrefs.getString(DNS_HIJACK_BLOCKLIST_URLS, ""); + return dnsPolicyPrefs().getString(DNS_HIJACK_BLOCKLIST_URLS, ""); } public static boolean dnsHijackScheduledBlocklistUpdates() { - return gPrefs.getBoolean(DNS_HIJACK_SCHEDULED_BLOCKLIST_UPDATES, false); + return dnsPolicyPrefs().getBoolean(DNS_HIJACK_SCHEDULED_BLOCKLIST_UPDATES, false); } public static int dnsHijackBlocklistUpdateIntervalHours() { - return readIntPreference(DNS_HIJACK_BLOCKLIST_UPDATE_INTERVAL_HOURS, 24, 1, 720); + return readIntPreference(dnsPolicyPrefs(), DNS_HIJACK_BLOCKLIST_UPDATE_INTERVAL_HOURS, 24, 1, 720); + } + + public static boolean dnsHijackUseProfilePolicy() { + return gPrefs.getBoolean(DNS_HIJACK_USE_PROFILE_POLICY, false); + } + + public static boolean activeDnsHijackProfilePolicySaved() { + SharedPreferences profilePrefs = activeDnsProfilePrefs(); + return profilePrefs != null + && profilePrefs.getBoolean(DNS_HIJACK_PROFILE_POLICY_SAVED, false); + } + + public static String activeDnsHijackPolicyProfile() { + if (!enableMultiProfile()) { + return Api.DEFAULT_PREFS_NAME; + } + return storedProfile(); + } + + public static boolean saveActiveDnsHijackProfilePolicy() { + SharedPreferences profilePrefs = activeDnsProfilePrefs(); + if (profilePrefs == null) { + return false; + } + SharedPreferences.Editor editor = profilePrefs.edit(); + for (String key : DNS_HIJACK_PROFILE_POLICY_KEYS) { + copyPreferenceValue(gPrefs, editor, key); + } + editor.putBoolean(DNS_HIJACK_PROFILE_POLICY_SAVED, true); + return editor.commit(); + } + + public static boolean clearActiveDnsHijackProfilePolicy() { + SharedPreferences profilePrefs = activeDnsProfilePrefs(); + if (profilePrefs == null) { + return false; + } + SharedPreferences.Editor editor = profilePrefs.edit(); + for (String key : DNS_HIJACK_PROFILE_POLICY_KEYS) { + editor.remove(key); + } + editor.remove(DNS_HIJACK_PROFILE_POLICY_SAVED); + return editor.commit(); + } + + public static String dnsHijackBlocklistDirectoryName(String defaultName) { + if (!usingActiveDnsProfilePolicy()) { + return defaultName; + } + String profile = activeDnsHijackPolicyProfile(); + String safeProfile = profile == null ? Api.DEFAULT_PREFS_NAME : profile; + safeProfile = safeProfile.replaceAll("[^A-Za-z0-9_.-]", "_"); + if (safeProfile.length() == 0) { + safeProfile = Api.DEFAULT_PREFS_NAME; + } + return defaultName + "_" + safeProfile; } public static boolean appendDnsHijackAllowExact(String domain) { - return appendLinePreference(DNS_HIJACK_ALLOW_EXACT, domain); + return appendLinePreference(dnsWritablePolicyPrefs(), DNS_HIJACK_ALLOW_EXACT, domain); } public static boolean appendDnsHijackAllowSuffix(String domain) { - return appendLinePreference(DNS_HIJACK_ALLOW_SUFFIX, domain); + return appendLinePreference(dnsWritablePolicyPrefs(), DNS_HIJACK_ALLOW_SUFFIX, domain); } public static boolean appendDnsHijackBlockExact(String domain) { - return appendLinePreference(DNS_HIJACK_BLOCK_EXACT, domain); + return appendLinePreference(dnsWritablePolicyPrefs(), DNS_HIJACK_BLOCK_EXACT, domain); } public static boolean appendDnsHijackBlockSuffix(String domain) { - return appendLinePreference(DNS_HIJACK_BLOCK_SUFFIX, domain); + return appendLinePreference(dnsWritablePolicyPrefs(), DNS_HIJACK_BLOCK_SUFFIX, domain); } public static boolean appendDnsHijackTempAllow(String domain, long expiresAtSeconds) { - return appendTemporaryLinePreference(DNS_HIJACK_TEMP_ALLOW, domain, expiresAtSeconds); + return appendTemporaryLinePreference(dnsWritablePolicyPrefs(), DNS_HIJACK_TEMP_ALLOW, domain, expiresAtSeconds); } public static boolean appendDnsHijackTempBlock(String domain, long expiresAtSeconds) { - return appendTemporaryLinePreference(DNS_HIJACK_TEMP_BLOCK, domain, expiresAtSeconds); + return appendTemporaryLinePreference(dnsWritablePolicyPrefs(), DNS_HIJACK_TEMP_BLOCK, domain, expiresAtSeconds); } public static void pruneExpiredDnsHijackTemporaryRules() { - pruneExpiredTemporaryPreference(DNS_HIJACK_TEMP_ALLOW); - pruneExpiredTemporaryPreference(DNS_HIJACK_TEMP_BLOCK); + SharedPreferences prefs = dnsWritablePolicyPrefs(); + pruneExpiredTemporaryPreference(prefs, DNS_HIJACK_TEMP_ALLOW); + pruneExpiredTemporaryPreference(prefs, DNS_HIJACK_TEMP_BLOCK); + } + + private static SharedPreferences dnsPolicyPrefs() { + return usingActiveDnsProfilePolicy() ? activeDnsProfilePrefs() : gPrefs; + } + + private static SharedPreferences dnsWritablePolicyPrefs() { + return usingActiveDnsProfilePolicy() ? activeDnsProfilePrefs() : gPrefs; + } + + private static boolean usingActiveDnsProfilePolicy() { + return dnsHijackUseProfilePolicy() && activeDnsHijackProfilePolicySaved(); } - private static boolean appendLinePreference(String key, String rawValue) { + private static SharedPreferences activeDnsProfilePrefs() { + if (ctx == null) { + return pPrefs; + } + if (pPrefs == null) { + reloadPrefs(); + } + return pPrefs; + } + + @SuppressWarnings("unchecked") + private static void copyPreferenceValue(SharedPreferences source, SharedPreferences.Editor target, + String key) { + if (source == null || !source.contains(key)) { + target.remove(key); + return; + } + Object value = source.getAll().get(key); + if (value instanceof Boolean) { + target.putBoolean(key, (Boolean) value); + } else if (value instanceof Integer) { + target.putInt(key, (Integer) value); + } else if (value instanceof Long) { + target.putLong(key, (Long) value); + } else if (value instanceof Float) { + target.putFloat(key, (Float) value); + } else if (value instanceof Set) { + target.putStringSet(key, (Set) value); + } else if (value != null) { + target.putString(key, String.valueOf(value)); + } + } + + private static boolean appendLinePreference(SharedPreferences prefs, String key, String rawValue) { if (rawValue == null) { return false; } @@ -394,7 +515,7 @@ private static boolean appendLinePreference(String key, String rawValue) { return false; } LinkedHashSet values = new LinkedHashSet<>(); - String existing = gPrefs.getString(key, ""); + String existing = prefs.getString(key, ""); if (existing != null) { String[] lines = existing.split("[\\r\\n,]+"); for (String line : lines) { @@ -406,12 +527,13 @@ private static boolean appendLinePreference(String key, String rawValue) { } boolean added = values.add(value); if (added) { - gPrefs.edit().putString(key, android.text.TextUtils.join("\n", values)).commit(); + prefs.edit().putString(key, android.text.TextUtils.join("\n", values)).commit(); } return added; } - private static boolean appendTemporaryLinePreference(String key, String rawValue, long expiresAtSeconds) { + private static boolean appendTemporaryLinePreference(SharedPreferences prefs, String key, + String rawValue, long expiresAtSeconds) { if (rawValue == null || expiresAtSeconds <= (System.currentTimeMillis() / 1000L)) { return false; } @@ -421,7 +543,7 @@ private static boolean appendTemporaryLinePreference(String key, String rawValue } LinkedHashSet values = new LinkedHashSet<>(); String prefix = value + "|"; - String existing = gPrefs.getString(key, ""); + String existing = prefs.getString(key, ""); boolean changed = false; if (existing != null) { String[] lines = existing.split("[\\r\\n]+"); @@ -442,13 +564,13 @@ private static boolean appendTemporaryLinePreference(String key, String rawValue String entry = value + "|" + expiresAtSeconds; boolean added = values.add(entry); if (added || changed) { - gPrefs.edit().putString(key, android.text.TextUtils.join("\n", values)).commit(); + prefs.edit().putString(key, android.text.TextUtils.join("\n", values)).commit(); } return added || changed; } - private static void pruneExpiredTemporaryPreference(String key) { - String existing = gPrefs.getString(key, ""); + private static void pruneExpiredTemporaryPreference(SharedPreferences prefs, String key) { + String existing = prefs.getString(key, ""); if (existing == null || existing.trim().isEmpty()) { return; } @@ -465,7 +587,7 @@ private static void pruneExpiredTemporaryPreference(String key) { values.add(value); } if (changed) { - gPrefs.edit().putString(key, android.text.TextUtils.join("\n", values)).commit(); + prefs.edit().putString(key, android.text.TextUtils.join("\n", values)).commit(); } } @@ -482,7 +604,11 @@ private static boolean isExpiredTemporaryLine(String value, long nowSeconds) { } private static int readIntPreference(String key, int fallback, int min, int max) { - String value = gPrefs.getString(key, String.valueOf(fallback)); + return readIntPreference(gPrefs, key, fallback, min, max); + } + + private static int readIntPreference(SharedPreferences prefs, String key, int fallback, int min, int max) { + String value = prefs.getString(key, String.valueOf(fallback)); try { int parsed = Integer.parseInt(value); if (parsed < min || parsed > max) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cd5cd93b6..a51dab1a8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -313,6 +313,15 @@ Install a root boot script that restarts the DNS daemon and restores DNS redirect rules before opening the app. Upstream timeout DNS upstream timeout in milliseconds. + Use active profile DNS policy + When enabled, saved DNS settings and compiled blocklists follow the active firewall profile. + Save DNS policy to active profile + Copy the current DNS upstreams, rules, blocklist URLs, and update schedule into the active profile. + Clear active profile DNS policy + Remove the active profile DNS override and fall back to the global DNS settings. + DNS policy saved for active profile. + Active profile DNS policy cleared. + Unable to update active profile DNS policy. Exact allow domains Domains that should always be allowed. One entry per line. Wildcard allow suffixes diff --git a/app/src/main/res/xml/rules_preferences.xml b/app/src/main/res/xml/rules_preferences.xml index 60748cca2..925365192 100644 --- a/app/src/main/res/xml/rules_preferences.xml +++ b/app/src/main/res/xml/rules_preferences.xml @@ -119,6 +119,25 @@ android:summary="@string/dns_hijack_timeout_summary" android:title="@string/dns_hijack_timeout_title" /> + + + + + + Date: Fri, 26 Jun 2026 15:01:15 -0700 Subject: [PATCH 013/108] Add DNS upstream benchmarking --- .../main/assets/dnsd/arm64-v8a/afwall_dnsd | Bin 25120 -> 25792 bytes .../main/assets/dnsd/armeabi-v7a/afwall_dnsd | Bin 20408 -> 20888 bytes app/src/main/assets/dnsd/x86/afwall_dnsd | Bin 25580 -> 26316 bytes app/src/main/assets/dnsd/x86_64/afwall_dnsd | Bin 26480 -> 27200 bytes .../ufirewall/dns/DnsHijackManager.java | 149 ++++++++++++++++++ .../preferences/RulesPreferenceFragment.java | 28 ++++ app/src/main/res/values/strings.xml | 3 + app/src/main/res/xml/rules_preferences.xml | 6 + dnsdaemon/jni/afwall_dnsd.c | 66 ++++++++ 9 files changed, 252 insertions(+) diff --git a/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd b/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd index 895daeaa563eccbf8a3196cc4a3c50295087981e..5c10e4b2a3c7159085dbf0353f68ebb8bf9f7c3f 100755 GIT binary patch delta 8225 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 N*3h&$17it>{|Ata2hjik delta 7591 zcmc&(dw5e-w%_|CZBJSXX`41}3eBsJB&98nzJjzQrG>VDg|r|PFD(U~0;5oTA>t%d z9Sh8($5pR$b(GQ>9SG{J7Uwn&YN_JIVI1oyKJRE+VJ3h&l#ka@Fn8@d=pN_Zzdheq z*8ct0+Iz3F_u6Z(Lx$d>y>HO&^yGk!gdRs&5dUh)_KbUEMHogUQHL=_5sQCOe&p7O zT|_z*VLU?>mf!EEZVvP6?f)#NM$Bt78U$=Y15HZ)*EwJ-&8_=aI^6gBQ!`iDv-H%R z>y;?Qv=E$-1EaKoYTn*3K0dYZ)4Ivuz5JVFKidBOwUIZ+AxW4z(5mPX-L386P6{>x zKGD@`|9|)`-{U{Z4EIZqyl-@z2P6Eph&{#eQ^Ka9e}5I`-9$h|^i7ziH`0OeY^9>l zevXgqK}gll@sW23@q-*66CDKQ5XZ+7_k`vcr-+-N$q2`b9RCr=M}vW>{Tv_9*#|g2 zA<@iV(hWK`l4M1DSA2H%<=mV4g>L80ASOacc~ibJpWd zEJmrpmEVD~6<7K&%3@sE3n+h$D>)Z)(0*K?9Vq+D2|0#xr5)Wx8JI&zIlASTOURul z{|DuMlWeQ7V+1;P#9K!b&szKBH2|&VfrA^@6_`s&s|I$`aVB zs}%N^!i%~&!W(7qwQiO$y&O!LE#)(-Wot>bY@yEz;LFU9>ANVXr^4yXsj;)FWwE3h5~i+7ym{n?6RhjN zxS;NWj;VPIFC>y4k&tf1nV-Arp6qmy4UTL0R^7&9X;Nzyk;e2Mm)Y67HCyR%Z4ijB zHI`gEi+wD_<9c0~^lr%ZSv7ne`TemTmmeK*S5CIKKcevYkqank|7-E2gG`H& z_b5oy71T2?R=ggZaT#@&1*?RqSmRe{y==Y@6QOciuJCRm+&V4KO*hyB8dCg*g7gff zl2Tm%5z*LT7X?ymz&0_=ltNCN(@H})nS+u;7Zk*M1lz(62ZVH*Sjn%@c$uEbVU)~) z3&)7sPd%S|rf}bY)E;c6n zZbJT0BFxFk68aONIZG!TNQAqy3TN%Zjvfq8oY~fgZ4L1xv(9WFBM!t5@(a{Elu((K zX1b^#w%rK7h;yLxsWxW1&Y_a3P(Fx%4)jT#8O8PSE7EMk zi5^$*@A38q>VMjffpMKC@YjZJe`Tz_$#oe|nlER#eO6h*By*9o||RrtcIS za!B75b6uaq#=-GeKrkEB7k3-eQ$q%07%f%ADzSkw(U84Nm)0R4cwo&HJyo5hYe`cu z!65}-PXN7rn%jT_5Q9}ZQtENBiT4W{Th}+iveyL7Cd>l;`-gjUb@}za&joSQr^8*k zT`Nd&AQ(Jn&!gRTMS(;rhAJ3N&+)jvy-a-m)t(AsAFA*-dMc{X!BZH?ekJV=%qBk3 z<8j5N*T|l~d0eOUL?(`2$T!YXZi|(+!&;*j*YaMYzTn=Ct%C#)Ti|!(fB_HIDZT5! zHsm~v`=vu>oO~P)8gf_Qs4>sBY7*)B_Oipr9F9819P+m~eQ%?#E{62f;!7M`3_6o( z)w@WID&j&hBd9$tW)j9}n4dhZw-EbR4^_0rktD{Sd_6|O5cGb*-lfG;aTN8vF;~jM zeKesyZy-nDQIpvec#QgjpA-2oGI}K$-;_X_F5_|Y|0Xt+fL@*ipP8~I$H(C$>%!E3 zPJ(!I?)(GT!-;El5T!^QK7A7D=)Dwd$`ryIEjsIcmN-%pc+Vl9{?s8qpGVJ~dBW*C zd(i0{#XT@yh=DuIg%0O@-; z2~>ML@I|b267`g7_psQpqdgWV<65HK^JDlpyMda(no~x%z}lRm3N>n3?=uOcC%Wt;QD*@G+|TwWRJ^0Yq$3*!If(g43prgTvOIiTG(pOS9nzoFSP19$_ok7d`Be`%e&m^?v!aI3c!lWAbM_#IRokDk9 zsi~1SzZE>h&LC0O$T8wOkJo+|)Uvs9!t;7(LxDv*IhBq56S46uM$)F`;Ifn^tVGI+ zXUdvn1+Z8vWbA|qzCYbuBB?M?{fbOmF50l{X^$gPdWs;48+Q8UDa5n8@fyRe@v@6x zOrf=9gKW{$a>%fnOY*SKH|$7Ye-Ya)ab!IIYOo1Q4~>p^9?8Ir96cKb)CUf(I?w_g z)|8AzxDPEUWV{chh*nrQY2Lv?$OHTGGo2mrq-Pqw+Z`q%;y~B@W64WP_av2DNP3 zKtA=ctS34#E#m~y$Po*w>|!FB(4W#ufxSe22FLKNt=| z9U;AN`VPpQZkp1`?EY!5@1FiAwPaAH-~RW#4%tfMkDrmB`pe}_!hww&51;>b3X#2c zzIQ&5LVUZ^Po9@So<7}ObmIXs_`;2C_d7tLh(CT>ff@P+^2#L@>3Q-RMnN^~~O2)2_~HdtHznMUD4nRJU)udvI^3(tZ(_6_>_#>1t5h41X=0PnUqP$k2)v z)&s(%P=!U56S3+V7eb=X)FNLe&wDLLu`-;q%myQ;-q&|zbtRI$;62*IJ3|&kB`;2_59Jpo1aRp6qT4`PZ?l0D6Ttya>S4SXjudY3o_{JjIOYmIr zYWfAJO3LWR;4IN6E=Nnh!XdZJn{0m*ZYyb^3*eQKUsBV+lF|lh9mC6_ebz!BX3Ubv zn~xa(k2gOIN6Yl|1e_{sp;w`%d^J4<`^vRT3`Rjcsz~vgFq>Ru7Z0|-Ln)AM*N~E) zBcy=cO}0+4ck349k0Hk@2USLmY{lzAl@TMegT(rsgBW`m9fk_KA=w)58&b4<(1PKC zIiOoK-UgfPCWF^0fB1}3-YaO&_6np4Ym9DUz!`$U5o4`VS_UuJ(}ic8aNM4eu#`=Q z#{0b#{$bY%=9!Q%#~3#!OvCIs4`n>eJXPW)g|o9-lVR503GdE%fcjzi4bK{ITm1^b z`-fNzzF2YyOGB^U9No%PZxR^inyCmibLZ1NuxoAu1^9Sw5q$?#6%W&8AXTK$_u=UZ zj~E$f78F!!X&2N~>Zu2Ask|fgG8Pe|I3$*D-Z5O8&wrw{cfwbdW*P%Y^JXg@I5iC2 zpo6w~b5j3|#%%tb7?y$q>p{I}p9wF_)6#r+YhFu685#%74toG=x9h&5T?sfHuh9;m z&V1Si1x_=41(rD*5+23z*rwo>00*6mvqy|qw9+;Ok&XBlQtZo>R7Qs!&$0-vGr?LQ zv+4ld0Y|Gg(^e>%e^26@N~|leh+>6(Ir!$UriUQ4disq17~Fh8`W>qAf2@ixV3N8k zmb{DARCn`$O2Sg`tOu`ZX5&}ryiY<$btBcl(dvctJS5g+(#>G4DZ<>os%9Pi1YW7x zlvRXddAKE;fhlQlfT~49?^ZS}QHXmo;ob%LR1Hrr zFjxW_X$6Lx81RIgUD=POj^3@f!xA-kTq&E{2QOfIH+;3Af!+!g3-xpi{%v7?%Al93 z5Ak#LYvGB7IrKCfS-2>30ea;?ueMQA8umoX()T&Bq8{>UAJYC5zo2k2M=s(~_#?`C zS|DYfs)pBVHzeGSx(Eklb-BVRCA8Gt8h--6K-mE~p@etprqLJStGY7!Tga)m2s?A3 zp}tBO%>}48(xvbcavPoSdA-ht_h%}bH*}Ps~Cqc46Qi*n)8HqN!}O#}*msZ162Ao5J!lTkhEpQ+3zIoe*5)q~qXR zY^DLYWpNRP_oIs&>1%L$aUS(S(vsS#Ni|r>S@u|xVq`tuz{hb$c0sYQYJ$6#^yeJO zV_%);R7noG9&69gizeYU6Z%xsdqYb|p#H|pc#OUf8q^GIzHt^!Hs`U=ByTMh>!XV{ z(6B6FkWMV(l%?yHBhB;k;GU%w89PuBj<3{EK2=~9pv0Zt4sS2jr<_ME+m~HJ+MaxZ zUp}MN5L}v;G^%8=KO*jo%x;0)Wj56=v_6ZO_7AXX8L%B$)<|yyr)z<7#Jbi3dt4@6 zYK;6}_yL3UY#0$Ko4<2u~`i;XwYS7Aw$ z8JEAKNjq}@JM2t$$eqa!AEq-~KKeZrTG|vFPTiA&g~my|8JYA?amab#Ybv52!s({z z!l5+KF0Z2$)-E^Get2m4!}J44Tw$hn!ORu;+U?9we9qnX+5t7*%}MpuvbxFyn^&Z{ zZ^UMsNiqof4?-#z;!X~)K-|aSX2ioBUW0gy!)=HK^Tc?!A~tb&BjTzF>`uBJiM9zM zX)EGR4&RNqkHgy$4|Dh@h{rhGiCD;L2Tl%7jab-yKy(3N1`oCAbt^XCx?HJxR1jxBOd1P ztBA)qJd9Y#op9hy#3l~^5ph)nyIDB=8HqN|;4g?fIs5_QJ`R6^c$mYVAs*xK7-AuB z!hydbHgWh2;;Jxqhl1{FB-%KG^N2e+dA$ejw>4KhVUHc`+1zCkzuK)H2 zAFnNoAB_CkGMEOsw$kgrfJT4Yd%qmo+6v<*oQKETO5?Bp(zyaYK^XmEuyrNq)|JM4 z+QWP8SqaVSN|V(a!!Y`D=eZc@TUQu={a4Rs_yjx6z(mTP>CK>9Un!tyUSFxY(i~<_ I!l+vRziy%nwEzGB diff --git a/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd b/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd index 232f554929195c2f9114a9a4eaffe4a93ac54095..7806424ee141ed22b56ac009ccf7cac26b1e856f 100755 GIT binary patch delta 7218 zcmc&(dstIP+MhWImmo@zt0Izwi$OsF!D77-FdT_D@LIfcvki)hh!&J>5=y&X>h{FZ z?NQN>cH2H^(W2}{trqOs{j9CK(YmayvSrt{CM3X-0v@&X>^lM3t>5?O_dH)7hTqI@ zX5N{3=bd*h=j?xB{x_Hl^|1vYl#CGCHQ%Z!Fxdp2$?qw1gL^i|GI#An$J8_{|cmOp!sqLi@qx_`VaYDgAFwK;Bh$MMJ@G%&P5JUISjHes{_0`EW64s_wK$CY&NE`v7-%aVLO29ECrJ>3 zA%u`l&kzq4!~)1^Jc+bmIhpPirvL)c@p}Lp5HuQMqaXx9pubQE-sF&1Bv#XWV)OFF z5v0wlWq5gh;fA$^#tmy<+Lm8Nc<*vDR?%hRS3pZpr*;tQ2C)X_mh$gHItYZZ!dHW2Y?;u7EVjkcaFo3$z2t@&&RfGLBHkxgKDoFQg26#3SAuWSUs1YJ@kkJqY zMg}O41~mW*fT@7F;}Dt-STh+R9iSah52#8(C<{ElLA-{#9457;uXpy1{v`7)uolH>!TBHbCo=y?8tfL6p)dQM>V?d3R05#8} zs6{A;Vk|;SD2|6Ipf~}cRTSe8%A*J-TSRdpLPm;{5GtXVfKVyLM1;yIf;m@EglVgy z2qr%FEyiL-md_d+KOn#Km0}9kZ7MWw%rDz8BhhDD>DKbHb@>~&&WJAZDKFl*Zu7SC zweD0?&G7AV#ZX!D(0}sGr=?d$7pzZ?Wt4%Aka6>ctC z2SQZ^mF4Rozof{gX~M`TOmYG$M%MZwXAKM948oEZU}P-$IzZz?d{IZcBuT0lh-cu; zOkc?Lh9LY-_F=pO`B@s{JLP*%_W7>vSm42SWbI~O(P#GOC06KLdK7A8M8?_Tbl(J4 zCJ1(2|7B&ifW7}g_6A1F+U>VUQ=mHb&-N5m*{}a3ax$cPU3~LZneb=(7jrI!F!4L| zrTaf|Xz^$Bs`Qb!KO;W{Mwrgqkya=C((HYo@i~!c?x{B47QK}!7R7#RlQc5nj9q?T zLVv%fszBPUHYB_&A?;3E+0o(m14oSLBP$MyN`^b#Xz=KhmsaX!!aMfd({kwD`}PI{ z!>U-y)!S9ToU$LE=clUDt0CTKXH*m$hTAbj=pbkn(hwAyBopeOPgyr<3-ag@eQzy} zRgc!7gH-BaJ7rZYw7eLr8DM1sXD9tZarrXAY!^<`hHC8Df|Rg{3vD-LnGF^CuSBG( z)FWekf=pnc;rH5iW>o=SHHWf0^oQC9%H#G;2g;86sIVGoCK|7b=0=~Wt0FSX1U+;p zl`ISnh>;01-CfB2Sr?M+E!{b&_PBRA(wr1aGsvFcF-v7aj9qmumsP4|LV{g&Iv2VY zMY}ew>?o#9PSaK)ZMqG+8^qDs0#Y!-kKIW7+|4buX3(8X7-I)wc0-K{#OW94c__`ch_NykzqF)PtfcDO=M2RIT2&IongSoMN9 zeatsvZ`=<3NMQG5;O60AXBS=ay}0qB9r<}T3l|yTM)wvzyZ81MMriHcba-V4gZ_3i z!k}bH=9T7Lm`}3_B06@XRbfQ2NN9b{+?``a_pzd?!Q(#ou9)XJ`!t!Av=$U@rV9N#}r@AxhG?U~pl2geE+YB>OCczJhYM8Wl`q z210iqNs?|cu18l!(-3b-@7E`_^k9gi1YJ*R zDRAxS{aL^v73C9I$jKuILN%tZ43oG_zEZE^^t_sz&TF`7d?aV!qqr4(-IW`s8%({<7&)>`NqZ4>LPRShVnglB}0yRb0g;YJ=AO-PG`jv5ua=_q=5 zZI7BYYbgHj;V*l%U|3hWa#>oA5iWP>24f%)R`6DCYdzw!SfoLb<-cZx3tf%(rL?JS z+QCv6y2_5y_I_hFt7?z$^SLoG7n*+t+)#TIBiKc}H#ChEJMwR*vd9WxaGs4+Ur1I0e zCVF9C73B5Rlo|{)r&7-dCpz{0UoL##>5VS+6yWUM9b0oAV*zQNs{1uDL~ZfMPFv{- zrvg*O(+R+jW$058&UPwB*x#u(eiHJjBa6uzb14Lwoc{T0LBhJxs=TU(r|MO9Q7@az zB5*~FkN~Ojo1QF+@=$q4Uv(gP0*lpwn#FA80d$ZN8art^2+}llq7%oBxP?@g?=uW& z4ehMQqY^+vjNs~&>yftm&YX58F6;V5(SiVpI;$FukyFj&@VlAH!724ru z0;~TU7!P-uQa2-3UmjwNZYJi{7DJ^z{4OK3xYlz>1&2@Ju*=L|Ao<||%U-mm_bC0@ z&{Dpb*c{r!*tpJ`ZY;7|jQQ3}#yl%7UTaM+USq{2h1T?v0;{EDwe?cTDl6W&(we?; zh1Ie#*LrE=3s##WRJqK$9ON@Xk&9dnk25W`wmLk&%X9jmR)=@w!u=ziBbXerA$4NOe&+ z)ZRu-mYy2kTKI3b1KFX_NhaUp4Nv=8Is*-o;TSkMUS`1D~_O{a(=RB4Pulmct zEy4JAY^DBanOHOJp9WA<5_2N)lS=&@=*IdZj1VA}@&8tFbANTifIEJ}S$z2Y`)0(b z*K=4{1INJ7|Do<`C(mtyo9F9FEDTRWRLKQ#SIpE3HINKbRf5h=^ zj+d3kZp-84H(CeBapd0cKJ%Jm;)9GEbL4`be20GjJ*YjEN*L9SgcA?xk`J|fVaV*y zom|GlDLJxI|4DABewML>$3g?BFZ#mM8emJN(19kSXp;<%FFgj023&I#gITXjl0)O( zH=434^tind{ugpkHNm@muoKKl0}}jTuPC$@fS;=FD57p5ni1A?d->NtCULP8tw+nKlKB7 zU=33`;2@FDwCnYFs<%y3fyO_yEfKxrsxz)MSw@sgE>_%JZi@&K+<@9|hZxr8q|>`kNxx{p?5q38-d_&}paJ5E6{zw0xb(t33t zWQ3;H-O4h$$B`7{PkWsI9fVgwNIo6K_8_XXc;UVe6o@E%#$AYeuRYZA2-4A<%%O0 z%;rxHdd&UAu>}~LqpVimw@hBj2v;3&`b&jVo)$EPur}g$*%51WpSUEc2(~+NLNhV9;W!kTS~l*gKy& z>HyKOfDdGl@sShpS+YDb5r0hfMuvwp+V5ngXzqZcxgv64#k<5e7sFADG)IoZ735yz z?XZ!K^s(9fPs*$reDf6%Zq+QclJPKtC!{SZ68}hWwAy{AyJ|DRZszCS-_F4G1qpvJ zR{^7NGbh~4@68oM483!~CDgnPn1P*>cQd~=Zvn>FUF%na%qC!lxtZ4one{_*s_e)F zf*j_ThN_jj3;9_Jf$?`&TkmG3TJnGy?q&+y%w)?dU`D!`TsISMSw18u$IXnhEFF@= zx*3CI(U6>(z?hIQ%d%idP_ny_&N6pMP@J2YVVON7NaJRnv*?G)jCM1L7Tr)8rJI>( znE}ke=)K*{1k1fa1`AK%_GT*R4gIjqA;+qJjN+HGk_HRl^zVE%@!Sr;RE|A{~ z8cZkCbm5QRQ``0gp`p!Kbp=fE2Vk)KN;tsCQHPu9C3svw!8x$9gJ4~O?3QR-=2KLXlETj1hIHcpDbQ^>wai*YUa$D~-8$YBYiJRZTr-Xap4 zFb>&a({D{(c6PKw5x$lRnboJU?tnu^QG+etHm zk~=IcPHoKSyy3&gvUN@c!oq0sLsBu0A*&~^j5!Ny;=Aj^j;-zZywum`0ei(C+Akka zFmJ=8c6=>K-#>@Y$y?;_lcVr{B1?|OW)hp6f)9|j$nIAx`QC~hMek{FaduyR5SWKGbq2mb{*oGje@nVkm*S45%&9+MERw0y zei2mB2~Cs+!$W}ztc%V&5{{A2r$yqMq|um{5Km PJZn>35B}hTiTn329|OK* delta 6752 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 KBm0E@-~3-;MuDvW delta 7016 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 diff --git a/app/src/main/assets/dnsd/x86_64/afwall_dnsd b/app/src/main/assets/dnsd/x86_64/afwall_dnsd index 986da9a3b8dcc8a1098cc5e2a90593e16265fa8f..8305b5bbca9b50dfc9494f0a7ed5fc5428efe8a2 100755 GIT binary patch delta 7201 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 diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java index db39a84d3..f2bc2d76e 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java @@ -12,6 +12,10 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.SocketTimeoutException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -208,6 +212,18 @@ public static List getRecentQueries(Context context) { return entries; } + public static String benchmarkUpstreams(Context context) { + String daemonResult = queryControl(context, "benchmark"); + if (daemonResult.startsWith("benchmark=1")) { + ApplicationErrorLog.add(context, "DNS upstream benchmark completed through daemon control socket"); + return daemonResult; + } + + ApplicationErrorLog.add(context, "DNS upstream benchmark falling back to app UDP probes: " + + daemonResult.trim()); + return benchmarkUpstreamsDirect(); + } + public static boolean addRuleFromQuery(Context context, QueryEntry entry, int action) { if (entry == null || !entry.hasDomain()) { return false; @@ -310,6 +326,89 @@ private static String queryControl(Context context, String command) { } } + private static String benchmarkUpstreamsDirect() { + StringBuilder out = new StringBuilder(); + List targets = parseUpstreamTargets(G.dnsHijackUpstreams()); + int timeoutMs = Math.min(Math.max(G.dnsHijackTimeoutMs(), 250), 1000); + byte[] query = buildBenchmarkQuery(); + + out.append("benchmark=1\n"); + out.append("source=app_direct_udp\n"); + out.append("upstreams=").append(targets.size()).append('\n'); + out.append("timeout_ms=").append(timeoutMs).append('\n'); + if (targets.isEmpty()) { + out.append("error=no_upstreams_configured\n"); + return out.toString(); + } + + for (int i = 0; i < targets.size(); i++) { + UpstreamTarget target = targets.get(i); + long start = System.nanoTime(); + int latencyMs = -1; + int bytes = -1; + int rcode = -1; + String status = "fail"; + try (DatagramSocket socket = new DatagramSocket()) { + socket.setSoTimeout(timeoutMs); + InetAddress address = InetAddress.getByName(target.host); + DatagramPacket request = new DatagramPacket(query, query.length, address, target.port); + socket.send(request); + byte[] response = new byte[512]; + DatagramPacket reply = new DatagramPacket(response, response.length); + socket.receive(reply); + latencyMs = (int) ((System.nanoTime() - start) / 1000000L); + bytes = reply.getLength(); + rcode = bytes >= 4 ? response[3] & 0x0f : -1; + status = "ok"; + } catch (SocketTimeoutException e) { + latencyMs = (int) ((System.nanoTime() - start) / 1000000L); + status = "timeout"; + } catch (IOException | RuntimeException e) { + latencyMs = (int) ((System.nanoTime() - start) / 1000000L); + status = "error"; + } + out.append("upstream[").append(i).append("]=") + .append(target.host).append(':').append(target.port) + .append(" status=").append(status) + .append(" latency_ms=").append(latencyMs) + .append(" rcode=").append(rcode) + .append(" bytes=").append(bytes) + .append('\n'); + } + return out.toString(); + } + + private static byte[] buildBenchmarkQuery() { + byte[] query = new byte[] { + 0x42, 0x53, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 0x03, 'c', 'o', 'm', + 0x00, + 0x00, 0x01, + 0x00, 0x01 + }; + int id = (int) (System.currentTimeMillis() & 0xffff); + query[0] = (byte) ((id >> 8) & 0xff); + query[1] = (byte) (id & 0xff); + return query; + } + + private static List parseUpstreamTargets(String raw) { + List targets = new ArrayList<>(); + if (raw == null) { + return targets; + } + String[] lines = raw.split("[\\r\\n,]+"); + for (String line : lines) { + UpstreamTarget target = UpstreamTarget.parse(line); + if (target != null) { + targets.add(target); + } + } + return targets; + } + private static void appendFileInfo(StringBuilder out, String label, File file) { out.append(label).append('=').append(file.getAbsolutePath()); out.append(" exists=").append(file.exists()); @@ -390,6 +489,56 @@ public String displayLine() { } } + private static final class UpstreamTarget { + private final String host; + private final int port; + + private UpstreamTarget(String host, int port) { + this.host = host; + this.port = port; + } + + private static UpstreamTarget parse(String raw) { + if (raw == null) { + return null; + } + String value = raw.trim(); + String host = value; + int port = 53; + if (value.isEmpty() || value.startsWith("#")) { + return null; + } + if (value.startsWith("[") && value.contains("]")) { + int end = value.indexOf(']'); + host = value.substring(1, end); + if (end + 2 < value.length() && value.charAt(end + 1) == ':') { + port = parsePort(value.substring(end + 2), port); + } + } else { + int firstColon = value.indexOf(':'); + int lastColon = value.lastIndexOf(':'); + if (firstColon > 0 && firstColon == lastColon) { + host = value.substring(0, firstColon); + port = parsePort(value.substring(firstColon + 1), port); + } + } + host = host.trim(); + if (host.isEmpty()) { + return null; + } + return new UpstreamTarget(host, port); + } + + private static int parsePort(String raw, int fallback) { + try { + int parsed = Integer.parseInt(raw.trim()); + return parsed > 0 && parsed <= 65535 ? parsed : fallback; + } catch (NumberFormatException e) { + return fallback; + } + } + } + private static String normalizeDomain(String raw) { if (raw == null) { return ""; diff --git a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java index 699f183c1..ed108fc19 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java +++ b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java @@ -77,6 +77,14 @@ private void wireDnsBlocklistActions() { }); } + Preference benchmarkUpstreams = findPreference("dnsHijackBenchmarkUpstreams"); + if (benchmarkUpstreams != null) { + benchmarkUpstreams.setOnPreferenceClickListener(preference -> { + runDnsUpstreamBenchmark(); + return true; + }); + } + Preference rollbackBlocklist = findPreference("dnsHijackRollbackBlocklist"); if (rollbackBlocklist != null) { rollbackBlocklist.setOnPreferenceClickListener(preference -> { @@ -217,6 +225,26 @@ private void runDnsBlocklistRollback() { runBlocklistTask(() -> DnsBlocklistManager.restorePrevious(ctx)); } + private void runDnsUpstreamBenchmark() { + new Thread(() -> { + String result = DnsHijackManager.benchmarkUpstreams(ctx); + new Handler(Looper.getMainLooper()).post(() -> showDnsBenchmarkResult(result)); + }).start(); + } + + private void showDnsBenchmarkResult(String result) { + if (getActivity() == null) { + return; + } + new MaterialDialog.Builder(getActivity()) + .title(R.string.dns_hijack_benchmark_upstreams_title) + .content(result == null || result.trim().isEmpty() + ? getString(R.string.dns_hijack_benchmark_empty) + : result) + .positiveText(R.string.OK) + .show(); + } + private void saveDnsProfilePolicy() { boolean saved = G.saveActiveDnsHijackProfilePolicy() && DnsBlocklistManager.copyGlobalBlocklistToActiveProfile(ctx); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a51dab1a8..d9f8eeda5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -305,6 +305,9 @@ Port used by the local root DNS daemon. Reapply firewall rules after changing this. Upstream DNS servers One upstream per line, using host:port format. + Benchmark upstream DNS + Probe configured upstream resolvers and report per-server latency. + No benchmark result was returned. Fail open Allow upstream DNS when filtering cannot complete instead of blocking the query. Strict allow/block priority diff --git a/app/src/main/res/xml/rules_preferences.xml b/app/src/main/res/xml/rules_preferences.xml index 925365192..364cdb4f2 100644 --- a/app/src/main/res/xml/rules_preferences.xml +++ b/app/src/main/res/xml/rules_preferences.xml @@ -91,6 +91,12 @@ android:summary="@string/dns_hijack_upstreams_summary" android:title="@string/dns_hijack_upstreams_title" /> + + 0 ? response_rcode(response, (size_t) response_len) : -1; + + write_control_response(client, + "upstream[%d]=%s:%d status=%s latency_ms=%d rcode=%d bytes=%ld\n", + i, + g_cfg.upstreams[i].host, + g_cfg.upstreams[i].port, + response_len > 0 ? "ok" : "fail", + latency_ms, + rcode, + (long) response_len); + } +} + static void handle_control(int fd) { int client = accept(fd, NULL, NULL); char cmd[128]; @@ -1406,6 +1470,8 @@ static void handle_control(int fd) { g_cfg.temp_block_count); } else if (strcmp(cmd, "health") == 0) { write_health_response(client); + } else if (strcmp(cmd, "benchmark") == 0) { + write_benchmark_response(client); } else if (strcmp(cmd, "reload") == 0) { if (reload_config()) { write_control_response(client, "ok reload generation=%llu\n", (unsigned long long) g_cfg.generation); From 7298b8d8536f80df995413a9130ac80dd19da58e Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 15:06:35 -0700 Subject: [PATCH 014/108] Add DNS split upstream routes --- .../main/assets/dnsd/arm64-v8a/afwall_dnsd | Bin 25792 -> 27144 bytes .../main/assets/dnsd/armeabi-v7a/afwall_dnsd | Bin 20888 -> 21820 bytes app/src/main/assets/dnsd/x86/afwall_dnsd | Bin 26316 -> 27712 bytes app/src/main/assets/dnsd/x86_64/afwall_dnsd | Bin 27200 -> 28608 bytes .../ufirewall/dns/DnsHijackManager.java | 2 + .../preferences/RulesPreferenceFragment.java | 1 + .../java/dev/ukanth/ufirewall/util/G.java | 6 + app/src/main/res/values/strings.xml | 2 + app/src/main/res/xml/rules_preferences.xml | 6 + dnsdaemon/jni/afwall_dnsd.c | 163 +++++++++++++++--- 10 files changed, 154 insertions(+), 26 deletions(-) diff --git a/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd b/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd index 5c10e4b2a3c7159085dbf0353f68ebb8bf9f7c3f..107e4b3121f6387bc9a117a0370d6bde53bda89a 100755 GIT binary patch literal 27144 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 literal 25792 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 diff --git a/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd b/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd index 7806424ee141ed22b56ac009ccf7cac26b1e856f..255287325b5091a0b711eafd588c9e43cc61fd32 100755 GIT binary patch delta 12027 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 V3V!MQEW?Znn8K*eK}SvCzX7B%Q>y>~ delta 11109 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 F{{w02r}h8< delta 13805 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 diff --git a/app/src/main/assets/dnsd/x86_64/afwall_dnsd b/app/src/main/assets/dnsd/x86_64/afwall_dnsd index 8305b5bbca9b50dfc9494f0a7ed5fc5428efe8a2..5a9f039ab94d20516c015017b8e1f20d01535116 100755 GIT binary patch literal 28608 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%0AF>Fsy%R35uUuKWCPOILRfo8Oj{V|YeaV$&w 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 diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java index f2bc2d76e..4ab1fbb3b 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java @@ -171,6 +171,7 @@ public static String collectLocalDiagnostics(Context context) { out.append("fail_open=").append(G.dnsHijackFailOpen()).append('\n'); out.append("strict_mode=").append(G.dnsHijackStrictMode()).append('\n'); out.append("timeout_ms=").append(G.dnsHijackTimeoutMs()).append('\n'); + out.append("split_upstream_entries=").append(countLines(G.dnsHijackSplitUpstreams())).append('\n'); out.append("scheduled_blocklist_updates=").append(G.dnsHijackScheduledBlocklistUpdates()).append('\n'); out.append("blocklist_update_interval_hours=") .append(G.dnsHijackBlocklistUpdateIntervalHours()).append('\n'); @@ -750,6 +751,7 @@ private static String buildConfig(Context context) { config.append("timeout_ms=").append(G.dnsHijackTimeoutMs()).append('\n'); appendConfigEntries(config, "upstream", G.dnsHijackUpstreams()); + appendConfigEntries(config, "split_upstream", G.dnsHijackSplitUpstreams()); appendConfigEntries(config, "allow_exact", G.dnsHijackAllowExact()); appendConfigEntries(config, "allow_suffix", G.dnsHijackAllowSuffix()); appendConfigEntries(config, "block_exact", G.dnsHijackBlockExact()); diff --git a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java index ed108fc19..c321981b8 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java +++ b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java @@ -509,6 +509,7 @@ private boolean isDnsHijackPreference(String key) { return key != null && (key.equals("enableDnsHijack") || key.equals("dnsHijackPort") || key.equals("dnsHijackUpstreams") + || key.equals("dnsHijackSplitUpstreams") || key.equals("dnsHijackFailOpen") || key.equals("dnsHijackStrictMode") || key.equals("dnsHijackBootPersistence") diff --git a/app/src/main/java/dev/ukanth/ufirewall/util/G.java b/app/src/main/java/dev/ukanth/ufirewall/util/G.java index a4a1e91a4..59dc1a929 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/util/G.java +++ b/app/src/main/java/dev/ukanth/ufirewall/util/G.java @@ -174,6 +174,7 @@ public static Context getContext() { private static final String ENABLE_DNS_HIJACK = "enableDnsHijack"; private static final String DNS_HIJACK_PORT = "dnsHijackPort"; private static final String DNS_HIJACK_UPSTREAMS = "dnsHijackUpstreams"; + private static final String DNS_HIJACK_SPLIT_UPSTREAMS = "dnsHijackSplitUpstreams"; private static final String DNS_HIJACK_FAIL_OPEN = "dnsHijackFailOpen"; private static final String DNS_HIJACK_STRICT_MODE = "dnsHijackStrictMode"; private static final String DNS_HIJACK_BOOT_PERSISTENCE = "dnsHijackBootPersistence"; @@ -193,6 +194,7 @@ public static Context getContext() { private static final String DNS_HIJACK_PROFILE_POLICY_SAVED = "dnsHijackProfilePolicySaved"; private static final String[] DNS_HIJACK_PROFILE_POLICY_KEYS = new String[] { DNS_HIJACK_UPSTREAMS, + DNS_HIJACK_SPLIT_UPSTREAMS, DNS_HIJACK_FAIL_OPEN, DNS_HIJACK_STRICT_MODE, DNS_HIJACK_TIMEOUT_MS, @@ -310,6 +312,10 @@ public static String dnsHijackUpstreams() { return dnsPolicyPrefs().getString(DNS_HIJACK_UPSTREAMS, "1.1.1.1:53\n8.8.8.8:53"); } + public static String dnsHijackSplitUpstreams() { + return dnsPolicyPrefs().getString(DNS_HIJACK_SPLIT_UPSTREAMS, ""); + } + public static boolean dnsHijackFailOpen() { return dnsPolicyPrefs().getBoolean(DNS_HIJACK_FAIL_OPEN, true); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d9f8eeda5..b1b6e84f8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -308,6 +308,8 @@ Benchmark upstream DNS Probe configured upstream resolvers and report per-server latency. No benchmark result was returned. + Split DNS routes + Route matching domains to dedicated upstreams, one per line, such as corp.example=10.0.0.53:53. Fail open Allow upstream DNS when filtering cannot complete instead of blocking the query. Strict allow/block priority diff --git a/app/src/main/res/xml/rules_preferences.xml b/app/src/main/res/xml/rules_preferences.xml index 364cdb4f2..29c64b5b7 100644 --- a/app/src/main/res/xml/rules_preferences.xml +++ b/app/src/main/res/xml/rules_preferences.xml @@ -97,6 +97,12 @@ android:summary="@string/dns_hijack_benchmark_upstreams_summary" android:title="@string/dns_hijack_benchmark_upstreams_title" /> + + domain_len) { - continue; - } - if (strcmp(domain + domain_len - suffix_len, suffix) == 0) { - if (suffix_len == domain_len || domain[domain_len - suffix_len - 1] == '.') { - return true; - } + if (domain_has_suffix(domain, suffix)) { + return true; } } return false; } +static bool domain_has_suffix(const char *domain, const char *suffix) { + size_t domain_len; + size_t suffix_len; + if (domain == NULL || suffix == NULL) { + return false; + } + domain_len = strlen(domain); + suffix_len = strlen(suffix); + if (suffix_len == 0 || suffix_len > domain_len) { + return false; + } + if (strcmp(domain + domain_len - suffix_len, suffix) != 0) { + return false; + } + return suffix_len == domain_len || domain[domain_len - suffix_len - 1] == '.'; +} + static bool regex_match_rules(const regex_rule_t *rules, int count, const char *domain) { int i; for (i = 0; i < count; i++) { @@ -737,10 +757,40 @@ static int connect_upstream(const upstream_t *upstream, int socktype, int timeou return fd; } -static ssize_t forward_udp(const config_t *cfg, const uint8_t *query, size_t query_len, uint8_t *response, size_t response_len) { +static const upstream_t *select_upstreams(const config_t *cfg, const char *domain, + int *count, const char **route) { int i; - for (i = 0; i < cfg->upstream_count; i++) { - int fd = connect_upstream(&cfg->upstreams[i], SOCK_DGRAM, cfg->timeout_ms); + int best = -1; + size_t best_len = 0; + for (i = 0; i < cfg->split_upstream_count; i++) { + size_t suffix_len = strlen(cfg->split_upstreams[i].suffix); + if (suffix_len > best_len && domain_has_suffix(domain, cfg->split_upstreams[i].suffix)) { + best = i; + best_len = suffix_len; + } + } + if (best >= 0) { + *count = 1; + if (route != NULL) { + *route = "split_upstream"; + } + return &cfg->split_upstreams[best].upstream; + } + *count = cfg->upstream_count; + if (route != NULL) { + *route = "upstream"; + } + return cfg->upstreams; +} + +static ssize_t forward_udp(const config_t *cfg, const char *domain, const uint8_t *query, + size_t query_len, uint8_t *response, size_t response_len, + const char **route) { + int i; + int count = 0; + const upstream_t *upstreams = select_upstreams(cfg, domain, &count, route); + for (i = 0; i < count; i++) { + int fd = connect_upstream(&upstreams[i], SOCK_DGRAM, cfg->timeout_ms); ssize_t got; if (fd < 0) { continue; @@ -820,18 +870,23 @@ static ssize_t read_full(int fd, uint8_t *buf, size_t len) { return (ssize_t) got; } -static ssize_t forward_tcp(const config_t *cfg, const uint8_t *query, size_t query_len, uint8_t *response, size_t response_len) { +static ssize_t forward_tcp(const config_t *cfg, const char *domain, const uint8_t *query, + size_t query_len, uint8_t *response, size_t response_len, + const char **route) { int i; uint8_t lenbuf[2]; + int count = 0; + const upstream_t *upstreams; if (query_len > 65535) { return -1; } + upstreams = select_upstreams(cfg, domain, &count, route); lenbuf[0] = (uint8_t) ((query_len >> 8) & 0xffu); lenbuf[1] = (uint8_t) (query_len & 0xffu); - for (i = 0; i < cfg->upstream_count; i++) { + for (i = 0; i < count; i++) { uint8_t rlenbuf[2]; uint16_t rlen; - int fd = connect_upstream(&cfg->upstreams[i], SOCK_STREAM, cfg->timeout_ms); + int fd = connect_upstream(&upstreams[i], SOCK_STREAM, cfg->timeout_ms); if (fd < 0) { continue; } @@ -869,13 +924,11 @@ static void default_config(config_t *cfg) { cfg->upstreams[0].port = 53; } -static bool parse_upstream(config_t *cfg, const char *value) { +static bool parse_upstream_value(const char *value, upstream_t *upstream) { const char *colon; - upstream_t *upstream; - if (cfg->upstream_count >= MAX_UPSTREAMS || value == NULL || value[0] == '\0') { + if (value == NULL || value[0] == '\0' || upstream == NULL) { return false; } - upstream = &cfg->upstreams[cfg->upstream_count]; memset(upstream, 0, sizeof(*upstream)); colon = strrchr(value, ':'); if (colon != NULL && colon[1] != '\0') { @@ -895,10 +948,63 @@ static bool parse_upstream(config_t *cfg, const char *value) { if (upstream->port <= 0 || upstream->port > 65535) { upstream->port = 53; } + return upstream->host[0] != '\0'; +} + +static bool parse_upstream(config_t *cfg, const char *value) { + if (cfg->upstream_count >= MAX_UPSTREAMS) { + return false; + } + if (!parse_upstream_value(value, &cfg->upstreams[cfg->upstream_count])) { + return false; + } cfg->upstream_count++; return true; } +static bool parse_split_upstream(config_t *cfg, const char *value) { + char line[512]; + char *sep; + char *suffix; + char *upstream; + if (cfg->split_upstream_count >= MAX_SPLIT_UPSTREAMS || value == NULL || value[0] == '\0') { + return false; + } + safe_copy(line, sizeof(line), value); + sep = strchr(line, '|'); + if (sep == NULL) { + sep = strchr(line, '='); + } + if (sep == NULL) { + sep = strchr(line, ' '); + } + if (sep == NULL) { + return false; + } + *sep = '\0'; + suffix = line; + upstream = sep + 1; + trim(suffix); + trim(upstream); + lower_ascii(suffix); + if (suffix[0] == '*' && suffix[1] == '.') { + memmove(suffix, suffix + 2, strlen(suffix + 2) + 1); + } + while (suffix[0] == '.') { + memmove(suffix, suffix + 1, strlen(suffix)); + } + if (!valid_domain_rule(suffix)) { + return false; + } + safe_copy(cfg->split_upstreams[cfg->split_upstream_count].suffix, + sizeof(cfg->split_upstreams[cfg->split_upstream_count].suffix), suffix); + if (!parse_upstream_value(upstream, &cfg->split_upstreams[cfg->split_upstream_count].upstream)) { + return false; + } + cfg->split_upstream_count++; + return true; +} + static void load_string_rule_file(string_rule_t *rules, int *count, const char *path); static void load_regex_rule_file(regex_rule_t *rules, int *count, const char *path); @@ -949,6 +1055,8 @@ static bool load_config(const char *path, config_t *new_cfg) { } } else if (strcmp(key, "upstream") == 0) { parse_upstream(new_cfg, value); + } else if (strcmp(key, "split_upstream") == 0) { + parse_split_upstream(new_cfg, value); } else if (strcmp(key, "allow_exact") == 0) { add_string_rule(new_cfg->exact_allow, &new_cfg->exact_allow_count, value); } else if (strcmp(key, "allow_exact_file") == 0) { @@ -1140,6 +1248,7 @@ static void handle_dns_query(const config_t *cfg, const uint8_t *query, size_t q uint16_t qtype = 0; const char *reason = "parse"; ssize_t forwarded; + const char *route = "upstream"; struct timeval start; struct timeval upstream_start; struct timeval upstream_end; @@ -1177,8 +1286,8 @@ static void handle_dns_query(const config_t *cfg, const uint8_t *query, size_t q g_stats.upstream_requests++; gettimeofday(&upstream_start, NULL); forwarded = tcp - ? forward_tcp(cfg, query, query_len, response, MAX_PACKET) - : forward_udp(cfg, query, query_len, response, MAX_PACKET); + ? forward_tcp(cfg, domain, query, query_len, response, MAX_PACKET, &route) + : forward_udp(cfg, domain, query, query_len, response, MAX_PACKET, &route); gettimeofday(&upstream_end, NULL); upstream_latency_ms = elapsed_ms(&upstream_start, &upstream_end); if (upstream_latency_ms > 0) { @@ -1189,8 +1298,8 @@ static void handle_dns_query(const config_t *cfg, const uint8_t *query, size_t q cache_store(domain, qtype, response, *response_len); g_stats.allowed++; g_stats.upstream_successes++; - *action_out = "upstream"; - finish_dns_query(domain, "upstream", &start); + *action_out = route; + finish_dns_query(domain, route, &start); return; } g_stats.upstream_failures++; @@ -1338,7 +1447,7 @@ static void write_health_response(int client) { write_control_response(client, "health=1\nrunning=1\npid=%ld\nuptime=%llu\nlisten_port=%d\n" - "generation=%llu\nupstreams=%d\nupstream_probe=%s\n" + "generation=%llu\nupstreams=%d\nsplit_upstreams=%d\nupstream_probe=%s\n" "upstream_probe_ms=%d\nupstream_probe_index=%d\nupstream_probe_rcode=%d\n" "queries=%llu\nblocked=%llu\nallowed=%llu\ncache_entries=%d\n" "rules_total=%d\n", @@ -1347,6 +1456,7 @@ static void write_health_response(int client) { g_cfg.listen_port, (unsigned long long) g_cfg.generation, g_cfg.upstream_count, + g_cfg.split_upstream_count, response_len > 0 ? "ok" : "fail", latency_ms, upstream_index, @@ -1432,7 +1542,7 @@ static void handle_control(int fd) { "avg_latency_ms=%llu\nmax_latency_ms=%llu\nupstream_avg_latency_ms=%llu\n" "reloads=%llu\nrules_exact_allow=%d\nrules_suffix_allow=%d\nrules_exact_block=%d\n" "rules_suffix_block=%d\nrules_regex_allow=%d\nrules_regex_block=%d\n" - "rules_temp_allow=%d\nrules_temp_block=%d\n", + "rules_temp_allow=%d\nrules_temp_block=%d\nsplit_upstreams=%d\n", (long) getpid(), (unsigned long long) (now_seconds() - g_stats.start_time), (unsigned long long) g_cfg.generation, @@ -1467,7 +1577,8 @@ static void handle_control(int fd) { g_cfg.regex_allow_count, g_cfg.regex_block_count, g_cfg.temp_allow_count, - g_cfg.temp_block_count); + g_cfg.temp_block_count, + g_cfg.split_upstream_count); } else if (strcmp(cmd, "health") == 0) { write_health_response(client); } else if (strcmp(cmd, "benchmark") == 0) { From 6bf58e8b15ab83d5867c7c20c5c81b6c188d2711 Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 15:13:36 -0700 Subject: [PATCH 015/108] Add per-app DNS redirect policy --- .../ufirewall/dns/DnsHijackManager.java | 119 ++++++++++++++++-- .../preferences/RulesPreferenceFragment.java | 4 + .../java/dev/ukanth/ufirewall/util/G.java | 12 ++ app/src/main/res/values/strings.xml | 4 + app/src/main/res/xml/rules_preferences.xml | 12 ++ 5 files changed, 143 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java index 4ab1fbb3b..4c496dd84 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java @@ -76,6 +76,7 @@ public static void appendApplyCommands(Context context, List commands, b if (!ipv6) { ApplicationErrorLog.add(context, "DNS hijacker enabled; daemon start and DNS redirect rules queued"); + logUidPolicy(context, "DNS per-app redirect policy queued"); commands.add("#LITERAL# " + shellQuote(supervisorPath(context)) + " start"); appendBootPersistenceCommand(context, commands); } @@ -172,6 +173,8 @@ public static String collectLocalDiagnostics(Context context) { out.append("strict_mode=").append(G.dnsHijackStrictMode()).append('\n'); out.append("timeout_ms=").append(G.dnsHijackTimeoutMs()).append('\n'); out.append("split_upstream_entries=").append(countLines(G.dnsHijackSplitUpstreams())).append('\n'); + out.append("capture_uid_entries=").append(parseUidList(G.dnsHijackCaptureUids()).size()).append('\n'); + out.append("bypass_uid_entries=").append(parseUidList(G.dnsHijackBypassUids()).size()).append('\n'); out.append("scheduled_blocklist_updates=").append(G.dnsHijackScheduledBlocklistUpdates()).append('\n'); out.append("blocklist_update_interval_hours=") .append(G.dnsHijackBlocklistUpdateIntervalHours()).append('\n'); @@ -447,6 +450,103 @@ private static int countLines(String raw) { return count; } + private static void logUidPolicy(Context context, String prefix) { + int captureCount = parseUidList(G.dnsHijackCaptureUids()).size(); + int bypassCount = parseUidList(G.dnsHijackBypassUids()).size(); + if (captureCount > 0 || bypassCount > 0) { + ApplicationErrorLog.add(context, prefix + ": capture_uids=" + captureCount + + " bypass_uids=" + bypassCount); + } + } + + private static boolean appendOutputUidPolicyRules(List commands, String appendCommand, int port) { + List bypassUids = parseUidList(G.dnsHijackBypassUids()); + List captureUids = parseUidList(G.dnsHijackCaptureUids()); + for (Integer uid : bypassUids) { + commands.add(appendCommand + " -m owner --uid-owner " + uid + " -j RETURN"); + } + if (captureUids.isEmpty()) { + return false; + } + for (Integer uid : captureUids) { + if (bypassUids.contains(uid)) { + continue; + } + commands.add(appendCommand + " -p udp --dport 53 -m owner --uid-owner " + + uid + " -j REDIRECT --to-ports " + port); + commands.add(appendCommand + " -p tcp --dport 53 -m owner --uid-owner " + + uid + " -j REDIRECT --to-ports " + port); + } + commands.add(appendCommand + " -j RETURN"); + return true; + } + + private static String buildBootOutputRedirectRules(String tool, String chainVariable) { + StringBuilder script = new StringBuilder(); + List bypassUids = parseUidList(G.dnsHijackBypassUids()); + List captureUids = parseUidList(G.dnsHijackCaptureUids()); + for (Integer uid : bypassUids) { + script.append(" ").append(tool).append(" -t nat -A \"") + .append(chainVariable).append("\" -m owner --uid-owner ") + .append(uid).append(" -j RETURN >> \"$LOG\" 2>&1\n"); + } + if (captureUids.isEmpty()) { + script.append(" ").append(tool).append(" -t nat -A \"") + .append(chainVariable) + .append("\" -p udp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n"); + script.append(" ").append(tool).append(" -t nat -A \"") + .append(chainVariable) + .append("\" -p tcp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n"); + return script.toString(); + } + for (Integer uid : captureUids) { + if (bypassUids.contains(uid)) { + continue; + } + script.append(" ").append(tool).append(" -t nat -A \"") + .append(chainVariable).append("\" -p udp --dport 53 -m owner --uid-owner ") + .append(uid).append(" -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n"); + script.append(" ").append(tool).append(" -t nat -A \"") + .append(chainVariable).append("\" -p tcp --dport 53 -m owner --uid-owner ") + .append(uid).append(" -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n"); + } + script.append(" ").append(tool).append(" -t nat -A \"") + .append(chainVariable).append("\" -j RETURN >> \"$LOG\" 2>&1\n"); + return script.toString(); + } + + private static List parseUidList(String raw) { + List uids = new ArrayList<>(); + if (raw == null || raw.trim().isEmpty()) { + return uids; + } + String[] lines = raw.split("\\r?\\n"); + for (String line : lines) { + if (line == null) { + continue; + } + int comment = line.indexOf('#'); + String clean = comment >= 0 ? line.substring(0, comment) : line; + String[] tokens = clean.trim().split("[\\s,|]+"); + for (String token : tokens) { + if (token == null || token.trim().isEmpty()) { + continue; + } + try { + long parsed = Long.parseLong(token.trim()); + if (parsed > 0 && parsed <= Integer.MAX_VALUE) { + Integer uid = (int) parsed; + if (!uids.contains(uid)) { + uids.add(uid); + } + } + } catch (NumberFormatException ignored) { + } + } + } + return uids; + } + public static final class QueryEntry { public final long timestamp; public final String action; @@ -601,6 +701,7 @@ private static List buildRootRepairCommands(Context context) { List commands = new ArrayList<>(); File bootScript = new File(workDir(context), BOOT_SCRIPT); commands.add(shellQuote(supervisorPath(context)) + " start"); + logUidPolicy(context, "DNS per-app redirect policy repair queued"); appendRootRedirectRepairCommands(context, commands, false); if (G.enableIPv6()) { appendRootRedirectRepairCommands(context, commands, true); @@ -629,8 +730,10 @@ private static void appendRootRedirectRepairCommands(Context context, List commands, boolean ipv6) { commands.add("#NOCHK# -t nat -A " + chain + " -o lo -j RETURN"); commands.add("#NOCHK# -t nat -A " + chain + " -m owner --uid-owner 0 -j RETURN"); - commands.add("#NOCHK# -t nat -A " + chain + " -p udp --dport 53 -j REDIRECT --to-ports " + port); - commands.add("#NOCHK# -t nat -A " + chain + " -p tcp --dport 53 -j REDIRECT --to-ports " + port); + if (!appendOutputUidPolicyRules(commands, "#NOCHK# -t nat -A " + chain, port)) { + commands.add("#NOCHK# -t nat -A " + chain + " -p udp --dport 53 -j REDIRECT --to-ports " + port); + commands.add("#NOCHK# -t nat -A " + chain + " -p tcp --dport 53 -j REDIRECT --to-ports " + port); + } commands.add("#NOCHK# -t nat -A " + preChain + " -i lo -j RETURN"); commands.add("#NOCHK# -t nat -A " + preChain + " -p udp --dport 53 -j REDIRECT --to-ports " + port); @@ -824,8 +929,7 @@ private static String buildBootScript(Context context, File dir) { + " ipt -t nat -F \"$PRE4\" >/dev/null 2>&1\n" + " ipt -t nat -A \"$CHAIN4\" -o lo -j RETURN >> \"$LOG\" 2>&1\n" + " ipt -t nat -A \"$CHAIN4\" -m owner --uid-owner 0 -j RETURN >> \"$LOG\" 2>&1\n" - + " ipt -t nat -A \"$CHAIN4\" -p udp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" - + " ipt -t nat -A \"$CHAIN4\" -p tcp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" + + buildBootOutputRedirectRules("ipt", "$CHAIN4") + " ipt -t nat -A \"$PRE4\" -i lo -j RETURN >> \"$LOG\" 2>&1\n" + " ipt -t nat -A \"$PRE4\" -p udp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" + " ipt -t nat -A \"$PRE4\" -p tcp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" @@ -845,8 +949,7 @@ private static String buildBootScript(Context context, File dir) { + " ip6t -t nat -F \"$PRE6\" >/dev/null 2>&1\n" + " ip6t -t nat -A \"$CHAIN6\" -o lo -j RETURN >> \"$LOG\" 2>&1\n" + " ip6t -t nat -A \"$CHAIN6\" -m owner --uid-owner 0 -j RETURN >> \"$LOG\" 2>&1\n" - + " ip6t -t nat -A \"$CHAIN6\" -p udp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" - + " ip6t -t nat -A \"$CHAIN6\" -p tcp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" + + buildBootOutputRedirectRules("ip6t", "$CHAIN6") + " ip6t -t nat -A \"$PRE6\" -i lo -j RETURN >> \"$LOG\" 2>&1\n" + " ip6t -t nat -A \"$PRE6\" -p udp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" + " ip6t -t nat -A \"$PRE6\" -p tcp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" diff --git a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java index c321981b8..238faee22 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java +++ b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java @@ -510,6 +510,8 @@ private boolean isDnsHijackPreference(String key) { || key.equals("dnsHijackPort") || key.equals("dnsHijackUpstreams") || key.equals("dnsHijackSplitUpstreams") + || key.equals("dnsHijackCaptureUids") + || key.equals("dnsHijackBypassUids") || key.equals("dnsHijackFailOpen") || key.equals("dnsHijackStrictMode") || key.equals("dnsHijackBootPersistence") @@ -539,6 +541,8 @@ private boolean shouldReloadDnsHijackPreference(String key) { && !key.equals("enableDnsHijack") && !key.equals("dnsHijackPort") && !key.equals("dnsHijackBootPersistence") + && !key.equals("dnsHijackCaptureUids") + && !key.equals("dnsHijackBypassUids") && !key.equals("dnsHijackBlocklistUrls") && !key.equals("dnsHijackScheduledBlocklistUpdates") && !key.equals("dnsHijackBlocklistUpdateIntervalHours"); diff --git a/app/src/main/java/dev/ukanth/ufirewall/util/G.java b/app/src/main/java/dev/ukanth/ufirewall/util/G.java index 59dc1a929..c8fd57cab 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/util/G.java +++ b/app/src/main/java/dev/ukanth/ufirewall/util/G.java @@ -175,6 +175,8 @@ public static Context getContext() { private static final String DNS_HIJACK_PORT = "dnsHijackPort"; private static final String DNS_HIJACK_UPSTREAMS = "dnsHijackUpstreams"; private static final String DNS_HIJACK_SPLIT_UPSTREAMS = "dnsHijackSplitUpstreams"; + private static final String DNS_HIJACK_CAPTURE_UIDS = "dnsHijackCaptureUids"; + private static final String DNS_HIJACK_BYPASS_UIDS = "dnsHijackBypassUids"; private static final String DNS_HIJACK_FAIL_OPEN = "dnsHijackFailOpen"; private static final String DNS_HIJACK_STRICT_MODE = "dnsHijackStrictMode"; private static final String DNS_HIJACK_BOOT_PERSISTENCE = "dnsHijackBootPersistence"; @@ -195,6 +197,8 @@ public static Context getContext() { private static final String[] DNS_HIJACK_PROFILE_POLICY_KEYS = new String[] { DNS_HIJACK_UPSTREAMS, DNS_HIJACK_SPLIT_UPSTREAMS, + DNS_HIJACK_CAPTURE_UIDS, + DNS_HIJACK_BYPASS_UIDS, DNS_HIJACK_FAIL_OPEN, DNS_HIJACK_STRICT_MODE, DNS_HIJACK_TIMEOUT_MS, @@ -316,6 +320,14 @@ public static String dnsHijackSplitUpstreams() { return dnsPolicyPrefs().getString(DNS_HIJACK_SPLIT_UPSTREAMS, ""); } + public static String dnsHijackCaptureUids() { + return dnsPolicyPrefs().getString(DNS_HIJACK_CAPTURE_UIDS, ""); + } + + public static String dnsHijackBypassUids() { + return dnsPolicyPrefs().getString(DNS_HIJACK_BYPASS_UIDS, ""); + } + public static boolean dnsHijackFailOpen() { return dnsPolicyPrefs().getBoolean(DNS_HIJACK_FAIL_OPEN, true); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b1b6e84f8..2e7339f2d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -310,6 +310,10 @@ No benchmark result was returned. Split DNS routes Route matching domains to dedicated upstreams, one per line, such as corp.example=10.0.0.53:53. + Limit DNS capture to UIDs + Optional app UID list. When set, only listed UIDs are redirected through DNS filtering. + Bypass DNS capture for UIDs + Optional app UID list that keeps matching apps on the normal resolver path. Fail open Allow upstream DNS when filtering cannot complete instead of blocking the query. Strict allow/block priority diff --git a/app/src/main/res/xml/rules_preferences.xml b/app/src/main/res/xml/rules_preferences.xml index 29c64b5b7..88e13aab8 100644 --- a/app/src/main/res/xml/rules_preferences.xml +++ b/app/src/main/res/xml/rules_preferences.xml @@ -103,6 +103,18 @@ android:summary="@string/dns_hijack_split_upstreams_summary" android:title="@string/dns_hijack_split_upstreams_title" /> + + + + Date: Fri, 26 Jun 2026 15:19:27 -0700 Subject: [PATCH 016/108] Add per-network DNS redirect policy --- .../ufirewall/dns/DnsHijackManager.java | 211 +++++++++++++++--- .../preferences/RulesPreferenceFragment.java | 4 + .../java/dev/ukanth/ufirewall/util/G.java | 12 + app/src/main/res/values/strings.xml | 4 + app/src/main/res/xml/rules_preferences.xml | 12 + 5 files changed, 215 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java index 4c496dd84..43fb27b03 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java @@ -76,7 +76,7 @@ public static void appendApplyCommands(Context context, List commands, b if (!ipv6) { ApplicationErrorLog.add(context, "DNS hijacker enabled; daemon start and DNS redirect rules queued"); - logUidPolicy(context, "DNS per-app redirect policy queued"); + logRedirectPolicy(context, "DNS redirect policy queued"); commands.add("#LITERAL# " + shellQuote(supervisorPath(context)) + " start"); appendBootPersistenceCommand(context, commands); } @@ -175,6 +175,10 @@ public static String collectLocalDiagnostics(Context context) { out.append("split_upstream_entries=").append(countLines(G.dnsHijackSplitUpstreams())).append('\n'); out.append("capture_uid_entries=").append(parseUidList(G.dnsHijackCaptureUids()).size()).append('\n'); out.append("bypass_uid_entries=").append(parseUidList(G.dnsHijackBypassUids()).size()).append('\n'); + out.append("capture_interface_entries=") + .append(parseInterfaceList(G.dnsHijackCaptureInterfaces()).size()).append('\n'); + out.append("bypass_interface_entries=") + .append(parseInterfaceList(G.dnsHijackBypassInterfaces()).size()).append('\n'); out.append("scheduled_blocklist_updates=").append(G.dnsHijackScheduledBlocklistUpdates()).append('\n'); out.append("blocklist_update_interval_hours=") .append(G.dnsHijackBlocklistUpdateIntervalHours()).append('\n'); @@ -450,32 +454,88 @@ private static int countLines(String raw) { return count; } - private static void logUidPolicy(Context context, String prefix) { + private static void logRedirectPolicy(Context context, String prefix) { int captureCount = parseUidList(G.dnsHijackCaptureUids()).size(); int bypassCount = parseUidList(G.dnsHijackBypassUids()).size(); - if (captureCount > 0 || bypassCount > 0) { + int captureInterfaceCount = parseInterfaceList(G.dnsHijackCaptureInterfaces()).size(); + int bypassInterfaceCount = parseInterfaceList(G.dnsHijackBypassInterfaces()).size(); + if (captureCount > 0 || bypassCount > 0 + || captureInterfaceCount > 0 || bypassInterfaceCount > 0) { ApplicationErrorLog.add(context, prefix + ": capture_uids=" + captureCount - + " bypass_uids=" + bypassCount); + + " bypass_uids=" + bypassCount + + " capture_interfaces=" + captureInterfaceCount + + " bypass_interfaces=" + bypassInterfaceCount); } } - private static boolean appendOutputUidPolicyRules(List commands, String appendCommand, int port) { + private static boolean appendOutputPolicyRules(List commands, String appendCommand, int port) { List bypassUids = parseUidList(G.dnsHijackBypassUids()); List captureUids = parseUidList(G.dnsHijackCaptureUids()); + List bypassInterfaces = parseInterfaceList(G.dnsHijackBypassInterfaces()); + List captureInterfaces = parseInterfaceList(G.dnsHijackCaptureInterfaces()); + for (String iface : bypassInterfaces) { + commands.add(appendCommand + " -o " + iface + " -j RETURN"); + } for (Integer uid : bypassUids) { commands.add(appendCommand + " -m owner --uid-owner " + uid + " -j RETURN"); } + if (captureUids.isEmpty() && captureInterfaces.isEmpty()) { + return false; + } if (captureUids.isEmpty()) { + for (String iface : captureInterfaces) { + appendOutputRedirect(commands, appendCommand, port, null, iface); + } + } else if (captureInterfaces.isEmpty()) { + for (Integer uid : captureUids) { + if (!bypassUids.contains(uid)) { + appendOutputRedirect(commands, appendCommand, port, uid, null); + } + } + } else { + for (String iface : captureInterfaces) { + if (bypassInterfaces.contains(iface)) { + continue; + } + for (Integer uid : captureUids) { + if (!bypassUids.contains(uid)) { + appendOutputRedirect(commands, appendCommand, port, uid, iface); + } + } + } + } + commands.add(appendCommand + " -j RETURN"); + return true; + } + + private static void appendOutputRedirect(List commands, String appendCommand, + int port, Integer uid, String iface) { + String matcher = ""; + if (iface != null) { + matcher += " -o " + iface; + } + if (uid != null) { + matcher += " -m owner --uid-owner " + uid; + } + commands.add(appendCommand + matcher + " -p udp --dport 53 -j REDIRECT --to-ports " + port); + commands.add(appendCommand + matcher + " -p tcp --dport 53 -j REDIRECT --to-ports " + port); + } + + private static boolean appendPreroutingPolicyRules(List commands, String appendCommand, int port) { + List bypassInterfaces = parseInterfaceList(G.dnsHijackBypassInterfaces()); + List captureInterfaces = parseInterfaceList(G.dnsHijackCaptureInterfaces()); + for (String iface : bypassInterfaces) { + commands.add(appendCommand + " -i " + iface + " -j RETURN"); + } + if (captureInterfaces.isEmpty()) { return false; } - for (Integer uid : captureUids) { - if (bypassUids.contains(uid)) { + for (String iface : captureInterfaces) { + if (bypassInterfaces.contains(iface)) { continue; } - commands.add(appendCommand + " -p udp --dport 53 -m owner --uid-owner " - + uid + " -j REDIRECT --to-ports " + port); - commands.add(appendCommand + " -p tcp --dport 53 -m owner --uid-owner " - + uid + " -j REDIRECT --to-ports " + port); + commands.add(appendCommand + " -i " + iface + " -p udp --dport 53 -j REDIRECT --to-ports " + port); + commands.add(appendCommand + " -i " + iface + " -p tcp --dport 53 -j REDIRECT --to-ports " + port); } commands.add(appendCommand + " -j RETURN"); return true; @@ -485,12 +545,81 @@ private static String buildBootOutputRedirectRules(String tool, String chainVari StringBuilder script = new StringBuilder(); List bypassUids = parseUidList(G.dnsHijackBypassUids()); List captureUids = parseUidList(G.dnsHijackCaptureUids()); + List bypassInterfaces = parseInterfaceList(G.dnsHijackBypassInterfaces()); + List captureInterfaces = parseInterfaceList(G.dnsHijackCaptureInterfaces()); + for (String iface : bypassInterfaces) { + script.append(" ").append(tool).append(" -t nat -A \"") + .append(chainVariable).append("\" -o ") + .append(iface).append(" -j RETURN >> \"$LOG\" 2>&1\n"); + } for (Integer uid : bypassUids) { script.append(" ").append(tool).append(" -t nat -A \"") .append(chainVariable).append("\" -m owner --uid-owner ") .append(uid).append(" -j RETURN >> \"$LOG\" 2>&1\n"); } + if (captureUids.isEmpty() && captureInterfaces.isEmpty()) { + script.append(" ").append(tool).append(" -t nat -A \"") + .append(chainVariable) + .append("\" -p udp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n"); + script.append(" ").append(tool).append(" -t nat -A \"") + .append(chainVariable) + .append("\" -p tcp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n"); + return script.toString(); + } if (captureUids.isEmpty()) { + for (String iface : captureInterfaces) { + appendBootOutputRedirect(script, tool, chainVariable, null, iface); + } + } else if (captureInterfaces.isEmpty()) { + for (Integer uid : captureUids) { + if (!bypassUids.contains(uid)) { + appendBootOutputRedirect(script, tool, chainVariable, uid, null); + } + } + } else { + for (String iface : captureInterfaces) { + if (bypassInterfaces.contains(iface)) { + continue; + } + for (Integer uid : captureUids) { + if (!bypassUids.contains(uid)) { + appendBootOutputRedirect(script, tool, chainVariable, uid, iface); + } + } + } + } + script.append(" ").append(tool).append(" -t nat -A \"") + .append(chainVariable).append("\" -j RETURN >> \"$LOG\" 2>&1\n"); + return script.toString(); + } + + private static void appendBootOutputRedirect(StringBuilder script, String tool, + String chainVariable, Integer uid, String iface) { + String matcher = ""; + if (iface != null) { + matcher += " -o " + iface; + } + if (uid != null) { + matcher += " -m owner --uid-owner " + uid; + } + script.append(" ").append(tool).append(" -t nat -A \"") + .append(chainVariable).append("\"").append(matcher) + .append(" -p udp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n"); + script.append(" ").append(tool).append(" -t nat -A \"") + .append(chainVariable).append("\"").append(matcher) + .append(" -p tcp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n"); + } + + private static String buildBootPreroutingRedirectRules(String tool, String chainVariable) { + StringBuilder script = new StringBuilder(); + List bypassInterfaces = parseInterfaceList(G.dnsHijackBypassInterfaces()); + List captureInterfaces = parseInterfaceList(G.dnsHijackCaptureInterfaces()); + for (String iface : bypassInterfaces) { + script.append(" ").append(tool).append(" -t nat -A \"") + .append(chainVariable).append("\" -i ") + .append(iface).append(" -j RETURN >> \"$LOG\" 2>&1\n"); + } + if (captureInterfaces.isEmpty()) { script.append(" ").append(tool).append(" -t nat -A \"") .append(chainVariable) .append("\" -p udp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n"); @@ -499,16 +628,16 @@ private static String buildBootOutputRedirectRules(String tool, String chainVari .append("\" -p tcp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n"); return script.toString(); } - for (Integer uid : captureUids) { - if (bypassUids.contains(uid)) { + for (String iface : captureInterfaces) { + if (bypassInterfaces.contains(iface)) { continue; } script.append(" ").append(tool).append(" -t nat -A \"") - .append(chainVariable).append("\" -p udp --dport 53 -m owner --uid-owner ") - .append(uid).append(" -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n"); + .append(chainVariable).append("\" -i ").append(iface) + .append(" -p udp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n"); script.append(" ").append(tool).append(" -t nat -A \"") - .append(chainVariable).append("\" -p tcp --dport 53 -m owner --uid-owner ") - .append(uid).append(" -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n"); + .append(chainVariable).append("\" -i ").append(iface) + .append(" -p tcp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n"); } script.append(" ").append(tool).append(" -t nat -A \"") .append(chainVariable).append("\" -j RETURN >> \"$LOG\" 2>&1\n"); @@ -547,6 +676,30 @@ private static List parseUidList(String raw) { return uids; } + private static List parseInterfaceList(String raw) { + List interfaces = new ArrayList<>(); + if (raw == null || raw.trim().isEmpty()) { + return interfaces; + } + String[] lines = raw.split("\\r?\\n"); + for (String line : lines) { + if (line == null) { + continue; + } + int comment = line.indexOf('#'); + String clean = comment >= 0 ? line.substring(0, comment) : line; + String[] tokens = clean.trim().split("[\\s,|]+"); + for (String token : tokens) { + String iface = token == null ? "" : token.trim(); + if (iface.matches("[A-Za-z0-9_.:-]{1,31}\\+?") + && !interfaces.contains(iface)) { + interfaces.add(iface); + } + } + } + return interfaces; + } + public static final class QueryEntry { public final long timestamp; public final String action; @@ -701,7 +854,7 @@ private static List buildRootRepairCommands(Context context) { List commands = new ArrayList<>(); File bootScript = new File(workDir(context), BOOT_SCRIPT); commands.add(shellQuote(supervisorPath(context)) + " start"); - logUidPolicy(context, "DNS per-app redirect policy repair queued"); + logRedirectPolicy(context, "DNS redirect policy repair queued"); appendRootRedirectRepairCommands(context, commands, false); if (G.enableIPv6()) { appendRootRedirectRepairCommands(context, commands, true); @@ -730,13 +883,15 @@ private static void appendRootRedirectRepairCommands(Context context, List commands, boolean ipv6) { commands.add("#NOCHK# -t nat -A " + chain + " -o lo -j RETURN"); commands.add("#NOCHK# -t nat -A " + chain + " -m owner --uid-owner 0 -j RETURN"); - if (!appendOutputUidPolicyRules(commands, "#NOCHK# -t nat -A " + chain, port)) { + if (!appendOutputPolicyRules(commands, "#NOCHK# -t nat -A " + chain, port)) { commands.add("#NOCHK# -t nat -A " + chain + " -p udp --dport 53 -j REDIRECT --to-ports " + port); commands.add("#NOCHK# -t nat -A " + chain + " -p tcp --dport 53 -j REDIRECT --to-ports " + port); } commands.add("#NOCHK# -t nat -A " + preChain + " -i lo -j RETURN"); - commands.add("#NOCHK# -t nat -A " + preChain + " -p udp --dport 53 -j REDIRECT --to-ports " + port); - commands.add("#NOCHK# -t nat -A " + preChain + " -p tcp --dport 53 -j REDIRECT --to-ports " + port); + if (!appendPreroutingPolicyRules(commands, "#NOCHK# -t nat -A " + preChain, port)) { + commands.add("#NOCHK# -t nat -A " + preChain + " -p udp --dport 53 -j REDIRECT --to-ports " + port); + commands.add("#NOCHK# -t nat -A " + preChain + " -p tcp --dport 53 -j REDIRECT --to-ports " + port); + } commands.add("#NOCHK# -t nat -I OUTPUT 1 -p udp --dport 53 -j " + chain); commands.add("#NOCHK# -t nat -I OUTPUT 1 -p tcp --dport 53 -j " + chain); @@ -931,8 +1088,7 @@ private static String buildBootScript(Context context, File dir) { + " ipt -t nat -A \"$CHAIN4\" -m owner --uid-owner 0 -j RETURN >> \"$LOG\" 2>&1\n" + buildBootOutputRedirectRules("ipt", "$CHAIN4") + " ipt -t nat -A \"$PRE4\" -i lo -j RETURN >> \"$LOG\" 2>&1\n" - + " ipt -t nat -A \"$PRE4\" -p udp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" - + " ipt -t nat -A \"$PRE4\" -p tcp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" + + buildBootPreroutingRedirectRules("ipt", "$PRE4") + " ipt -t nat -I OUTPUT 1 -p udp --dport 53 -j \"$CHAIN4\" >> \"$LOG\" 2>&1\n" + " ipt -t nat -I OUTPUT 1 -p tcp --dport 53 -j \"$CHAIN4\" >> \"$LOG\" 2>&1\n" + " ipt -t nat -I PREROUTING 1 -p udp --dport 53 -j \"$PRE4\" >> \"$LOG\" 2>&1\n" @@ -951,8 +1107,7 @@ private static String buildBootScript(Context context, File dir) { + " ip6t -t nat -A \"$CHAIN6\" -m owner --uid-owner 0 -j RETURN >> \"$LOG\" 2>&1\n" + buildBootOutputRedirectRules("ip6t", "$CHAIN6") + " ip6t -t nat -A \"$PRE6\" -i lo -j RETURN >> \"$LOG\" 2>&1\n" - + " ip6t -t nat -A \"$PRE6\" -p udp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" - + " ip6t -t nat -A \"$PRE6\" -p tcp --dport 53 -j REDIRECT --to-ports \"$PORT\" >> \"$LOG\" 2>&1\n" + + buildBootPreroutingRedirectRules("ip6t", "$PRE6") + " ip6t -t nat -I OUTPUT 1 -p udp --dport 53 -j \"$CHAIN6\" >> \"$LOG\" 2>&1\n" + " ip6t -t nat -I OUTPUT 1 -p tcp --dport 53 -j \"$CHAIN6\" >> \"$LOG\" 2>&1\n" + " ip6t -t nat -I PREROUTING 1 -p udp --dport 53 -j \"$PRE6\" >> \"$LOG\" 2>&1\n" diff --git a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java index 238faee22..9a1d750d1 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java +++ b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java @@ -512,6 +512,8 @@ private boolean isDnsHijackPreference(String key) { || key.equals("dnsHijackSplitUpstreams") || key.equals("dnsHijackCaptureUids") || key.equals("dnsHijackBypassUids") + || key.equals("dnsHijackCaptureInterfaces") + || key.equals("dnsHijackBypassInterfaces") || key.equals("dnsHijackFailOpen") || key.equals("dnsHijackStrictMode") || key.equals("dnsHijackBootPersistence") @@ -543,6 +545,8 @@ private boolean shouldReloadDnsHijackPreference(String key) { && !key.equals("dnsHijackBootPersistence") && !key.equals("dnsHijackCaptureUids") && !key.equals("dnsHijackBypassUids") + && !key.equals("dnsHijackCaptureInterfaces") + && !key.equals("dnsHijackBypassInterfaces") && !key.equals("dnsHijackBlocklistUrls") && !key.equals("dnsHijackScheduledBlocklistUpdates") && !key.equals("dnsHijackBlocklistUpdateIntervalHours"); diff --git a/app/src/main/java/dev/ukanth/ufirewall/util/G.java b/app/src/main/java/dev/ukanth/ufirewall/util/G.java index c8fd57cab..25a73aa0a 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/util/G.java +++ b/app/src/main/java/dev/ukanth/ufirewall/util/G.java @@ -177,6 +177,8 @@ public static Context getContext() { private static final String DNS_HIJACK_SPLIT_UPSTREAMS = "dnsHijackSplitUpstreams"; private static final String DNS_HIJACK_CAPTURE_UIDS = "dnsHijackCaptureUids"; private static final String DNS_HIJACK_BYPASS_UIDS = "dnsHijackBypassUids"; + private static final String DNS_HIJACK_CAPTURE_INTERFACES = "dnsHijackCaptureInterfaces"; + private static final String DNS_HIJACK_BYPASS_INTERFACES = "dnsHijackBypassInterfaces"; private static final String DNS_HIJACK_FAIL_OPEN = "dnsHijackFailOpen"; private static final String DNS_HIJACK_STRICT_MODE = "dnsHijackStrictMode"; private static final String DNS_HIJACK_BOOT_PERSISTENCE = "dnsHijackBootPersistence"; @@ -199,6 +201,8 @@ public static Context getContext() { DNS_HIJACK_SPLIT_UPSTREAMS, DNS_HIJACK_CAPTURE_UIDS, DNS_HIJACK_BYPASS_UIDS, + DNS_HIJACK_CAPTURE_INTERFACES, + DNS_HIJACK_BYPASS_INTERFACES, DNS_HIJACK_FAIL_OPEN, DNS_HIJACK_STRICT_MODE, DNS_HIJACK_TIMEOUT_MS, @@ -328,6 +332,14 @@ public static String dnsHijackBypassUids() { return dnsPolicyPrefs().getString(DNS_HIJACK_BYPASS_UIDS, ""); } + public static String dnsHijackCaptureInterfaces() { + return dnsPolicyPrefs().getString(DNS_HIJACK_CAPTURE_INTERFACES, ""); + } + + public static String dnsHijackBypassInterfaces() { + return dnsPolicyPrefs().getString(DNS_HIJACK_BYPASS_INTERFACES, ""); + } + public static boolean dnsHijackFailOpen() { return dnsPolicyPrefs().getBoolean(DNS_HIJACK_FAIL_OPEN, true); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2e7339f2d..b26824861 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -314,6 +314,10 @@ Optional app UID list. When set, only listed UIDs are redirected through DNS filtering. Bypass DNS capture for UIDs Optional app UID list that keeps matching apps on the normal resolver path. + Limit DNS capture to interfaces + Optional network interface patterns to capture, such as wlan+, rmnet+, or tun+. When set, other interfaces bypass DNS filtering. + Bypass DNS capture on interfaces + Optional network interface patterns that should use the normal resolver path. Fail open Allow upstream DNS when filtering cannot complete instead of blocking the query. Strict allow/block priority diff --git a/app/src/main/res/xml/rules_preferences.xml b/app/src/main/res/xml/rules_preferences.xml index 88e13aab8..176cf7524 100644 --- a/app/src/main/res/xml/rules_preferences.xml +++ b/app/src/main/res/xml/rules_preferences.xml @@ -115,6 +115,18 @@ android:summary="@string/dns_hijack_bypass_uids_summary" android:title="@string/dns_hijack_bypass_uids_title" /> + + + + Date: Fri, 26 Jun 2026 15:25:45 -0700 Subject: [PATCH 017/108] Add configurable DNS cache size --- .../main/assets/dnsd/arm64-v8a/afwall_dnsd | Bin 27144 -> 27480 bytes .../main/assets/dnsd/armeabi-v7a/afwall_dnsd | Bin 21820 -> 22604 bytes app/src/main/assets/dnsd/x86/afwall_dnsd | Bin 27712 -> 28304 bytes app/src/main/assets/dnsd/x86_64/afwall_dnsd | Bin 28608 -> 29136 bytes .../ufirewall/dns/DnsHijackManager.java | 2 + .../preferences/RulesPreferenceFragment.java | 1 + .../java/dev/ukanth/ufirewall/util/G.java | 6 ++ app/src/main/res/values/strings.xml | 2 + app/src/main/res/xml/rules_preferences.xml | 7 ++ dnsdaemon/jni/afwall_dnsd.c | 60 ++++++++++++++---- 10 files changed, 65 insertions(+), 13 deletions(-) diff --git a/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd b/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd index 107e4b3121f6387bc9a117a0370d6bde53bda89a..f949b3940b27aee86978fe2823b73b646f4e5ffa 100755 GIT binary patch delta 12699 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�h0V7eSj71}?R_CNilVdrg`dgG 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 Txkqo}Nli9=Aj0uE5bJ*diNpEm diff --git a/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd b/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd index 255287325b5091a0b711eafd588c9e43cc61fd32..bbedbe4716a9ae78c52c76a4d8ff817d56518fe9 100755 GIT binary patch delta 11838 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 diff --git a/app/src/main/assets/dnsd/x86/afwall_dnsd b/app/src/main/assets/dnsd/x86/afwall_dnsd index 9d0b73599daaeb604a0ad0debfacf4505661ee86..3d2593ad8762f8a5f4b3c81cae60fbe668a6d21b 100755 GIT binary patch delta 14702 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 diff --git a/app/src/main/assets/dnsd/x86_64/afwall_dnsd b/app/src/main/assets/dnsd/x86_64/afwall_dnsd index 5a9f039ab94d20516c015017b8e1f20d01535116..96192f8ea4c5094400358f5aa914f8ea0db67616 100755 GIT binary patch delta 14336 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 orB##)DR4(6tx2J0 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 diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java index 43fb27b03..7e0041c25 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java @@ -172,6 +172,7 @@ public static String collectLocalDiagnostics(Context context) { out.append("fail_open=").append(G.dnsHijackFailOpen()).append('\n'); out.append("strict_mode=").append(G.dnsHijackStrictMode()).append('\n'); out.append("timeout_ms=").append(G.dnsHijackTimeoutMs()).append('\n'); + out.append("cache_size=").append(G.dnsHijackCacheSize()).append('\n'); out.append("split_upstream_entries=").append(countLines(G.dnsHijackSplitUpstreams())).append('\n'); out.append("capture_uid_entries=").append(parseUidList(G.dnsHijackCaptureUids()).size()).append('\n'); out.append("bypass_uid_entries=").append(parseUidList(G.dnsHijackBypassUids()).size()).append('\n'); @@ -1011,6 +1012,7 @@ private static String buildConfig(Context context) { config.append("fail_open=").append(G.dnsHijackFailOpen() ? "1" : "0").append('\n'); config.append("strict_mode=").append(G.dnsHijackStrictMode() ? "1" : "0").append('\n'); config.append("timeout_ms=").append(G.dnsHijackTimeoutMs()).append('\n'); + config.append("cache_size=").append(G.dnsHijackCacheSize()).append('\n'); appendConfigEntries(config, "upstream", G.dnsHijackUpstreams()); appendConfigEntries(config, "split_upstream", G.dnsHijackSplitUpstreams()); diff --git a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java index 9a1d750d1..724d3464a 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java +++ b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java @@ -518,6 +518,7 @@ private boolean isDnsHijackPreference(String key) { || key.equals("dnsHijackStrictMode") || key.equals("dnsHijackBootPersistence") || key.equals("dnsHijackTimeoutMs") + || key.equals("dnsHijackCacheSize") || key.equals("dnsHijackAllowExact") || key.equals("dnsHijackAllowSuffix") || key.equals("dnsHijackBlockExact") diff --git a/app/src/main/java/dev/ukanth/ufirewall/util/G.java b/app/src/main/java/dev/ukanth/ufirewall/util/G.java index 25a73aa0a..816a8d11b 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/util/G.java +++ b/app/src/main/java/dev/ukanth/ufirewall/util/G.java @@ -183,6 +183,7 @@ public static Context getContext() { private static final String DNS_HIJACK_STRICT_MODE = "dnsHijackStrictMode"; private static final String DNS_HIJACK_BOOT_PERSISTENCE = "dnsHijackBootPersistence"; private static final String DNS_HIJACK_TIMEOUT_MS = "dnsHijackTimeoutMs"; + private static final String DNS_HIJACK_CACHE_SIZE = "dnsHijackCacheSize"; private static final String DNS_HIJACK_ALLOW_EXACT = "dnsHijackAllowExact"; private static final String DNS_HIJACK_ALLOW_SUFFIX = "dnsHijackAllowSuffix"; private static final String DNS_HIJACK_BLOCK_EXACT = "dnsHijackBlockExact"; @@ -206,6 +207,7 @@ public static Context getContext() { DNS_HIJACK_FAIL_OPEN, DNS_HIJACK_STRICT_MODE, DNS_HIJACK_TIMEOUT_MS, + DNS_HIJACK_CACHE_SIZE, DNS_HIJACK_ALLOW_EXACT, DNS_HIJACK_ALLOW_SUFFIX, DNS_HIJACK_BLOCK_EXACT, @@ -361,6 +363,10 @@ public static int dnsHijackTimeoutMs() { return readIntPreference(dnsPolicyPrefs(), DNS_HIJACK_TIMEOUT_MS, 2500, 250, 10000); } + public static int dnsHijackCacheSize() { + return readIntPreference(dnsPolicyPrefs(), DNS_HIJACK_CACHE_SIZE, 1024, 0, 4096); + } + public static String dnsHijackAllowExact() { return dnsPolicyPrefs().getString(DNS_HIJACK_ALLOW_EXACT, ""); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b26824861..f4e572ff8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -326,6 +326,8 @@ Install a root boot script that restarts the DNS daemon and restores DNS redirect rules before opening the app. Upstream timeout DNS upstream timeout in milliseconds. + DNS cache size + Maximum daemon DNS cache entries. Use 0 to disable caching; maximum is 4096. Use active profile DNS policy When enabled, saved DNS settings and compiled blocklists follow the active firewall profile. Save DNS policy to active profile diff --git a/app/src/main/res/xml/rules_preferences.xml b/app/src/main/res/xml/rules_preferences.xml index 176cf7524..8d5ff28e7 100644 --- a/app/src/main/res/xml/rules_preferences.xml +++ b/app/src/main/res/xml/rules_preferences.xml @@ -155,6 +155,13 @@ android:summary="@string/dns_hijack_timeout_summary" android:title="@string/dns_hijack_timeout_title" /> + + now) { count++; } @@ -634,11 +640,17 @@ static uint32_t extract_min_ttl(const uint8_t *packet, size_t len) { static bool cache_lookup(const char *domain, uint16_t qtype, const uint8_t *query, uint8_t *out, size_t *out_len) { uint32_t h = hash_domain(domain, qtype); - uint32_t start = h % CACHE_SIZE; + uint32_t start; uint32_t i; + uint32_t probe_count; time_t now = time(NULL); - for (i = 0; i < 8; i++) { - cache_entry_t *entry = &g_cache[(start + i) % CACHE_SIZE]; + if (g_cache == NULL || g_cache_capacity <= 0) { + return false; + } + start = h % (uint32_t) g_cache_capacity; + probe_count = g_cache_capacity < 8 ? (uint32_t) g_cache_capacity : 8u; + for (i = 0; i < probe_count; i++) { + cache_entry_t *entry = &g_cache[(start + i) % (uint32_t) g_cache_capacity]; if (!entry->used) { continue; } @@ -678,9 +690,12 @@ static void cache_store(const char *domain, uint16_t qtype, const uint8_t *respo uint32_t ttl; cache_entry_t *entry; uint32_t i; + uint32_t probe_count; time_t now = time(NULL); bool evicting = false; - if (response_len < 12 || response_len > MAX_PACKET || !response_cacheable(response, response_len)) { + if (g_cache == NULL || g_cache_capacity <= 0 + || response_len < 12 || response_len > MAX_PACKET + || !response_cacheable(response, response_len)) { return; } ttl = extract_min_ttl(response, response_len); @@ -688,10 +703,11 @@ static void cache_store(const char *domain, uint16_t qtype, const uint8_t *respo return; } h = hash_domain(domain, qtype); - slot = h % CACHE_SIZE; + slot = h % (uint32_t) g_cache_capacity; + probe_count = g_cache_capacity < 8 ? (uint32_t) g_cache_capacity : 8u; entry = NULL; - for (i = 0; i < 8; i++) { - cache_entry_t *candidate = &g_cache[(slot + i) % CACHE_SIZE]; + for (i = 0; i < probe_count; i++) { + cache_entry_t *candidate = &g_cache[(slot + i) % (uint32_t) g_cache_capacity]; if (candidate->used && candidate->hash == h && candidate->qtype == qtype && strcmp(candidate->domain, domain) == 0) { @@ -918,6 +934,7 @@ static void default_config(config_t *cfg) { cfg->listen_port = DEFAULT_PORT; cfg->fail_open = 1; cfg->timeout_ms = DEFAULT_TIMEOUT_MS; + cfg->cache_size = DEFAULT_CACHE_SIZE; safe_copy(cfg->control_socket, sizeof(cfg->control_socket), "/data/local/tmp/afwall_dnsd.sock"); cfg->upstream_count = 1; safe_copy(cfg->upstreams[0].host, sizeof(cfg->upstreams[0].host), "1.1.1.1"); @@ -1053,6 +1070,11 @@ static bool load_config(const char *path, config_t *new_cfg) { if (timeout >= 250 && timeout <= 10000) { new_cfg->timeout_ms = timeout; } + } else if (strcmp(key, "cache_size") == 0) { + int cache_size = atoi(value); + if (cache_size >= 0 && cache_size <= MAX_CACHE_SIZE) { + new_cfg->cache_size = cache_size; + } } else if (strcmp(key, "upstream") == 0) { parse_upstream(new_cfg, value); } else if (strcmp(key, "split_upstream") == 0) { @@ -1139,6 +1161,7 @@ static void load_regex_rule_file(regex_rule_t *rules, int *count, const char *pa static bool reload_config(void) { config_t *next = (config_t *) calloc(1, sizeof(config_t)); + cache_entry_t *next_cache = NULL; if (next == NULL) { return false; } @@ -1146,10 +1169,20 @@ static bool reload_config(void) { free(next); return false; } + if (next->cache_size > 0) { + next_cache = (cache_entry_t *) calloc((size_t) next->cache_size, sizeof(cache_entry_t)); + if (next_cache == NULL) { + free_regex_rules(next); + free(next); + return false; + } + } free_regex_rules(&g_cfg); g_cfg = *next; free(next); - memset(g_cache, 0, sizeof(g_cache)); + free(g_cache); + g_cache = next_cache; + g_cache_capacity = g_cfg.cache_size; g_stats.reloads++; return true; } @@ -1449,7 +1482,7 @@ static void write_health_response(int client) { "health=1\nrunning=1\npid=%ld\nuptime=%llu\nlisten_port=%d\n" "generation=%llu\nupstreams=%d\nsplit_upstreams=%d\nupstream_probe=%s\n" "upstream_probe_ms=%d\nupstream_probe_index=%d\nupstream_probe_rcode=%d\n" - "queries=%llu\nblocked=%llu\nallowed=%llu\ncache_entries=%d\n" + "queries=%llu\nblocked=%llu\nallowed=%llu\ncache_size=%d\ncache_entries=%d\n" "rules_total=%d\n", (long) getpid(), (unsigned long long) (now_seconds() - g_stats.start_time), @@ -1464,6 +1497,7 @@ static void write_health_response(int client) { (unsigned long long) g_stats.queries, (unsigned long long) g_stats.blocked, (unsigned long long) g_stats.allowed, + g_cfg.cache_size, cache_entry_count(), g_cfg.exact_allow_count + g_cfg.suffix_allow_count + g_cfg.exact_block_count + g_cfg.suffix_block_count @@ -1554,7 +1588,7 @@ static void handle_control(int fd) { (unsigned long long) g_stats.blocked, (unsigned long long) g_stats.fail_open_drops, (unsigned long long) g_stats.fail_closed_blocks, - CACHE_SIZE, + g_cfg.cache_size, cache_entry_count(), (unsigned long long) g_stats.cache_hits, (unsigned long long) g_stats.cache_misses, From 8e81ebbc02ccba7802328e95e49812235e757c68 Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 15:30:28 -0700 Subject: [PATCH 018/108] Index exact DNS rules in daemon --- .../main/assets/dnsd/arm64-v8a/afwall_dnsd | Bin 27480 -> 28376 bytes .../main/assets/dnsd/armeabi-v7a/afwall_dnsd | Bin 22604 -> 23340 bytes app/src/main/assets/dnsd/x86/afwall_dnsd | Bin 28304 -> 29184 bytes app/src/main/assets/dnsd/x86_64/afwall_dnsd | Bin 29136 -> 30224 bytes dnsdaemon/jni/afwall_dnsd.c | 58 ++++++++++++++++-- 5 files changed, 53 insertions(+), 5 deletions(-) diff --git a/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd b/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd index f949b3940b27aee86978fe2823b73b646f4e5ffa..898fd59469f3d00c34adc1fce3979c29db42c82e 100755 GIT binary patch delta 13306 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 delta 12477 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 Pd#Y;kG6??3t=Inp%>I|v delta 10466 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 diff --git a/app/src/main/assets/dnsd/x86/afwall_dnsd b/app/src/main/assets/dnsd/x86/afwall_dnsd index 3d2593ad8762f8a5f4b3c81cae60fbe668a6d21b..e70201d65dc49b583091c9290a1ab5f59a00db82 100755 GIT binary patch delta 12844 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 delta 12011 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 diff --git a/app/src/main/assets/dnsd/x86_64/afwall_dnsd b/app/src/main/assets/dnsd/x86_64/afwall_dnsd index 96192f8ea4c5094400358f5aa914f8ea0db67616..2f7e8e970363166197ff326fac0d45e508e27f41 100755 GIT binary patch delta 13246 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 D&H-bn delta 12174 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 diff --git a/dnsdaemon/jni/afwall_dnsd.c b/dnsdaemon/jni/afwall_dnsd.c index 02e76da67..b98fba8da 100644 --- a/dnsdaemon/jni/afwall_dnsd.c +++ b/dnsdaemon/jni/afwall_dnsd.c @@ -32,6 +32,7 @@ #define MAX_PACKET 4096 #define MAX_DOMAIN 256 #define MAX_RULES 32768 +#define EXACT_INDEX_SIZE 65536 #define MAX_REGEX 128 #define MAX_TEMP_RULES 1024 #define MAX_UPSTREAMS 8 @@ -89,6 +90,8 @@ typedef struct { string_rule_t suffix_allow[MAX_RULES]; string_rule_t exact_block[MAX_RULES]; string_rule_t suffix_block[MAX_RULES]; + int exact_allow_index[EXACT_INDEX_SIZE]; + int exact_block_index[EXACT_INDEX_SIZE]; int exact_allow_count; int suffix_allow_count; int exact_block_count; @@ -394,12 +397,47 @@ static bool add_regex_rule(regex_rule_t *rules, int *count, const char *value) { return true; } -static bool exact_match(const string_rule_t *rules, int count, const char *domain) { +static bool build_exact_index(const string_rule_t *rules, int count, int *index) { int i; + memset(index, 0, sizeof(int) * EXACT_INDEX_SIZE); for (i = 0; i < count; i++) { - if (strcmp(rules[i].value, domain) == 0) { + uint32_t slot = hash_domain(rules[i].value, 0) % EXACT_INDEX_SIZE; + uint32_t probe; + for (probe = 0; probe < EXACT_INDEX_SIZE; probe++) { + int existing = index[slot]; + if (existing == 0) { + index[slot] = i + 1; + break; + } + if (existing > 0 && existing <= count + && strcmp(rules[existing - 1].value, rules[i].value) == 0) { + break; + } + slot = (slot + 1) % EXACT_INDEX_SIZE; + } + if (probe == EXACT_INDEX_SIZE) { + return false; + } + } + return true; +} + +static bool exact_match_indexed(const string_rule_t *rules, const int *index, const char *domain) { + uint32_t slot; + uint32_t probe; + if (domain == NULL || domain[0] == '\0') { + return false; + } + slot = hash_domain(domain, 0) % EXACT_INDEX_SIZE; + for (probe = 0; probe < EXACT_INDEX_SIZE; probe++) { + int ref = index[slot]; + if (ref == 0) { + return false; + } + if (ref > 0 && ref <= MAX_RULES && strcmp(rules[ref - 1].value, domain) == 0) { return true; } + slot = (slot + 1) % EXACT_INDEX_SIZE; } return false; } @@ -457,7 +495,7 @@ static bool regex_match_rules(const regex_rule_t *rules, int count, const char * static decision_t evaluate_domain(const config_t *cfg, const char *domain, const char **reason) { uint64_t now = now_seconds(); bool temp_allow = temp_match(cfg->temp_allow, cfg->temp_allow_count, domain, now); - bool exact_allow = exact_match(cfg->exact_allow, cfg->exact_allow_count, domain); + bool exact_allow = exact_match_indexed(cfg->exact_allow, cfg->exact_allow_index, domain); bool suffix_allow = suffix_match(cfg->suffix_allow, cfg->suffix_allow_count, domain); bool regex_allow = regex_match_rules(cfg->regex_allow, cfg->regex_allow_count, domain); bool block = false; @@ -465,7 +503,7 @@ static decision_t evaluate_domain(const config_t *cfg, const char *domain, const if (temp_match(cfg->temp_block, cfg->temp_block_count, domain, now)) { *reason = "temp_block"; block = true; - } else if (exact_match(cfg->exact_block, cfg->exact_block_count, domain)) { + } else if (exact_match_indexed(cfg->exact_block, cfg->exact_block_index, domain)) { *reason = "exact_block"; block = true; } else if (suffix_match(cfg->suffix_block, cfg->suffix_block_count, domain)) { @@ -1115,6 +1153,12 @@ static bool load_config(const char *path, config_t *new_cfg) { new_cfg->upstreams[0].port = 53; new_cfg->upstream_count = 1; } + if (!build_exact_index(new_cfg->exact_allow, new_cfg->exact_allow_count, + new_cfg->exact_allow_index) + || !build_exact_index(new_cfg->exact_block, new_cfg->exact_block_count, + new_cfg->exact_block_index)) { + return false; + } new_cfg->generation = g_cfg.generation + 1; return true; } @@ -1166,6 +1210,7 @@ static bool reload_config(void) { return false; } if (!load_config(g_config_path, next)) { + free_regex_rules(next); free(next); return false; } @@ -1483,6 +1528,7 @@ static void write_health_response(int client) { "generation=%llu\nupstreams=%d\nsplit_upstreams=%d\nupstream_probe=%s\n" "upstream_probe_ms=%d\nupstream_probe_index=%d\nupstream_probe_rcode=%d\n" "queries=%llu\nblocked=%llu\nallowed=%llu\ncache_size=%d\ncache_entries=%d\n" + "exact_index_size=%d\n" "rules_total=%d\n", (long) getpid(), (unsigned long long) (now_seconds() - g_stats.start_time), @@ -1499,6 +1545,7 @@ static void write_health_response(int client) { (unsigned long long) g_stats.allowed, g_cfg.cache_size, cache_entry_count(), + EXACT_INDEX_SIZE, g_cfg.exact_allow_count + g_cfg.suffix_allow_count + g_cfg.exact_block_count + g_cfg.suffix_block_count + g_cfg.regex_allow_count + g_cfg.regex_block_count @@ -1574,7 +1621,7 @@ static void handle_control(int fd) { "cache_hit_rate_ppm=%llu\ncache_stores=%llu\ncache_expired=%llu\ncache_evictions=%llu\n" "upstream_requests=%llu\nupstream_successes=%llu\nupstream_failures=%llu\n" "avg_latency_ms=%llu\nmax_latency_ms=%llu\nupstream_avg_latency_ms=%llu\n" - "reloads=%llu\nrules_exact_allow=%d\nrules_suffix_allow=%d\nrules_exact_block=%d\n" + "reloads=%llu\nexact_index_size=%d\nrules_exact_allow=%d\nrules_suffix_allow=%d\nrules_exact_block=%d\n" "rules_suffix_block=%d\nrules_regex_allow=%d\nrules_regex_block=%d\n" "rules_temp_allow=%d\nrules_temp_block=%d\nsplit_upstreams=%d\n", (long) getpid(), @@ -1604,6 +1651,7 @@ static void handle_control(int fd) { (unsigned long long) g_stats.max_latency_ms, (unsigned long long) div_u64(g_stats.upstream_latency_ms, g_stats.upstream_requests), (unsigned long long) g_stats.reloads, + EXACT_INDEX_SIZE, g_cfg.exact_allow_count, g_cfg.suffix_allow_count, g_cfg.exact_block_count, From df19908f852ebcec5bb0d847261bceadda2cd864 Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 15:38:22 -0700 Subject: [PATCH 019/108] Add suffix trie DNS rule lookup --- .../main/assets/dnsd/arm64-v8a/afwall_dnsd | Bin 28376 -> 29248 bytes .../main/assets/dnsd/armeabi-v7a/afwall_dnsd | Bin 23340 -> 24016 bytes app/src/main/assets/dnsd/x86/afwall_dnsd | Bin 29184 -> 29828 bytes app/src/main/assets/dnsd/x86_64/afwall_dnsd | Bin 30224 -> 31264 bytes dnsdaemon/jni/afwall_dnsd.c | 223 ++++++++++++++++-- 5 files changed, 207 insertions(+), 16 deletions(-) diff --git a/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd b/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd index 898fd59469f3d00c34adc1fce3979c29db42c82e..be85cf0e98f1b3de97b049f1546915e2d01ddc38 100755 GIT binary patch literal 29248 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 SMH4He+-GVao|SqE_^&(f13KcPnR?}3Ea20S@ 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 diff --git a/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd b/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd index 7d2b5fd3e64c8e2b0224371ff1c1788351fba7fe..7d3bd2ae4345f9e95b2a67177b71a7d975b4f2c3 100755 GIT binary patch delta 14365 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 UJXh(Ex|fZQ@HsG0_M5E#0kD&qbpQYW delta 13711 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 L8#f>Jz_9-Vg6WNF diff --git a/app/src/main/assets/dnsd/x86/afwall_dnsd b/app/src/main/assets/dnsd/x86/afwall_dnsd index e70201d65dc49b583091c9290a1ab5f59a00db82..05b87788efcd9cd7858ca6145bb4e9a7578feae8 100755 GIT binary patch literal 29828 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 literal 29184 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 V-Ep`vmX{{tVkxTgRB diff --git a/app/src/main/assets/dnsd/x86_64/afwall_dnsd b/app/src/main/assets/dnsd/x86_64/afwall_dnsd index 2f7e8e970363166197ff326fac0d45e508e27f41..6ef318c787fcf5773fb025f40610b7cbfab985e7 100755 GIT binary patch literal 31264 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 K2%Gs#^8W+jeME5p literal 30224 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 Qk7l%gBp!*pSt<8 diff --git a/dnsdaemon/jni/afwall_dnsd.c b/dnsdaemon/jni/afwall_dnsd.c index b98fba8da..c2ab37532 100644 --- a/dnsdaemon/jni/afwall_dnsd.c +++ b/dnsdaemon/jni/afwall_dnsd.c @@ -31,6 +31,7 @@ #define MAX_PACKET 4096 #define MAX_DOMAIN 256 +#define MAX_LABEL 64 #define MAX_RULES 32768 #define EXACT_INDEX_SIZE 65536 #define MAX_REGEX 128 @@ -73,6 +74,19 @@ typedef struct { upstream_t upstream; } split_upstream_t; +typedef struct { + char label[MAX_LABEL]; + int first_child; + int next_sibling; + bool terminal; +} suffix_trie_node_t; + +typedef struct { + suffix_trie_node_t *nodes; + int count; + int capacity; +} suffix_trie_t; + typedef struct { int listen_port; int strict_mode; @@ -92,6 +106,8 @@ typedef struct { string_rule_t suffix_block[MAX_RULES]; int exact_allow_index[EXACT_INDEX_SIZE]; int exact_block_index[EXACT_INDEX_SIZE]; + suffix_trie_t suffix_allow_trie; + suffix_trie_t suffix_block_trie; int exact_allow_count; int suffix_allow_count; int exact_block_count; @@ -313,6 +329,25 @@ static void free_regex_rules(config_t *cfg) { } } +static void free_suffix_trie(suffix_trie_t *trie) { + if (trie == NULL) { + return; + } + free(trie->nodes); + trie->nodes = NULL; + trie->count = 0; + trie->capacity = 0; +} + +static void free_config_dynamic(config_t *cfg) { + if (cfg == NULL) { + return; + } + free_regex_rules(cfg); + free_suffix_trie(&cfg->suffix_allow_trie); + free_suffix_trie(&cfg->suffix_block_trie); +} + static bool add_string_rule(string_rule_t *rules, int *count, const char *value) { if (*count >= MAX_RULES || value == NULL || value[0] == '\0') { return false; @@ -442,29 +477,176 @@ static bool exact_match_indexed(const string_rule_t *rules, const int *index, co return false; } -static bool temp_match(const temp_rule_t *rules, int count, const char *domain, uint64_t now) { +static bool suffix_trie_reserve(suffix_trie_t *trie, int needed) { + int next_capacity; + suffix_trie_node_t *nodes; + if (trie->capacity >= needed) { + return true; + } + next_capacity = trie->capacity > 0 ? trie->capacity : 64; + while (next_capacity < needed) { + if (next_capacity > MAX_RULES * 8) { + next_capacity = needed; + break; + } + next_capacity *= 2; + } + nodes = (suffix_trie_node_t *) realloc(trie->nodes, + (size_t) next_capacity * sizeof(suffix_trie_node_t)); + if (nodes == NULL) { + return false; + } + memset(nodes + trie->capacity, 0, + (size_t) (next_capacity - trie->capacity) * sizeof(suffix_trie_node_t)); + trie->nodes = nodes; + trie->capacity = next_capacity; + return true; +} + +static bool suffix_trie_init(suffix_trie_t *trie) { + memset(trie, 0, sizeof(*trie)); + if (!suffix_trie_reserve(trie, 1)) { + return false; + } + trie->count = 1; + return true; +} + +static int suffix_trie_find_child(const suffix_trie_t *trie, int parent, const char *label) { + int child; + if (trie == NULL || trie->nodes == NULL || parent < 0 || parent >= trie->count) { + return -1; + } + for (child = trie->nodes[parent].first_child; child != 0; + child = trie->nodes[child].next_sibling) { + if (strcmp(trie->nodes[child].label, label) == 0) { + return child; + } + } + return -1; +} + +static int suffix_trie_add_child(suffix_trie_t *trie, int parent, const char *label) { + int child; + if (!suffix_trie_reserve(trie, trie->count + 1)) { + return -1; + } + child = trie->count++; + memset(&trie->nodes[child], 0, sizeof(trie->nodes[child])); + safe_copy(trie->nodes[child].label, sizeof(trie->nodes[child].label), label); + trie->nodes[child].next_sibling = trie->nodes[parent].first_child; + trie->nodes[parent].first_child = child; + return child; +} + +static bool previous_domain_label(const char *domain, size_t *end, char *label, + size_t label_len, bool *done) { + size_t start; + size_t len; + if (domain == NULL || end == NULL || *end == 0 || label == NULL || label_len == 0) { + return false; + } + start = *end; + while (start > 0 && domain[start - 1] != '.') { + start--; + } + len = *end - start; + if (len == 0 || len >= label_len) { + return false; + } + memcpy(label, domain + start, len); + label[len] = '\0'; + if (start == 0) { + *done = true; + *end = 0; + } else { + *done = false; + *end = start - 1; + } + return true; +} + +static bool suffix_trie_insert(suffix_trie_t *trie, const char *suffix) { + char label[MAX_LABEL]; + size_t end; + int node = 0; + bool done = false; + if (trie == NULL || trie->nodes == NULL || suffix == NULL || suffix[0] == '\0') { + return false; + } + end = strlen(suffix); + while (!done) { + int child; + if (!previous_domain_label(suffix, &end, label, sizeof(label), &done)) { + return false; + } + child = suffix_trie_find_child(trie, node, label); + if (child < 0) { + child = suffix_trie_add_child(trie, node, label); + if (child < 0) { + return false; + } + } + node = child; + } + trie->nodes[node].terminal = true; + return true; +} + +static bool build_suffix_trie(const string_rule_t *rules, int count, suffix_trie_t *trie) { int i; + free_suffix_trie(trie); + if (!suffix_trie_init(trie)) { + return false; + } for (i = 0; i < count; i++) { - if (rules[i].expires_at > now && strcmp(rules[i].value, domain) == 0) { + if (!suffix_trie_insert(trie, rules[i].value)) { + free_suffix_trie(trie); + return false; + } + } + return true; +} + +static bool suffix_trie_match(const suffix_trie_t *trie, const char *domain) { + char label[MAX_LABEL]; + size_t end; + int node = 0; + bool done = false; + if (trie == NULL || trie->nodes == NULL || domain == NULL || domain[0] == '\0') { + return false; + } + end = strlen(domain); + /* Suffix rules used to scan linearly; this keeps the DNS hot path bounded by label depth. */ + while (!done) { + int child; + if (!previous_domain_label(domain, &end, label, sizeof(label), &done)) { + return false; + } + child = suffix_trie_find_child(trie, node, label); + if (child < 0) { + return false; + } + node = child; + if (trie->nodes[node].terminal) { return true; } } return false; } -static bool domain_has_suffix(const char *domain, const char *suffix); - -static bool suffix_match(const string_rule_t *rules, int count, const char *domain) { +static bool temp_match(const temp_rule_t *rules, int count, const char *domain, uint64_t now) { int i; for (i = 0; i < count; i++) { - const char *suffix = rules[i].value; - if (domain_has_suffix(domain, suffix)) { + if (rules[i].expires_at > now && strcmp(rules[i].value, domain) == 0) { return true; } } return false; } +static bool domain_has_suffix(const char *domain, const char *suffix); + static bool domain_has_suffix(const char *domain, const char *suffix) { size_t domain_len; size_t suffix_len; @@ -496,7 +678,7 @@ static decision_t evaluate_domain(const config_t *cfg, const char *domain, const uint64_t now = now_seconds(); bool temp_allow = temp_match(cfg->temp_allow, cfg->temp_allow_count, domain, now); bool exact_allow = exact_match_indexed(cfg->exact_allow, cfg->exact_allow_index, domain); - bool suffix_allow = suffix_match(cfg->suffix_allow, cfg->suffix_allow_count, domain); + bool suffix_allow = suffix_trie_match(&cfg->suffix_allow_trie, domain); bool regex_allow = regex_match_rules(cfg->regex_allow, cfg->regex_allow_count, domain); bool block = false; @@ -506,7 +688,7 @@ static decision_t evaluate_domain(const config_t *cfg, const char *domain, const } else if (exact_match_indexed(cfg->exact_block, cfg->exact_block_index, domain)) { *reason = "exact_block"; block = true; - } else if (suffix_match(cfg->suffix_block, cfg->suffix_block_count, domain)) { + } else if (suffix_trie_match(&cfg->suffix_block_trie, domain)) { *reason = "suffix_block"; block = true; } else if (regex_match_rules(cfg->regex_block, cfg->regex_block_count, domain)) { @@ -1156,7 +1338,11 @@ static bool load_config(const char *path, config_t *new_cfg) { if (!build_exact_index(new_cfg->exact_allow, new_cfg->exact_allow_count, new_cfg->exact_allow_index) || !build_exact_index(new_cfg->exact_block, new_cfg->exact_block_count, - new_cfg->exact_block_index)) { + new_cfg->exact_block_index) + || !build_suffix_trie(new_cfg->suffix_allow, new_cfg->suffix_allow_count, + &new_cfg->suffix_allow_trie) + || !build_suffix_trie(new_cfg->suffix_block, new_cfg->suffix_block_count, + &new_cfg->suffix_block_trie)) { return false; } new_cfg->generation = g_cfg.generation + 1; @@ -1210,19 +1396,19 @@ static bool reload_config(void) { return false; } if (!load_config(g_config_path, next)) { - free_regex_rules(next); + free_config_dynamic(next); free(next); return false; } if (next->cache_size > 0) { next_cache = (cache_entry_t *) calloc((size_t) next->cache_size, sizeof(cache_entry_t)); if (next_cache == NULL) { - free_regex_rules(next); + free_config_dynamic(next); free(next); return false; } } - free_regex_rules(&g_cfg); + free_config_dynamic(&g_cfg); g_cfg = *next; free(next); free(g_cache); @@ -1528,7 +1714,7 @@ static void write_health_response(int client) { "generation=%llu\nupstreams=%d\nsplit_upstreams=%d\nupstream_probe=%s\n" "upstream_probe_ms=%d\nupstream_probe_index=%d\nupstream_probe_rcode=%d\n" "queries=%llu\nblocked=%llu\nallowed=%llu\ncache_size=%d\ncache_entries=%d\n" - "exact_index_size=%d\n" + "exact_index_size=%d\nsuffix_allow_trie_nodes=%d\nsuffix_block_trie_nodes=%d\n" "rules_total=%d\n", (long) getpid(), (unsigned long long) (now_seconds() - g_stats.start_time), @@ -1546,6 +1732,8 @@ static void write_health_response(int client) { g_cfg.cache_size, cache_entry_count(), EXACT_INDEX_SIZE, + g_cfg.suffix_allow_trie.count, + g_cfg.suffix_block_trie.count, g_cfg.exact_allow_count + g_cfg.suffix_allow_count + g_cfg.exact_block_count + g_cfg.suffix_block_count + g_cfg.regex_allow_count + g_cfg.regex_block_count @@ -1621,7 +1809,8 @@ static void handle_control(int fd) { "cache_hit_rate_ppm=%llu\ncache_stores=%llu\ncache_expired=%llu\ncache_evictions=%llu\n" "upstream_requests=%llu\nupstream_successes=%llu\nupstream_failures=%llu\n" "avg_latency_ms=%llu\nmax_latency_ms=%llu\nupstream_avg_latency_ms=%llu\n" - "reloads=%llu\nexact_index_size=%d\nrules_exact_allow=%d\nrules_suffix_allow=%d\nrules_exact_block=%d\n" + "reloads=%llu\nexact_index_size=%d\nsuffix_allow_trie_nodes=%d\n" + "suffix_block_trie_nodes=%d\nrules_exact_allow=%d\nrules_suffix_allow=%d\nrules_exact_block=%d\n" "rules_suffix_block=%d\nrules_regex_allow=%d\nrules_regex_block=%d\n" "rules_temp_allow=%d\nrules_temp_block=%d\nsplit_upstreams=%d\n", (long) getpid(), @@ -1652,6 +1841,8 @@ static void handle_control(int fd) { (unsigned long long) div_u64(g_stats.upstream_latency_ms, g_stats.upstream_requests), (unsigned long long) g_stats.reloads, EXACT_INDEX_SIZE, + g_cfg.suffix_allow_trie.count, + g_cfg.suffix_block_trie.count, g_cfg.exact_allow_count, g_cfg.suffix_allow_count, g_cfg.exact_block_count, @@ -1780,6 +1971,6 @@ int main(int argc, char **argv) { close(control_fd); unlink(g_cfg.control_socket); unlink(g_cfg.pid_file); - free_regex_rules(&g_cfg); + free_config_dynamic(&g_cfg); return 0; } From fb09f4f83b97fa3bc7298b8c07307b5c1ae4ccbf Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 15:43:59 -0700 Subject: [PATCH 020/108] Harden DNS daemon watchdog recovery --- .../ufirewall/dns/DnsHijackManager.java | 95 ++++++++++++++++++- 1 file changed, 90 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java index 7e0041c25..0c7de3afa 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java @@ -8,6 +8,7 @@ import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -39,6 +40,9 @@ public final class DnsHijackManager { private static final String SOCKET = "afwall_dnsd.sock"; private static final String QUERY_LOG = "afwall_dnsd.log"; private static final String SUPERVISOR_LOG = "afwall_dnsd_supervisor.log"; + private static final String SUPERVISOR_PID = "afwall_dnsd_supervisor.pid"; + private static final String RESTART_COUNT = "afwall_dnsd_restart_count"; + private static final String LAST_EXIT = "afwall_dnsd_last_exit"; private static final String BOOT_SCRIPT = "afwall_dnsd_boot.sh"; private static final String BOOT_LOG = "afwall_dnsd_boot.log"; private static final String CHAIN_V4 = "afwall-dns"; @@ -157,6 +161,9 @@ public static String collectLocalDiagnostics(Context context) { File socket = new File(dir, SOCKET); File queryLog = new File(dir, QUERY_LOG); File supervisorLog = new File(dir, SUPERVISOR_LOG); + File supervisorPid = new File(dir, SUPERVISOR_PID); + File restartCount = new File(dir, RESTART_COUNT); + File lastExit = new File(dir, LAST_EXIT); File bootScript = new File(dir, BOOT_SCRIPT); File bootLog = new File(dir, BOOT_LOG); @@ -195,9 +202,17 @@ public static String collectLocalDiagnostics(Context context) { appendFileInfo(out, "control_socket", socket); appendFileInfo(out, "query_log", queryLog); appendFileInfo(out, "supervisor_log", supervisorLog); + appendFileInfo(out, "supervisor_pid", supervisorPid); + appendFileInfo(out, "restart_count", restartCount); + appendFileInfo(out, "last_exit", lastExit); appendFileInfo(out, "boot_script", bootScript); appendFileInfo(out, "boot_log", bootLog); + out.append("\n[supervisor metadata]\n"); + appendSmallFileValue(out, "watchdog_pid", supervisorPid); + appendSmallFileValue(out, "restart_count", restartCount); + appendSmallFileValue(out, "last_exit", lastExit); + out.append("\n[control status]\n"); out.append(queryControl(context, "status")); out.append("\n[control health]\n"); @@ -428,6 +443,25 @@ private static void appendFileInfo(StringBuilder out, String label, File file) { out.append('\n'); } + private static void appendSmallFileValue(StringBuilder out, String label, File file) { + out.append(label).append('='); + if (!file.exists()) { + out.append("missing\n"); + return; + } + try (FileInputStream input = new FileInputStream(file)) { + byte[] buffer = new byte[256]; + int read = input.read(buffer); + if (read <= 0) { + out.append("empty\n"); + } else { + out.append(new String(buffer, 0, read, StandardCharsets.UTF_8).trim()).append('\n'); + } + } catch (IOException e) { + out.append("unreadable: ").append(e.getMessage()).append('\n'); + } + } + private static String normalizeSupervisorAction(String action) { if ("start".equals(action) || "stop".equals(action) || "restart".equals(action) || "reload".equals(action) @@ -1129,27 +1163,71 @@ private static String buildSupervisorScript(File dir, File daemon) { String config = new File(dir, CONF).getAbsolutePath(); String pid = new File(dir, PID).getAbsolutePath(); String log = new File(dir, SUPERVISOR_LOG).getAbsolutePath(); + String supervisorPid = new File(dir, SUPERVISOR_PID).getAbsolutePath(); + String restartCount = new File(dir, RESTART_COUNT).getAbsolutePath(); + String lastExit = new File(dir, LAST_EXIT).getAbsolutePath(); return "#!/system/bin/sh\n" + "DIR=" + shellQuote(dir.getAbsolutePath()) + "\n" + "DAEMON=" + shellQuote(daemon.getAbsolutePath()) + "\n" + "CONF=" + shellQuote(config) + "\n" + "PID=" + shellQuote(pid) + "\n" + + "SUP_PID=" + shellQuote(supervisorPid) + "\n" + "MARKER=" + shellQuote(marker) + "\n" + "LOG=" + shellQuote(log) + "\n" + + "RESTARTS=" + shellQuote(restartCount) + "\n" + + "LAST_EXIT=" + shellQuote(lastExit) + "\n" + + "log_msg() {\n" + + " echo \"$(date +%s) $*\" >> \"$LOG\" 2>/dev/null\n" + + "}\n" + "is_running() {\n" + " [ -f \"$PID\" ] && kill -0 \"$(cat \"$PID\")\" 2>/dev/null\n" + "}\n" + + "supervisor_running() {\n" + + " [ -f \"$SUP_PID\" ] && kill -0 \"$(cat \"$SUP_PID\")\" 2>/dev/null\n" + + "}\n" + + "increment_restarts() {\n" + + " count=$(cat \"$RESTARTS\" 2>/dev/null || echo 0)\n" + + " case \"$count\" in *[!0-9]*|'') count=0 ;; esac\n" + + " count=$((count + 1))\n" + + " echo \"$count\" > \"$RESTARTS\" 2>/dev/null\n" + + "}\n" + + "watch_loop() {\n" + + " trap 'rm -f \"$SUP_PID\"; exit 0' TERM INT\n" + + " log_msg 'watchdog started'\n" + + " while [ -f \"$MARKER\" ]; do\n" + + " if [ ! -x \"$DAEMON\" ]; then\n" + + " echo \"$(date +%s) missing_daemon\" > \"$LAST_EXIT\" 2>/dev/null\n" + + " log_msg 'daemon binary missing or not executable'\n" + + " sleep 5\n" + + " continue\n" + + " fi\n" + + " \"$DAEMON\" --config \"$CONF\" >> \"$LOG\" 2>&1\n" + + " exit_code=$?\n" + + " echo \"$(date +%s) exit=$exit_code\" > \"$LAST_EXIT\" 2>/dev/null\n" + + " if [ -f \"$MARKER\" ]; then\n" + + " increment_restarts\n" + + " log_msg \"daemon exited with $exit_code; restarting\"\n" + + " sleep 2\n" + + " fi\n" + + " done\n" + + " log_msg 'watchdog stopped'\n" + + " rm -f \"$SUP_PID\"\n" + + "}\n" + "start_daemon() {\n" + " mkdir -p \"$DIR\"\n" + " chmod 700 \"$DIR\" 2>/dev/null || true\n" + " chmod 755 \"$DAEMON\" 2>/dev/null || true\n" + " touch \"$MARKER\"\n" + " if is_running; then exit 0; fi\n" - + " ( while [ -f \"$MARKER\" ]; do\n" - + " \"$DAEMON\" --config \"$CONF\" >> \"$LOG\" 2>&1\n" - + " sleep 2\n" - + " done ) >/dev/null 2>&1 &\n" + + " if supervisor_running; then\n" + + " sleep 1\n" + + " if is_running; then exit 0; fi\n" + + " log_msg 'watchdog already running but daemon is not ready'\n" + + " exit 1\n" + + " fi\n" + + " ( watch_loop ) >/dev/null 2>&1 &\n" + + " echo \"$!\" > \"$SUP_PID\" 2>/dev/null\n" + " sleep 1\n" + " if is_running; then exit 0; fi\n" + " exit 1\n" @@ -1157,13 +1235,20 @@ private static String buildSupervisorScript(File dir, File daemon) { + "stop_daemon() {\n" + " rm -f \"$MARKER\"\n" + " if [ -f \"$PID\" ]; then kill -TERM \"$(cat \"$PID\")\" 2>/dev/null || true; fi\n" + + " if [ -f \"$SUP_PID\" ]; then kill -TERM \"$(cat \"$SUP_PID\")\" 2>/dev/null || true; fi\n" + + " rm -f \"$SUP_PID\"\n" + "}\n" + "case \"$1\" in\n" + " start) start_daemon ;;\n" + " stop) stop_daemon; exit 0 ;;\n" + " restart) stop_daemon; start_daemon ;;\n" + " reload) if is_running; then kill -HUP \"$(cat \"$PID\")\" 2>/dev/null; else start_daemon; fi ;;\n" - + " status) if is_running; then echo running; exit 0; else echo stopped; exit 1; fi ;;\n" + + " status) \n" + + " if is_running; then echo \"daemon=running pid=$(cat \"$PID\")\"; else echo daemon=stopped; fi\n" + + " if supervisor_running; then echo \"watchdog=running pid=$(cat \"$SUP_PID\")\"; else echo watchdog=stopped; fi\n" + + " echo \"restart_count=$(cat \"$RESTARTS\" 2>/dev/null || echo 0)\"\n" + + " echo \"last_exit=$(cat \"$LAST_EXIT\" 2>/dev/null || echo none)\"\n" + + " if is_running || supervisor_running; then exit 0; else exit 1; fi ;;\n" + " *) echo \"usage: $0 {start|stop|restart|reload|status}\"; exit 2 ;;\n" + "esac\n"; } From 6c25dae54d8c7278cb5cce2ecfb771ce91a087f1 Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 15:47:26 -0700 Subject: [PATCH 021/108] Report DNS daemon resource stats --- .../main/assets/dnsd/arm64-v8a/afwall_dnsd | Bin 29248 -> 31344 bytes .../main/assets/dnsd/armeabi-v7a/afwall_dnsd | Bin 24016 -> 25620 bytes app/src/main/assets/dnsd/x86/afwall_dnsd | Bin 29828 -> 32172 bytes app/src/main/assets/dnsd/x86_64/afwall_dnsd | Bin 31264 -> 33664 bytes dnsdaemon/jni/afwall_dnsd.c | 123 +++++++++++++++++- 5 files changed, 122 insertions(+), 1 deletion(-) diff --git a/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd b/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd index be85cf0e98f1b3de97b049f1546915e2d01ddc38..bf22ad6500e15f8558d0904dd0151f7936db60ef 100755 GIT binary patch delta 13548 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 Q{~t;`E7gil&_t^JFYXJb<^TWy diff --git a/app/src/main/assets/dnsd/x86/afwall_dnsd b/app/src/main/assets/dnsd/x86/afwall_dnsd index 05b87788efcd9cd7858ca6145bb4e9a7578feae8..3df6413df9c1c31c0feb1beecece22ad3b71c38d 100755 GIT binary patch delta 14574 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 g5_hJA4(tUd>ezyvsS;4#&eV{$O@iPU* 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 delta 12377 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 U5hT8GT=1PWD)$Tgr*`uH2c8w(wEzGB diff --git a/dnsdaemon/jni/afwall_dnsd.c b/dnsdaemon/jni/afwall_dnsd.c index c2ab37532..d288dcbc3 100644 --- a/dnsdaemon/jni/afwall_dnsd.c +++ b/dnsdaemon/jni/afwall_dnsd.c @@ -239,6 +239,90 @@ static uint64_t div_u64(uint64_t numerator, uint64_t denominator) { return denominator == 0 ? 0 : numerator / denominator; } +static long read_proc_status_kb(const char *key) { + FILE *fp; + char line[256]; + char prefix[64]; + size_t prefix_len; + long value = 0; + if (key == NULL || key[0] == '\0') { + return 0; + } + snprintf(prefix, sizeof(prefix), "%s:", key); + prefix_len = strlen(prefix); + fp = fopen("/proc/self/status", "r"); + if (fp == NULL) { + return 0; + } + while (fgets(line, sizeof(line), fp) != NULL) { + if (strncmp(line, prefix, prefix_len) == 0) { + char *p = line + prefix_len; + while (*p && !isdigit((unsigned char) *p)) { + p++; + } + value = strtol(p, NULL, 10); + break; + } + } + fclose(fp); + return value < 0 ? 0 : value; +} + +static bool read_proc_cpu_ticks(uint64_t *user_ticks, uint64_t *system_ticks) { + FILE *fp; + char line[1024]; + char *end_comm; + char *token; + int field = 3; + uint64_t user = 0; + uint64_t system = 0; + if (user_ticks != NULL) { + *user_ticks = 0; + } + if (system_ticks != NULL) { + *system_ticks = 0; + } + fp = fopen("/proc/self/stat", "r"); + if (fp == NULL) { + return false; + } + if (fgets(line, sizeof(line), fp) == NULL) { + fclose(fp); + return false; + } + fclose(fp); + end_comm = strrchr(line, ')'); + if (end_comm == NULL || end_comm[1] == '\0') { + return false; + } + token = strtok(end_comm + 2, " "); + while (token != NULL) { + if (field == 14) { + user = strtoull(token, NULL, 10); + } else if (field == 15) { + system = strtoull(token, NULL, 10); + break; + } + field++; + token = strtok(NULL, " "); + } + if (user_ticks != NULL) { + *user_ticks = user; + } + if (system_ticks != NULL) { + *system_ticks = system; + } + return field >= 15; +} + +static uint64_t cpu_ticks_to_ms(uint64_t ticks) { + long hz = sysconf(_SC_CLK_TCK); + if (hz <= 0) { + return 0; + } + return div_u64(ticks * 1000ULL, (uint64_t) hz); +} + static void record_query_latency(int latency_ms) { uint64_t latency; if (latency_ms < 0) { @@ -1699,7 +1783,18 @@ static void write_health_response(int client) { int latency_ms; int upstream_index = -1; int rcode; - + long memory_rss_kb = read_proc_status_kb("VmRSS"); + long memory_hwm_kb = read_proc_status_kb("VmHWM"); + uint64_t cpu_user_ticks; + uint64_t cpu_system_ticks; + uint64_t cpu_user_ms; + uint64_t cpu_system_ms; + uint64_t cpu_total_ms; + + read_proc_cpu_ticks(&cpu_user_ticks, &cpu_system_ticks); + cpu_user_ms = cpu_ticks_to_ms(cpu_user_ticks); + cpu_system_ms = cpu_ticks_to_ms(cpu_system_ticks); + cpu_total_ms = cpu_user_ms + cpu_system_ms; query_len = build_health_query(query, sizeof(query)); gettimeofday(&start, NULL); response_len = query_len == 0 @@ -1714,6 +1809,8 @@ static void write_health_response(int client) { "generation=%llu\nupstreams=%d\nsplit_upstreams=%d\nupstream_probe=%s\n" "upstream_probe_ms=%d\nupstream_probe_index=%d\nupstream_probe_rcode=%d\n" "queries=%llu\nblocked=%llu\nallowed=%llu\ncache_size=%d\ncache_entries=%d\n" + "memory_rss_kb=%ld\nmemory_hwm_kb=%ld\ncpu_user_ms=%llu\n" + "cpu_system_ms=%llu\ncpu_total_ms=%llu\n" "exact_index_size=%d\nsuffix_allow_trie_nodes=%d\nsuffix_block_trie_nodes=%d\n" "rules_total=%d\n", (long) getpid(), @@ -1731,6 +1828,11 @@ static void write_health_response(int client) { (unsigned long long) g_stats.allowed, g_cfg.cache_size, cache_entry_count(), + memory_rss_kb, + memory_hwm_kb, + (unsigned long long) cpu_user_ms, + (unsigned long long) cpu_system_ms, + (unsigned long long) cpu_total_ms, EXACT_INDEX_SIZE, g_cfg.suffix_allow_trie.count, g_cfg.suffix_block_trie.count, @@ -1801,10 +1903,24 @@ static void handle_control(int fd) { cmd[n] = '\0'; trim(cmd); if (strcmp(cmd, "status") == 0 || strcmp(cmd, "stats") == 0) { + long memory_rss_kb = read_proc_status_kb("VmRSS"); + long memory_hwm_kb = read_proc_status_kb("VmHWM"); + uint64_t cpu_user_ticks; + uint64_t cpu_system_ticks; + uint64_t cpu_user_ms; + uint64_t cpu_system_ms; + uint64_t cpu_total_ms; + + read_proc_cpu_ticks(&cpu_user_ticks, &cpu_system_ticks); + cpu_user_ms = cpu_ticks_to_ms(cpu_user_ticks); + cpu_system_ms = cpu_ticks_to_ms(cpu_system_ticks); + cpu_total_ms = cpu_user_ms + cpu_system_ms; write_control_response(client, "running=1\npid=%ld\nuptime=%llu\ngeneration=%llu\n" "queries=%llu\nudp_queries=%llu\ntcp_queries=%llu\ninvalid_queries=%llu\n" "allowed=%llu\nblocked=%llu\nfail_open_drops=%llu\nfail_closed_blocks=%llu\n" + "memory_rss_kb=%ld\nmemory_hwm_kb=%ld\ncpu_user_ms=%llu\n" + "cpu_system_ms=%llu\ncpu_total_ms=%llu\n" "cache_size=%d\ncache_entries=%d\ncache_hits=%llu\ncache_misses=%llu\n" "cache_hit_rate_ppm=%llu\ncache_stores=%llu\ncache_expired=%llu\ncache_evictions=%llu\n" "upstream_requests=%llu\nupstream_successes=%llu\nupstream_failures=%llu\n" @@ -1824,6 +1940,11 @@ static void handle_control(int fd) { (unsigned long long) g_stats.blocked, (unsigned long long) g_stats.fail_open_drops, (unsigned long long) g_stats.fail_closed_blocks, + memory_rss_kb, + memory_hwm_kb, + (unsigned long long) cpu_user_ms, + (unsigned long long) cpu_system_ms, + (unsigned long long) cpu_total_ms, g_cfg.cache_size, cache_entry_count(), (unsigned long long) g_stats.cache_hits, From d59fd9c1e28fb0ae057a74647f9a20b11944ca8c Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 15:52:21 -0700 Subject: [PATCH 022/108] Add DNS query history search --- .../main/assets/dnsd/arm64-v8a/afwall_dnsd | Bin 31344 -> 32128 bytes .../main/assets/dnsd/armeabi-v7a/afwall_dnsd | Bin 25620 -> 26212 bytes app/src/main/assets/dnsd/x86/afwall_dnsd | Bin 32172 -> 33116 bytes app/src/main/assets/dnsd/x86_64/afwall_dnsd | Bin 33664 -> 34576 bytes .../activity/DnsQueriesActivity.java | 71 ++++++++++++++-- .../ufirewall/dns/DnsHijackManager.java | 44 +++++++--- app/src/main/res/values/strings.xml | 5 ++ dnsdaemon/jni/afwall_dnsd.c | 80 ++++++++++++++++++ 8 files changed, 183 insertions(+), 17 deletions(-) diff --git a/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd b/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd index bf22ad6500e15f8558d0904dd0151f7936db60ef..08e691a31658f49f22c4812fe2c6bbc23e2ee466 100755 GIT binary patch delta 9413 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 diff --git a/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd b/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd index af2adedd3d4db3e0c0c01c4031a65ce7a5794d76..b01cb94e88283b9cf548ae6eb156982f2db49d81 100755 GIT binary patch delta 9257 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 diff --git a/app/src/main/assets/dnsd/x86/afwall_dnsd b/app/src/main/assets/dnsd/x86/afwall_dnsd index 3df6413df9c1c31c0feb1beecece22ad3b71c38d..a3924fe906e8b0f6e3476d4bfa93a3d3b35520ea 100755 GIT binary patch delta 7365 zcmZu$3s@9amcCUs2#R*|ZlGxzDBcJ(C{IOD0zOciS2qYMF^bqez=%c-P6OSr_O$IV z-^sd}Ode*FG5NlAjS1>%G!rv2$Ye4JX0kD}YZ8-n++uLDn#>yGjMMwy>IO2q+h3pi zSDkb3Ip>~pUsZMD&%*USaZo#}Cz`SOjIpkRKTgezVK6lQ zjNv~eKm8^e0al;6iTPgbJ6!7@MTq z;N2cd6J`ogXJcn=n{lo0h3u9Y&A%zz^RS`%=2MU|M#6#6p%!s|fbHB584CdCq7N_m z@EqLb{9)Yt2Q&5&a3;)s!Vx}S=QxA08yw-vO^%3(%n`od<~S1};Rr>4;uy%-eU7sj z`wPd}%*L1t7eVMN$2l;{aV}#)9MuRRM+7a5V+dnfj-ia{IHKDIj^T_+93vP@=4In z#tw7LVQi42k+G*Z<}&s)$2`WK<%ofKjN<~vUgnt3*sB~17(2nSkg-!7i;zp-4}G5c z4IK{B3Nw;+&!U&+Q9%b9Lq=7|x&ax@0hR$9ft|p^z*E4Bz%j%_ z1|EZZVHh1Zfb)SlaH|#A3bzgcHE`<`@D%V9E{9txK8k>uz}6CGWsSHvwFvP5=9J?a z*s}yf4tS#$BLu^(vko$#p#g~i9y7xLP}7L|z@8@52i^e&pc95>I0Woj2O~hX9`)(D z@I+yl-U-hTWcp)xig1I%Bl3jnv^*l)|2A63#nKNVlEMC2L`J*=saVVdS3WnOUtBWB zugX57D@dh6idi-K{xaQ-$Ph*;HZsL;4C(nt+7%f_>mt=+<9yl~nd~=)T=mc{Z5aJ? zWT>Bnki4Q)`CX*i?*#51S7iNBYSL&`A}gc_ZMrBG(-OeGMYI#}Y$-jXP4^pH&Dem_ z_EW7|EL=lhfqBuy)yKo8F)GwggFtOn?$$-YgF4z7mG1X!J!6k5?OsQf8@NkTY~c2tX&o`2cyE>T~sg-`}b1GiLl=M9<5E`~o2J{-`86Ud-;K z_0gpvgNSyW{dNE!My$E_^5-3NGFoqZyMr3u%NhI+Ch)U!(ivo7U2U7@cTd zOIlr$xU8QR>qp1$bun5}C04TTqAwuQ^ojnWb(U;vqK??ysAh#5=5|Oo5euuzWEHJ~S*~cJ&-ANO{S+zpVzd2r zkXiQKU#XBZ9{eT{TSW18A7$&q_4|+`xO|SMX*?LEB7F6^VA1V*wVyWX7mF(!=_P$a zRDn|S{}?qia-)@BSbSaI6M=47HD>w0COK+HKEkHB@@p>-A%x#d?f3*G3|g60unO`) z3+;-F5l>m@NL;(vW~Tdbx@GqBcB=SAsR4qcLFB3Ulw_6t=mFVh94y8nCxco*(#xNgS@DvRHo zcm<1%eK@GS2RsV~ZmN9d`y8`;yn#mJ^Tgf;dKj-0cQ;T>LREaRQpeDLNqyu3Tyc)@ zATVT}FB&E}qk-%RX<;TT4)$TMph6LRRZo`^GQ_L(^v8tbB{MMstpQd~y9dT=O!9fm zZ~L%e#8L7uFCgh|Rf*p@Tp*loR~>q84YGQyYE&GorS}t~MMo|DA+cUuT}Ne7l(@T& znx&;7>lGzoR*czjt6-5=*U~A;C|;7m^aB z*J`*67^P}QH+FjOC}0-(+7$oLIueqT4SN)Z5`h?09C4^VK~9#}zVz@w^ z$qu(Yc3M2Gwa_l3cI4HOrin=%3x9;vT zj=2s?*P;C99gpv4#=C*Y|+Yb_GEGJ6LUPS?^>6!wp=`bPjCQKe*MN3leiubB%LE4*Q%EQR=M5>hBpU)M6%B zlO57ZZUV~Uamg!8jnqdR3=w1<)*x2f-R+t zyqCqbOXzA|hTx%xc`?GZp{V&c1@RF(c@`wwo+{zlA4GV@|Lq<$jM;De6>7p<71BcY zDJcO-@n91PKm|4t?tIsNMeH3(1-qzQ3R63dKSZ0WJwLzwmB+)nLX97yT~N`$P28$q z_=Qj}1@x4%u2CPq^1hEban^XxWk2_5Y# zgo;G3iYs)_Jo1yMpReOC}8ET-_n+^CJPZjEo3UBRNV9GftV3v1*fi>S3Q zzD&oLtblg;P_SsVq30EF)PmzIU#$lSXIOS+;3>cYTq*HrRSqD0!^SqZV-dYmm@kyl z{lZH9C%zqxXB0b{R@u=iq)xt_-S4HAqMr&2>3&g`u!vHMi%>pVTxHAV_SGh{d|@Fs zieazfOLQv2@3z~y>wyqH|2M)R_~W(*@RnTI`!~XKitsJIsmy|KlUK-fUV?-#KlW5E z41%y~p-nN$rN5YzN?h-3NYkgA4o?a{tP=Gvt2Q{Iwy z^taPOrouw3xOAIKxl3nD=v+x_$b9bN9KMsBMl?-wMG2)ZTpn`6>-iLWyqNkIHisPM zt-n{hyO_R4?Y}q_rBk)zi)q!O)(``CGiX}(Yen?-qUQWyZ@;H%FDaVp#6RJ1t+-jt zo6eqYsxKl_X`)a>U8Na90Uaxik1bGIxiA+;dP328HeU2+K9#U|+$p5bO7%h^Jyc5F z;xt@WF8+}&UuiSqkY2%p#x1ooteVztv;3O^y1O_Is)NgTX)NoB@){^ps+i2&U3h1b zr2=}lEF;*f$|tnQaz6Q&mkaqr%gRMT$fK1@&Y%>Qrec{(U%Cio`_jvTkuoc`qC8r0 zM#!P+N6u@FibwsI_GDvA&%8QQEI6?L$5v`EXpn;?XJvD$YJcg z>0g8M_jUH0ckH({lg|lFOKG^WTv$r}RTbivKB}(L30btYY75G%RSWov6tHZyFpn(D z{wkD_dHGTZo>{&Iib+SRkLpIBvzJQ*d>nkUc`m1+yh@-?xd zDV<7JMPb%9uF4Zq=`gNS>G&!=)ctbRO7MeMr%kGwNTH>xOVO}zb+wQ}AFPfSlIbqW zGzwia51jHfdbDm`lPMIFd(9F^$JRt^Qzio)GnICOMZTCqqNyE?wwV%9{>b!_AW>dT z8OpAj5+R9B)nsApd|nd`H4kc%P#S8pghX0XYlHNI+HELH>Z*kVI#kz%RuAhkg?LJ@ zUxV^MeK%@;TVDccUPF>FpPCvr;rizdMwE9N^kH$_DZ@ym4P!9~%dtj25l;!`G$D?v z&3RDKW6ny!L-Xbr!!TZP1lfn9g4@pLKQhtD*GYgCqjIZ({?+UeP+GPNv9zS|2+FIC zsnGPGFz4#L+ool%yXleht>p~=%*LUOkx9i(PxtB^d=y9`l!{g!nVM3jT z6XAr;+o3S|Hxcy3hDtO^ZA}j24-ZqDJo+0ZS4Yss)+8Z<4z)I+{IWFxrQf5aLO4}C z+Jf@MN9UpZ;L!#lbSP=#EJ3`|N5;o;#G3x0#~vFK1P#sKd{79XH#RR3H}uiH&544V zqT6&R3)=F9VA|QXLxYo+^9~lu@edzh_j*Y~6K&B*jsKQaX#b!wns#oKaBUTG^>bJ$t!8<*q&fr`q$+v=N*|scU7Co_ToA{}dZf;8v zjdq%|JyVAlZ@!#YNR2p~=#YLsM%;Gw05xo11jV#{qYy~iGK;*Bs~y(z z%U-WJrwYe-oOHZ9dpWik?CfV|(*B*v=*h92TG&0mGdBY7K@oQ66&&Mzj%nm|GfC)3 z5&|ftBN5|sWk+$jSB(a90cxJXg6`W1FJq4I$4M39p)z3*G+P}9!KQ37b~YYtv*iC6lb-MlQP9wh$vWR@%5q3*Z&G> zZjcj4R$tYJGbw&os4$Zj?5Y*~>Cmn?%;Z;hrGj&HSCrsK6T4zM@G$idW(pYfXS!`x)vIUfo8fbVtQ$K*a<1*iD{ zWj9p{*#M(Hu`Qj;D)ZzG&7k``%~CQ=5W zz||t@T-{QtR|(|v&GIk#sl)3^5g$8u<=xjjo*vXaC(JmF_R|F7VY!BsD5 zP%%t>~$MPTXHq7}ojO3t&7FNsmyfrb;w^}(Q?#iBW#Vdj;$R{$CyMFH-_YC*7a=3Rm z{%u3=N*BnNx&bJ9Z)o=8FRH}RAJWOaYi<1d7pG3VLghdHm22|1cQ4*VgN}lZgU*6R zKp%r{f$o9)pI|HklnlxTRf5c*Hqc(s0O%;_IOr^B1oScJ7UBWUT(Zc``!EM?mE!A0;1t z{6yZ0xU}vib9aJ259giz^n>n%K>jiA+yS(pnggM9u{+3r6r9lm^nQ23tkd|6!#^Ze qtLQ3wkk delta 6330 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 diff --git a/app/src/main/assets/dnsd/x86_64/afwall_dnsd b/app/src/main/assets/dnsd/x86_64/afwall_dnsd index 846dea977abb1b253cfce09dc92921a48b15321f..1c338d238e9bc76ff37ea92271d33b61a407ca41 100755 GIT binary patch delta 10265 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 diff --git a/app/src/main/java/dev/ukanth/ufirewall/activity/DnsQueriesActivity.java b/app/src/main/java/dev/ukanth/ufirewall/activity/DnsQueriesActivity.java index af926ac54..b75d65745 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/activity/DnsQueriesActivity.java +++ b/app/src/main/java/dev/ukanth/ufirewall/activity/DnsQueriesActivity.java @@ -32,6 +32,8 @@ public class DnsQueriesActivity extends AppCompatActivity { private static final int MENU_REFRESH = 1; private static final int MENU_COPY = 2; + private static final int MENU_SEARCH = 3; + private static final int MENU_TOGGLE_HISTORY = 4; private static final long REFRESH_MS = 2500L; private final Handler handler = new Handler(Looper.getMainLooper()); @@ -39,12 +41,16 @@ public class DnsQueriesActivity extends AppCompatActivity { private final List entries = new ArrayList<>(); private ArrayAdapter adapter; private TextView status; + private boolean showHistory; + private String historyFilter = ""; private final Runnable autoRefresh = new Runnable() { @Override public void run() { - loadQueries(false); - handler.postDelayed(this, REFRESH_MS); + if (!showHistory) { + loadQueries(false); + handler.postDelayed(this, REFRESH_MS); + } } }; @@ -75,7 +81,9 @@ protected void onCreate(Bundle savedInstanceState) { @Override protected void onResume() { super.onResume(); - handler.postDelayed(autoRefresh, REFRESH_MS); + if (!showHistory) { + handler.postDelayed(autoRefresh, REFRESH_MS); + } } @Override @@ -93,6 +101,9 @@ protected void onDestroy() { @Override public boolean onCreateOptionsMenu(Menu menu) { menu.add(0, MENU_REFRESH, 0, R.string.refresh).setIcon(R.drawable.ic_refresh); + menu.add(0, MENU_SEARCH, 0, R.string.Search).setIcon(R.drawable.ic_search); + menu.add(0, MENU_TOGGLE_HISTORY, 0, + showHistory ? R.string.dns_queries_live : R.string.dns_queries_history); menu.add(0, MENU_COPY, 0, R.string.copy).setIcon(R.drawable.ic_copy); return true; } @@ -106,6 +117,12 @@ public boolean onOptionsItemSelected(MenuItem item) { case MENU_REFRESH: loadQueries(true); return true; + case MENU_SEARCH: + showSearchDialog(); + return true; + case MENU_TOGGLE_HISTORY: + setHistoryMode(!showHistory); + return true; case MENU_COPY: Api.copyToClipboard(this, buildTextDump()); return true; @@ -121,13 +138,17 @@ private void loadQueries(boolean showLoading) { if (showLoading) { status.setText(R.string.loading); } + final boolean useHistory = showHistory; + final String filter = historyFilter; executor.execute(() -> { - List latest = DnsHijackManager.getRecentQueries(this); - runOnUiThread(() -> updateQueries(latest)); + List latest = useHistory + ? DnsHijackManager.getHistoricalQueries(this, filter) + : DnsHijackManager.getRecentQueries(this); + runOnUiThread(() -> updateQueries(latest, useHistory, filter)); }); } - private void updateQueries(List latest) { + private void updateQueries(List latest, boolean history, String filter) { entries.clear(); adapter.clear(); for (int i = latest.size() - 1; i >= 0; i--) { @@ -136,7 +157,16 @@ private void updateQueries(List latest) { adapter.add(formatEntry(entry)); } adapter.notifyDataSetChanged(); - status.setText(getString(R.string.dns_queries_status, latest.size())); + if (history) { + if (filter == null || filter.trim().isEmpty()) { + status.setText(getString(R.string.dns_queries_history_status, latest.size())); + } else { + status.setText(getString(R.string.dns_queries_history_filter_status, + latest.size(), filter.trim())); + } + } else { + status.setText(getString(R.string.dns_queries_status, latest.size())); + } } private String formatEntry(DnsHijackManager.QueryEntry entry) { @@ -195,6 +225,33 @@ private void applyQueryAction(DnsHijackManager.QueryEntry entry, int which) { loadQueries(false); } + private void setHistoryMode(boolean enabled) { + showHistory = enabled; + if (showHistory) { + handler.removeCallbacks(autoRefresh); + } else { + historyFilter = ""; + handler.removeCallbacks(autoRefresh); + handler.postDelayed(autoRefresh, REFRESH_MS); + } + invalidateOptionsMenu(); + loadQueries(true); + } + + private void showSearchDialog() { + new MaterialDialog.Builder(this) + .title(R.string.Search) + .input(getString(R.string.dns_queries_search_hint), historyFilter, (dialog, input) -> { + historyFilter = input == null ? "" : input.toString().trim(); + showHistory = true; + handler.removeCallbacks(autoRefresh); + invalidateOptionsMenu(); + loadQueries(true); + }) + .negativeText(R.string.Cancel) + .show(); + } + private String buildTextDump() { StringBuilder dump = new StringBuilder(); for (DnsHijackManager.QueryEntry entry : entries) { diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java index 0c7de3afa..bc40ea3f6 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java @@ -224,16 +224,13 @@ public static String collectLocalDiagnostics(Context context) { } public static List getRecentQueries(Context context) { - List entries = new ArrayList<>(); - String logs = queryControl(context, "logs"); - String[] lines = logs.split("\\r?\\n"); - for (String line : lines) { - QueryEntry entry = QueryEntry.parse(line); - if (entry != null) { - entries.add(entry); - } - } - return entries; + return parseQueryEntries(queryControl(context, "logs")); + } + + public static List getHistoricalQueries(Context context, String filter) { + String cleanFilter = sanitizeHistoryFilter(filter); + String command = cleanFilter.isEmpty() ? "history" : "history " + cleanFilter; + return parseQueryEntries(queryControl(context, command)); } public static String benchmarkUpstreams(Context context) { @@ -350,6 +347,33 @@ private static String queryControl(Context context, String command) { } } + private static List parseQueryEntries(String raw) { + List entries = new ArrayList<>(); + if (raw == null) { + return entries; + } + String[] lines = raw.split("\\r?\\n"); + for (String line : lines) { + QueryEntry entry = QueryEntry.parse(line); + if (entry != null) { + entries.add(entry); + } + } + return entries; + } + + private static String sanitizeHistoryFilter(String filter) { + if (filter == null) { + return ""; + } + String clean = filter.trim().replace('\n', ' ').replace('\r', ' '); + clean = clean.replaceAll("\\s+", " "); + if (clean.length() > 80) { + clean = clean.substring(0, 80); + } + return clean; + } + private static String benchmarkUpstreamsDirect() { StringBuilder out = new StringBuilder(); List targets = parseUpstreamTargets(G.dnsHijackUpstreams()); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f4e572ff8..3a4853e48 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -376,6 +376,11 @@ DNS Queries View recent daemon DNS queries and quickly add allow or block rules. %1$d DNS queries loaded. + History + Live + %1$d historical DNS queries loaded. + %1$d historical DNS queries matched \"%2$s\". + Domain, action, or latency Allow this domain Allow this domain and subdomains Temporarily allow this domain diff --git a/dnsdaemon/jni/afwall_dnsd.c b/dnsdaemon/jni/afwall_dnsd.c index d288dcbc3..0676d6557 100644 --- a/dnsdaemon/jni/afwall_dnsd.c +++ b/dnsdaemon/jni/afwall_dnsd.c @@ -41,6 +41,8 @@ #define DEFAULT_CACHE_SIZE 1024 #define MAX_CACHE_SIZE 4096 #define LOG_RING 256 +#define LOG_HISTORY_LIMIT 512 +#define LOG_LINE_MAX 512 #define DEFAULT_PORT 5354 #define DEFAULT_TIMEOUT_MS 2500 @@ -315,6 +317,38 @@ static bool read_proc_cpu_ticks(uint64_t *user_ticks, uint64_t *system_ticks) { return field >= 15; } +static bool ascii_contains_ci(const char *haystack, const char *needle) { + size_t needle_len; + const char *p; + if (needle == NULL || needle[0] == '\0') { + return true; + } + if (haystack == NULL) { + return false; + } + needle_len = strlen(needle); + if (needle_len == 0) { + return true; + } + for (p = haystack; *p != '\0'; p++) { + size_t i; + for (i = 0; i < needle_len; i++) { + unsigned char hc = (unsigned char) p[i]; + unsigned char nc = (unsigned char) needle[i]; + if (hc == '\0') { + return false; + } + if (tolower(hc) != tolower(nc)) { + break; + } + } + if (i == needle_len) { + return true; + } + } + return false; +} + static uint64_t cpu_ticks_to_ms(uint64_t ticks) { long hz = sysconf(_SC_CLK_TCK); if (hz <= 0) { @@ -1888,6 +1922,46 @@ static void write_benchmark_response(int client) { } } +static void write_history_response(int client, const char *filter) { + FILE *fp; + char line[LOG_LINE_MAX]; + char (*matches)[LOG_LINE_MAX]; + int count = 0; + int pos = 0; + int i; + + if (g_cfg.log_file[0] == '\0') { + return; + } + fp = fopen(g_cfg.log_file, "r"); + if (fp == NULL) { + return; + } + matches = (char (*)[LOG_LINE_MAX]) calloc(LOG_HISTORY_LIMIT, LOG_LINE_MAX); + if (matches == NULL) { + fclose(fp); + return; + } + while (fgets(line, sizeof(line), fp) != NULL) { + trim(line); + if (line[0] == '\0' || !ascii_contains_ci(line, filter)) { + continue; + } + safe_copy(matches[pos], LOG_LINE_MAX, line); + pos = (pos + 1) % LOG_HISTORY_LIMIT; + if (count < LOG_HISTORY_LIMIT) { + count++; + } + } + fclose(fp); + + for (i = 0; i < count; i++) { + int idx = (pos - count + i + LOG_HISTORY_LIMIT) % LOG_HISTORY_LIMIT; + write_control_response(client, "%s\n", matches[idx]); + } + free(matches); +} + static void handle_control(int fd) { int client = accept(fd, NULL, NULL); char cmd[128]; @@ -1996,6 +2070,12 @@ static void handle_control(int fd) { g_logs[idx].domain, g_logs[idx].latency_ms); } + } else if (strcmp(cmd, "history") == 0) { + write_history_response(client, ""); + } else if (strncmp(cmd, "history ", 8) == 0) { + char *filter = cmd + 8; + trim(filter); + write_history_response(client, filter); } else if (strcmp(cmd, "stop") == 0) { write_control_response(client, "ok stopping\n"); g_running = 0; From f379738e158ffe2cf884a8016ab39da06fb4c39a Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 15:55:36 -0700 Subject: [PATCH 023/108] Export displayed DNS queries --- .../activity/DnsQueriesActivity.java | 81 +++++++++++++++++++ app/src/main/res/values/strings.xml | 2 + 2 files changed, 83 insertions(+) diff --git a/app/src/main/java/dev/ukanth/ufirewall/activity/DnsQueriesActivity.java b/app/src/main/java/dev/ukanth/ufirewall/activity/DnsQueriesActivity.java index b75d65745..14d061f9b 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/activity/DnsQueriesActivity.java +++ b/app/src/main/java/dev/ukanth/ufirewall/activity/DnsQueriesActivity.java @@ -1,8 +1,13 @@ package dev.ukanth.ufirewall.activity; +import android.app.Activity; +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Looper; +import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.widget.ArrayAdapter; @@ -14,6 +19,9 @@ import com.afollestad.materialdialogs.MaterialDialog; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; @@ -30,10 +38,13 @@ public class DnsQueriesActivity extends AppCompatActivity { + private static final String TAG = "AFWallDnsQueries"; + private static final int REQUEST_EXPORT_DNS_QUERIES = 50; private static final int MENU_REFRESH = 1; private static final int MENU_COPY = 2; private static final int MENU_SEARCH = 3; private static final int MENU_TOGGLE_HISTORY = 4; + private static final int MENU_EXPORT = 5; private static final long REFRESH_MS = 2500L; private final Handler handler = new Handler(Looper.getMainLooper()); @@ -105,6 +116,7 @@ public boolean onCreateOptionsMenu(Menu menu) { menu.add(0, MENU_TOGGLE_HISTORY, 0, showHistory ? R.string.dns_queries_live : R.string.dns_queries_history); menu.add(0, MENU_COPY, 0, R.string.copy).setIcon(R.drawable.ic_copy); + menu.add(0, MENU_EXPORT, 0, R.string.export_to_sd).setIcon(R.drawable.ic_export); return true; } @@ -126,11 +138,22 @@ public boolean onOptionsItemSelected(MenuItem item) { case MENU_COPY: Api.copyToClipboard(this, buildTextDump()); return true; + case MENU_EXPORT: + startQueryExportPicker(); + return true; default: return super.onOptionsItemSelected(item); } } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == REQUEST_EXPORT_DNS_QUERIES && resultCode == Activity.RESULT_OK) { + exportQueriesToUri(data); + } + } + private void loadQueries(boolean showLoading) { if (executor.isShutdown()) { return; @@ -252,6 +275,64 @@ private void showSearchDialog() { .show(); } + private void startQueryExportPicker() { + Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType("text/plain"); + intent.putExtra(Intent.EXTRA_TITLE, buildExportFilename()); + intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION + | Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); + try { + startActivityForResult(intent, REQUEST_EXPORT_DNS_QUERIES); + } catch (ActivityNotFoundException e) { + Log.w(TAG, "System export picker unavailable for DNS query export", e); + Api.copyToClipboard(this, buildTextDump()); + Api.toast(this, getString(R.string.dns_queries_export_picker_missing)); + } + } + + private void exportQueriesToUri(Intent data) { + if (data == null || data.getData() == null) { + Api.toast(this, getString(R.string.export_logs_fail)); + return; + } + Uri uri = data.getData(); + takePersistablePermission(data, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + try (OutputStream output = getContentResolver().openOutputStream(uri, "wt")) { + if (output == null) { + throw new IOException("Unable to open selected export location"); + } + output.write(buildTextDump().getBytes(StandardCharsets.UTF_8)); + output.flush(); + Api.toast(this, getString(R.string.dns_queries_export_success)); + } catch (IOException | RuntimeException e) { + Log.e(TAG, "Unable to export DNS queries", e); + Api.toast(this, getString(R.string.export_logs_fail)); + } + } + + private void takePersistablePermission(Intent data, int permissionFlag) { + Uri uri = data.getData(); + if (uri == null) { + return; + } + int flags = data.getFlags() & permissionFlag; + if (flags == 0) { + return; + } + try { + getContentResolver().takePersistableUriPermission(uri, flags); + } catch (SecurityException e) { + Log.w(TAG, "Unable to persist DNS query export URI permission", e); + } + } + + private String buildExportFilename() { + String timestamp = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.US).format(new Date()); + return "afwall-dns-queries-" + timestamp + ".log"; + } + private String buildTextDump() { StringBuilder dump = new StringBuilder(); for (DnsHijackManager.QueryEntry entry : entries) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3a4853e48..57794d809 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -381,6 +381,8 @@ %1$d historical DNS queries loaded. %1$d historical DNS queries matched \"%2$s\". Domain, action, or latency + DNS queries exported. + No file picker found. DNS queries copied instead. Allow this domain Allow this domain and subdomains Temporarily allow this domain From ed41abbf1c50c541bc6c9bef4a20c08ec37dc612 Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 15:58:49 -0700 Subject: [PATCH 024/108] Add DNS blocklist paste import --- .../ufirewall/dns/DnsBlocklistManager.java | 21 ++++++++++ .../preferences/RulesPreferenceFragment.java | 40 +++++++++++++++++++ app/src/main/res/values/strings.xml | 3 ++ app/src/main/res/xml/rules_preferences.xml | 6 +++ 4 files changed, 70 insertions(+) diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsBlocklistManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsBlocklistManager.java index bfa5eba5c..45936bcdd 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsBlocklistManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsBlocklistManager.java @@ -4,6 +4,7 @@ import android.net.Uri; import android.util.Log; +import java.io.ByteArrayInputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; @@ -60,6 +61,26 @@ public static Result importFromUri(Context context, Uri uri) { } } + public static Result importFromText(Context context, String text) { + Result result = new Result("paste import"); + if (text == null || text.trim().isEmpty()) { + result.failed = true; + result.message = "No DNS blocklist text was provided"; + return result; + } + try (InputStream input = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8))) { + parseStream(input, result); + activate(context, result); + return result; + } catch (IOException e) { + result.failed = true; + result.message = e.getMessage(); + Log.e(TAG, "DNS blocklist paste import failed", e); + ApplicationErrorLog.add(context, "DNS blocklist paste import failed: " + e.getMessage()); + return result; + } + } + public static Result updateFromConfiguredUrls(Context context) { Result result = new Result("URL update"); String raw = G.dnsHijackBlocklistUrls(); diff --git a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java index 724d3464a..3f64c56ab 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java +++ b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java @@ -1,6 +1,8 @@ package dev.ukanth.ufirewall.preferences; import android.app.Activity; +import android.content.ClipData; +import android.content.ClipboardManager; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; @@ -69,6 +71,14 @@ private void wireDnsBlocklistActions() { }); } + Preference pasteBlocklist = findPreference("dnsHijackPasteBlocklist"); + if (pasteBlocklist != null) { + pasteBlocklist.setOnPreferenceClickListener(preference -> { + showDnsBlocklistPasteDialog(); + return true; + }); + } + Preference updateBlocklists = findPreference("dnsHijackUpdateBlocklists"); if (updateBlocklists != null) { updateBlocklists.setOnPreferenceClickListener(preference -> { @@ -221,6 +231,36 @@ private void runDnsBlocklistUpdate() { runBlocklistTask(() -> DnsBlocklistManager.updateFromConfiguredUrls(ctx)); } + private void showDnsBlocklistPasteDialog() { + if (getActivity() == null) { + return; + } + new MaterialDialog.Builder(getActivity()) + .title(R.string.dns_hijack_paste_blocklist_title) + .input(getString(R.string.dns_hijack_paste_blocklist_hint), + getClipboardText(), (dialog, input) -> { + String text = input == null ? "" : input.toString(); + runBlocklistTask(() -> DnsBlocklistManager.importFromText(ctx, text)); + }) + .positiveText(R.string.imports) + .negativeText(R.string.Cancel) + .show(); + } + + private String getClipboardText() { + if (ctx == null) { + return ""; + } + ClipboardManager clipboard = (ClipboardManager) ctx.getSystemService(Context.CLIPBOARD_SERVICE); + if (clipboard == null || !clipboard.hasPrimaryClip() || clipboard.getPrimaryClip() == null + || clipboard.getPrimaryClip().getItemCount() == 0) { + return ""; + } + ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0); + CharSequence text = item == null ? null : item.coerceToText(ctx); + return text == null ? "" : text.toString(); + } + private void runDnsBlocklistRollback() { runBlocklistTask(() -> DnsBlocklistManager.restorePrevious(ctx)); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 57794d809..66ec1f14e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -357,6 +357,9 @@ How often scheduled DNS blocklist updates should run, in hours. Import DNS blocklist file Use the system picker to import a hosts, domain, Pi-hole, or AdBlock-style list. + Paste DNS blocklist + Paste copied hosts, domain, Pi-hole, or AdBlock-style entries and activate them. + Paste blocklist entries here Update DNS blocklists Download configured URLs, compile them, and reload the daemon. Rollback DNS blocklist diff --git a/app/src/main/res/xml/rules_preferences.xml b/app/src/main/res/xml/rules_preferences.xml index 8d5ff28e7..7bd46d2df 100644 --- a/app/src/main/res/xml/rules_preferences.xml +++ b/app/src/main/res/xml/rules_preferences.xml @@ -243,6 +243,12 @@ android:summary="@string/dns_hijack_import_blocklist_summary" android:title="@string/dns_hijack_import_blocklist_title" /> + + Date: Fri, 26 Jun 2026 16:05:49 -0700 Subject: [PATCH 025/108] Add DNS blocklist JSON bundle import --- .../ufirewall/dns/DnsBlocklistManager.java | 247 +++++++++++++++++- app/src/main/res/values/strings.xml | 4 +- 2 files changed, 245 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsBlocklistManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsBlocklistManager.java index 45936bcdd..abf4cf524 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsBlocklistManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsBlocklistManager.java @@ -4,8 +4,14 @@ import android.net.Uri; import android.util.Log; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -18,6 +24,7 @@ import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Locale; import java.util.Set; @@ -35,6 +42,11 @@ public final class DnsBlocklistManager { private static final String EXACT_BACKUP = "block_exact.previous.txt"; private static final String SUFFIX_BACKUP = "block_suffix.previous.txt"; private static final String META_FILE = "metadata.txt"; + private static final int JSON_DETECT_BYTES = 8192; + private static final int MAX_JSON_BUNDLE_BYTES = 16 * 1024 * 1024; + private static final int JSON_TARGET_GENERIC = 0; + private static final int JSON_TARGET_EXACT = 1; + private static final int JSON_TARGET_SUFFIX = 2; private static final Pattern DOMAIN_PATTERN = Pattern.compile( "^(?=.{1,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"); @@ -49,7 +61,7 @@ public static Result importFromUri(Context context, Uri uri) { result.message = "Unable to open selected blocklist"; return result; } - parseStream(input, result); + parsePossiblyJsonStream(input, result); activate(context, result); return result; } catch (IOException e) { @@ -69,7 +81,7 @@ public static Result importFromText(Context context, String text) { return result; } try (InputStream input = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8))) { - parseStream(input, result); + parsePossiblyJsonStream(input, result); activate(context, result); return result; } catch (IOException e) { @@ -208,7 +220,7 @@ private static void downloadAndParse(String urlString, Result result) { result.notes.append(urlString).append(": HTTP ").append(code).append('\n'); return; } - parseStream(connection.getInputStream(), result); + parsePossiblyJsonStream(connection.getInputStream(), result); } catch (IOException e) { result.invalid++; result.notes.append(urlString).append(": ").append(e.getMessage()).append('\n'); @@ -219,6 +231,233 @@ private static void downloadAndParse(String urlString, Result result) { } } + private static void parsePossiblyJsonStream(InputStream rawInput, Result result) throws IOException { + BufferedInputStream input = new BufferedInputStream(rawInput); + input.mark(JSON_DETECT_BYTES); + int first = firstNonWhitespace(input); + input.reset(); + if (first == '{' || first == '[') { + parseJsonBundle(readLimitedString(input), result); + } else { + parseStream(input, result); + } + } + + private static int firstNonWhitespace(InputStream input) throws IOException { + for (int i = 0; i < JSON_DETECT_BYTES; i++) { + int value = input.read(); + if (value == -1) { + return -1; + } + if (!Character.isWhitespace((char) value)) { + return value; + } + } + return -1; + } + + private static String readLimitedString(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + byte[] buffer = new byte[8192]; + int total = 0; + int read; + while ((read = input.read(buffer)) != -1) { + total += read; + if (total > MAX_JSON_BUNDLE_BYTES) { + throw new IOException("JSON DNS blocklist bundle is too large to import safely"); + } + output.write(buffer, 0, read); + } + return output.toString(StandardCharsets.UTF_8.name()); + } + + private static void parseJsonBundle(String rawJson, Result result) throws IOException { + String json = rawJson == null ? "" : rawJson.trim(); + if (json.isEmpty()) { + return; + } + result.sourceLabel = result.sourceLabel + " JSON bundle"; + result.notes.append("Detected JSON DNS blocklist bundle\n"); + try { + if (json.startsWith("[")) { + parseJsonArray(new JSONArray(json), result, JSON_TARGET_GENERIC); + } else { + parseJsonObject(new JSONObject(json), result); + } + } catch (JSONException e) { + throw new IOException("Invalid JSON DNS blocklist bundle: " + e.getMessage(), e); + } + } + + private static void parseJsonObject(JSONObject object, Result result) throws JSONException { + boolean handled = false; + Iterator keys = object.keys(); + while (keys.hasNext()) { + String key = keys.next(); + Object value = object.opt(key); + if (JSONObject.NULL.equals(value)) { + continue; + } + if (isJsonAllowKey(key)) { + result.skipped += countJsonEntries(value); + continue; + } + int target = classifyJsonRuleKey(key); + if (target == JSON_TARGET_EXACT || target == JSON_TARGET_SUFFIX) { + parseJsonValue(value, result, target); + handled = true; + } else if (isJsonGenericRuleKey(key)) { + parseJsonValue(value, result, JSON_TARGET_GENERIC); + handled = true; + } else if (isJsonWrapperKey(key) && (value instanceof JSONObject || value instanceof JSONArray)) { + parseJsonValue(value, result, JSON_TARGET_GENERIC); + handled = true; + } + } + + if (!handled) { + parseJsonRuleObject(object, result, JSON_TARGET_GENERIC); + } + } + + private static void parseJsonArray(JSONArray array, Result result, int target) throws JSONException { + for (int i = 0; i < array.length(); i++) { + parseJsonValue(array.opt(i), result, target); + } + } + + private static void parseJsonValue(Object value, Result result, int target) throws JSONException { + if (value == null || JSONObject.NULL.equals(value)) { + return; + } + if (value instanceof JSONArray) { + parseJsonArray((JSONArray) value, result, target); + } else if (value instanceof JSONObject) { + JSONObject object = (JSONObject) value; + if (!parseJsonRuleObject(object, result, target)) { + parseJsonObject(object, result); + } + } else { + parseJsonScalar(String.valueOf(value), result, target); + } + } + + private static boolean parseJsonRuleObject(JSONObject object, Result result, int parentTarget) throws JSONException { + String domain = firstJsonString(object, "domain", "host", "hostname", "pattern", "value"); + if (domain.isEmpty()) { + return false; + } + String action = firstJsonString(object, "action", "policy", "decision", "list"); + if (isAllowToken(action)) { + result.skipped++; + return true; + } + String type = firstJsonString(object, "type", "kind", "rule", "rule_type", "match"); + if (containsToken(type, "regex")) { + result.skipped++; + return true; + } + int target = parentTarget == JSON_TARGET_EXACT || parentTarget == JSON_TARGET_SUFFIX + ? parentTarget : JSON_TARGET_GENERIC; + if (containsToken(type, "suffix") || containsToken(type, "wildcard") + || containsToken(type, "subdomain")) { + target = JSON_TARGET_SUFFIX; + } + parseJsonScalar(domain, result, target); + return true; + } + + private static void parseJsonScalar(String raw, Result result, int target) { + String value = raw == null ? "" : raw.trim(); + if (value.isEmpty()) { + result.skipped++; + return; + } + if (target == JSON_TARGET_SUFFIX) { + result.lines++; + addDomain(result.suffixRules, normalizeDomain(value), result); + } else if (target == JSON_TARGET_EXACT) { + result.lines++; + addDomain(result.exactRules, normalizeDomain(value), result); + } else { + parseLine(value, result); + } + } + + private static String firstJsonString(JSONObject object, String... keys) { + for (String key : keys) { + String value = object.optString(key, ""); + if (!value.trim().isEmpty()) { + return value.trim(); + } + } + return ""; + } + + private static int classifyJsonRuleKey(String rawKey) { + String key = normalizeJsonKey(rawKey); + if (key.contains("suffix") || key.contains("wildcard")) { + return JSON_TARGET_SUFFIX; + } + if (key.equals("exact") || key.equals("exactblock") || key.equals("blockexact") + || key.equals("host") || key.equals("hosts")) { + return JSON_TARGET_EXACT; + } + return JSON_TARGET_GENERIC; + } + + private static boolean isJsonGenericRuleKey(String rawKey) { + String key = normalizeJsonKey(rawKey); + return key.equals("domain") || key.equals("domains") + || key.equals("rule") || key.equals("rules") + || key.equals("entry") || key.equals("entries") + || key.equals("item") || key.equals("items") + || key.equals("block") || key.equals("blocked") + || key.equals("deny") || key.equals("denied") + || key.equals("blacklist") || key.equals("denylist") + || key.equals("blocklist") || key.equals("blocklists") + || (key.contains("domain") && (key.contains("block") + || key.contains("deny") || key.contains("disallow"))); + } + + private static boolean isJsonWrapperKey(String rawKey) { + String key = normalizeJsonKey(rawKey); + return key.equals("data") || key.equals("backup") || key.equals("export") + || key.equals("dnsblocklist") || key.equals("dnsblocklists") + || key.equals("blocklist") || key.equals("blocklists"); + } + + private static boolean isJsonAllowKey(String rawKey) { + String key = normalizeJsonKey(rawKey); + return isAllowToken(key); + } + + private static String normalizeJsonKey(String rawKey) { + return rawKey == null ? "" : rawKey.toLowerCase(Locale.US).replaceAll("[^a-z0-9]", ""); + } + + private static boolean containsToken(String value, String token) { + return value != null && value.toLowerCase(Locale.US).contains(token); + } + + private static boolean isAllowToken(String value) { + if (value == null) { + return false; + } + String token = value.toLowerCase(Locale.US); + if (token.contains("disallow") || token.contains("deny") || token.contains("block")) { + return false; + } + return token.contains("allow") || token.contains("white"); + } + + private static int countJsonEntries(Object value) { + if (value instanceof JSONArray) { + return ((JSONArray) value).length(); + } + return value == null || JSONObject.NULL.equals(value) ? 0 : 1; + } + private static void parseStream(InputStream input, Result result) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); String line; @@ -406,7 +645,7 @@ public static final class Result { private final Set exactRules = new LinkedHashSet<>(); private final Set suffixRules = new LinkedHashSet<>(); private final StringBuilder notes = new StringBuilder(); - private final String sourceLabel; + private String sourceLabel; public int lines; public int duplicates; public int invalid; diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 66ec1f14e..6753e165f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -356,9 +356,9 @@ Blocklist update interval How often scheduled DNS blocklist updates should run, in hours. Import DNS blocklist file - Use the system picker to import a hosts, domain, Pi-hole, or AdBlock-style list. + Use the system picker to import a hosts, domain, Pi-hole, AdBlock-style, or JSON backup list. Paste DNS blocklist - Paste copied hosts, domain, Pi-hole, or AdBlock-style entries and activate them. + Paste copied hosts, domain, Pi-hole, AdBlock-style, or JSON backup entries and activate them. Paste blocklist entries here Update DNS blocklists Download configured URLs, compile them, and reload the daemon. From ecd05c3ccfdad36a48f78b5c2f1806348fb88734 Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 16:10:46 -0700 Subject: [PATCH 026/108] Retry truncated DNS upstream replies over TCP --- .../main/assets/dnsd/arm64-v8a/afwall_dnsd | Bin 32128 -> 32960 bytes .../main/assets/dnsd/armeabi-v7a/afwall_dnsd | Bin 26212 -> 26900 bytes app/src/main/assets/dnsd/x86/afwall_dnsd | Bin 33116 -> 33836 bytes app/src/main/assets/dnsd/x86_64/afwall_dnsd | Bin 34576 -> 35232 bytes dnsdaemon/jni/afwall_dnsd.c | 117 +++++++++++++----- 5 files changed, 88 insertions(+), 29 deletions(-) diff --git a/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd b/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd index 08e691a31658f49f22c4812fe2c6bbc23e2ee466..2b46eb8765b8594eaffae7af7d3c8fef3059f9d2 100755 GIT binary patch delta 13954 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 b%HX@y>K(^#TSKe8w`%A8B7&ZwoWb%x9@6Uw diff --git a/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd b/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd index b01cb94e88283b9cf548ae6eb156982f2db49d81..b2b762e6dc67f4606ae19b61d6e03012c1794ab1 100755 GIT binary patch delta 11485 zcmc(FdsGz1)^BysFw6`y%AmF~nmO6wUaGh>rutI5SF& z#%LNk@id5hNv_F~7&B!e0cMoA`#pU^yphM;L5vG1+{Ir;AT*1G@Q zJ8RYas&?0N@2Xw9cGazKh&L`1OrW|T5TQhbkbHGT_)4p>5Fs2qfP(Z05dd!5W~Ee;P#Ph&Vx=G3;wf(`Ade}nBJ^-9P#=yU zDj80rJ;Nx6^q4USDKQ2hG+R47!na27*a)5(K@sp63}H5fP(5H^3_=YJ4K^cS9i$ge z9;Qde0-Z!wv>hTJ!v`neNx+*^5IO^x7>7^`AoT=77XbGefenBU1aZL96sQZZJQbl^fXmVl>H;*I5$Xjrr6VK&mI5lvt$(w93=#aHm>&K>Wq>>& zT>~fr?#vnlXaG55j0Q1dgn4ihBg}&{B_RI*kb4UzfZQ)&1i4?r2y*`h zBgox>aVp3gV?4+kBgp?IMp%hXjMG5g7?VKW7^j0+F(!jpG0p(7Vw?$L#W)M0d4FSF z+V-FZ8-ic@-w1od`^A5XH#GgjJChiKde*EXBt#}p9kPXSfz z_OUyB6Maz6;%8x!K`^a@S^6wX28OFA`=D;8BuV;pY+T@z<8I~y(;*0-$o@WsM>>1M zls@@^5AJwBSI)i?7)Dav?1@05qJohNnr_w^7#j6DMDO#{sLI0^#W!S#+AFeqFy&&_ z=VQq!JIqYwc|Mkn2%1FR=Gp9^V2hKN4@k(_NtGhQItL*f6JaGeDvxUKaL>Le`jbp! zeWu49kK!`3T)52VH_BcISk@Xo}@6|ea+0SSF`nUb1Zh^~(J@YIhBdR){DX+7GBdK& z8Rfz*=+Ilv7c*XDR|ij;whQ`@_@_R|-F?{M?gKU2hmz4gAlwJ`^WdNf_eng|BAz-$ z(fTmC@B*}rDJyZ?iIwcV;BgaXLhUoIR@5G1jPPYC)cRy89*uH{pd3_Tu8^Bi{jn7DcvBX#&kK|?-K|LeR4*5ycKe5B? zYw@+bno2ZlVLr$k&i2X=5DoI?vt39hoRtgSdoAuIAIr(hpkS zxYSJ1ds8np8|jeDGV^N{DhrB6!V|9$Mq7WbO*x<;YU{HqlmjxtMyr7BnH3pKE5G-o z*U$B95vqgtG0QmX6U_4*#jN4N znAKc3Q^Z9utGGyJB^SjMaub;XZW6Pb3uNqE5VMsFX0~wSn03&R5cygzl(BFVn2nsC z*}(ZQ>p5TM1YGB0s5W+x|SUgSKO9h`zG<2;!ZwpCO%&N_U6+fywQ-o1}?L5CRl z(V^Pf`VKK<_W@2OTFPQZhSP7>h0&l-7DFz@xw^wE-w&q=;kLxNKiBskuHMmD108}U z-POp16aB?bnb6RWEONsk2Q+uK4*I{QtuQ-hsAgM1Mvj2gJI$r$FbgQF*yrYbJC=wi zdIHwGXr3rYiVnV-ojPG$Ja6%fnrR!TI!E zNxEk6BX1h4e&l(2x3!d zaECy1`obtHh>CN^Wx}T}BP|nFx+;&>)*q_Ha}1{|UC1zZi1`pox%u%CPT$%0AqumG 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 L{~}O!IQ72)TL(mZ delta 11011 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 diff --git a/app/src/main/assets/dnsd/x86/afwall_dnsd b/app/src/main/assets/dnsd/x86/afwall_dnsd index a3924fe906e8b0f6e3476d4bfa93a3d3b35520ea..52701901b1d908da5cf90a74129adcbe1d338713 100755 GIT binary patch delta 13905 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 E0hBtd(f|Me delta 13343 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 SIa#JOtb?pkzhQOdvHuMw)K{(m diff --git a/dnsdaemon/jni/afwall_dnsd.c b/dnsdaemon/jni/afwall_dnsd.c index 0676d6557..6e603457e 100644 --- a/dnsdaemon/jni/afwall_dnsd.c +++ b/dnsdaemon/jni/afwall_dnsd.c @@ -142,6 +142,8 @@ typedef struct { uint64_t upstream_requests; uint64_t upstream_successes; uint64_t upstream_failures; + uint64_t upstream_tcp_fallbacks; + uint64_t upstream_truncated_responses; uint64_t total_latency_ms; uint64_t upstream_latency_ms; uint64_t max_latency_ms; @@ -152,7 +154,7 @@ typedef struct { typedef struct { uint64_t seq; char domain[MAX_DOMAIN]; - char action[16]; + char action[32]; int latency_ms; uint64_t timestamp; } log_entry_t; @@ -1137,12 +1139,21 @@ static const upstream_t *select_upstreams(const config_t *cfg, const char *domai return cfg->upstreams; } +static bool dns_response_truncated(const uint8_t *response, size_t response_len); +static ssize_t forward_tcp_to_upstream(const upstream_t *upstream, int timeout_ms, + const uint8_t *query, size_t query_len, + uint8_t *response, size_t response_len); + static ssize_t forward_udp(const config_t *cfg, const char *domain, const uint8_t *query, size_t query_len, uint8_t *response, size_t response_len, const char **route) { int i; int count = 0; + uint8_t truncated_response[MAX_PACKET]; + ssize_t truncated_len = -1; + bool split_route = false; const upstream_t *upstreams = select_upstreams(cfg, domain, &count, route); + split_route = route != NULL && *route != NULL && strcmp(*route, "split_upstream") == 0; for (i = 0; i < count; i++) { int fd = connect_upstream(&upstreams[i], SOCK_DGRAM, cfg->timeout_ms); ssize_t got; @@ -1156,9 +1167,31 @@ static ssize_t forward_udp(const config_t *cfg, const char *domain, const uint8_ got = recv(fd, response, response_len, 0); close(fd); if (got > 0) { + if (dns_response_truncated(response, (size_t) got)) { + ssize_t tcp_got; + g_stats.upstream_truncated_responses++; + if (truncated_len < 0 && (size_t) got <= sizeof(truncated_response)) { + memcpy(truncated_response, response, (size_t) got); + truncated_len = got; + } + tcp_got = forward_tcp_to_upstream(&upstreams[i], cfg->timeout_ms, + query, query_len, response, response_len); + if (tcp_got > 0) { + g_stats.upstream_tcp_fallbacks++; + if (route != NULL) { + *route = split_route ? "split_upstream_tcp_fallback" : "upstream_tcp_fallback"; + } + return tcp_got; + } + continue; + } return got; } } + if (truncated_len > 0) { + memcpy(response, truncated_response, (size_t) truncated_len); + return truncated_len; + } return -1; } @@ -1212,6 +1245,10 @@ static ssize_t forward_udp_probe_one(const upstream_t *upstream, int timeout_ms, return got; } +static bool dns_response_truncated(const uint8_t *response, size_t response_len) { + return response_len >= 4 && (response[2] & 0x02u) != 0; +} + static ssize_t read_full(int fd, uint8_t *buf, size_t len) { size_t got = 0; while (got < len) { @@ -1224,45 +1261,59 @@ static ssize_t read_full(int fd, uint8_t *buf, size_t len) { return (ssize_t) got; } +static ssize_t forward_tcp_to_upstream(const upstream_t *upstream, int timeout_ms, + const uint8_t *query, size_t query_len, + uint8_t *response, size_t response_len) { + uint8_t lenbuf[2]; + uint8_t rlenbuf[2]; + uint16_t rlen; + int fd; + if (query_len > 65535) { + return -1; + } + lenbuf[0] = (uint8_t) ((query_len >> 8) & 0xffu); + lenbuf[1] = (uint8_t) (query_len & 0xffu); + fd = connect_upstream(upstream, SOCK_STREAM, timeout_ms); + if (fd < 0) { + return -1; + } + if (send(fd, lenbuf, 2, 0) != 2 || send(fd, query, query_len, 0) != (ssize_t) query_len) { + close(fd); + return -1; + } + if (read_full(fd, rlenbuf, 2) != 2) { + close(fd); + return -1; + } + rlen = (uint16_t) ((rlenbuf[0] << 8) | rlenbuf[1]); + if (rlen == 0 || rlen > response_len) { + close(fd); + return -1; + } + if (read_full(fd, response, rlen) != rlen) { + close(fd); + return -1; + } + close(fd); + return rlen; +} + static ssize_t forward_tcp(const config_t *cfg, const char *domain, const uint8_t *query, size_t query_len, uint8_t *response, size_t response_len, const char **route) { int i; - uint8_t lenbuf[2]; int count = 0; const upstream_t *upstreams; if (query_len > 65535) { return -1; } upstreams = select_upstreams(cfg, domain, &count, route); - lenbuf[0] = (uint8_t) ((query_len >> 8) & 0xffu); - lenbuf[1] = (uint8_t) (query_len & 0xffu); for (i = 0; i < count; i++) { - uint8_t rlenbuf[2]; - uint16_t rlen; - int fd = connect_upstream(&upstreams[i], SOCK_STREAM, cfg->timeout_ms); - if (fd < 0) { - continue; - } - if (send(fd, lenbuf, 2, 0) != 2 || send(fd, query, query_len, 0) != (ssize_t) query_len) { - close(fd); - continue; - } - if (read_full(fd, rlenbuf, 2) != 2) { - close(fd); - continue; - } - rlen = (uint16_t) ((rlenbuf[0] << 8) | rlenbuf[1]); - if (rlen == 0 || rlen > response_len) { - close(fd); - continue; - } - if (read_full(fd, response, rlen) != rlen) { - close(fd); - continue; + ssize_t got = forward_tcp_to_upstream(&upstreams[i], cfg->timeout_ms, + query, query_len, response, response_len); + if (got > 0) { + return got; } - close(fd); - return rlen; } return -1; } @@ -1677,7 +1728,9 @@ static void handle_dns_query(const config_t *cfg, const uint8_t *query, size_t q } if (forwarded > 0) { *response_len = (size_t) forwarded; - cache_store(domain, qtype, response, *response_len); + if (!dns_response_truncated(response, *response_len)) { + cache_store(domain, qtype, response, *response_len); + } g_stats.allowed++; g_stats.upstream_successes++; *action_out = route; @@ -1843,6 +1896,7 @@ static void write_health_response(int client) { "generation=%llu\nupstreams=%d\nsplit_upstreams=%d\nupstream_probe=%s\n" "upstream_probe_ms=%d\nupstream_probe_index=%d\nupstream_probe_rcode=%d\n" "queries=%llu\nblocked=%llu\nallowed=%llu\ncache_size=%d\ncache_entries=%d\n" + "upstream_tcp_fallbacks=%llu\nupstream_truncated_responses=%llu\n" "memory_rss_kb=%ld\nmemory_hwm_kb=%ld\ncpu_user_ms=%llu\n" "cpu_system_ms=%llu\ncpu_total_ms=%llu\n" "exact_index_size=%d\nsuffix_allow_trie_nodes=%d\nsuffix_block_trie_nodes=%d\n" @@ -1862,6 +1916,8 @@ static void write_health_response(int client) { (unsigned long long) g_stats.allowed, g_cfg.cache_size, cache_entry_count(), + (unsigned long long) g_stats.upstream_tcp_fallbacks, + (unsigned long long) g_stats.upstream_truncated_responses, memory_rss_kb, memory_hwm_kb, (unsigned long long) cpu_user_ms, @@ -1998,6 +2054,7 @@ static void handle_control(int fd) { "cache_size=%d\ncache_entries=%d\ncache_hits=%llu\ncache_misses=%llu\n" "cache_hit_rate_ppm=%llu\ncache_stores=%llu\ncache_expired=%llu\ncache_evictions=%llu\n" "upstream_requests=%llu\nupstream_successes=%llu\nupstream_failures=%llu\n" + "upstream_tcp_fallbacks=%llu\nupstream_truncated_responses=%llu\n" "avg_latency_ms=%llu\nmax_latency_ms=%llu\nupstream_avg_latency_ms=%llu\n" "reloads=%llu\nexact_index_size=%d\nsuffix_allow_trie_nodes=%d\n" "suffix_block_trie_nodes=%d\nrules_exact_allow=%d\nrules_suffix_allow=%d\nrules_exact_block=%d\n" @@ -2031,6 +2088,8 @@ static void handle_control(int fd) { (unsigned long long) g_stats.upstream_requests, (unsigned long long) g_stats.upstream_successes, (unsigned long long) g_stats.upstream_failures, + (unsigned long long) g_stats.upstream_tcp_fallbacks, + (unsigned long long) g_stats.upstream_truncated_responses, (unsigned long long) div_u64(g_stats.total_latency_ms, g_stats.queries), (unsigned long long) g_stats.max_latency_ms, (unsigned long long) div_u64(g_stats.upstream_latency_ms, g_stats.upstream_requests), From 14dbaf4ee147162dc5df8bf48ad31c6453d0f9ed Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 16:15:49 -0700 Subject: [PATCH 027/108] Improve DNS daemon negative cache stats --- .../main/assets/dnsd/arm64-v8a/afwall_dnsd | Bin 32960 -> 34384 bytes .../main/assets/dnsd/armeabi-v7a/afwall_dnsd | Bin 26900 -> 28020 bytes app/src/main/assets/dnsd/x86/afwall_dnsd | Bin 33836 -> 35692 bytes app/src/main/assets/dnsd/x86_64/afwall_dnsd | Bin 35232 -> 36992 bytes dnsdaemon/jni/afwall_dnsd.c | 169 +++++++++++++++--- 5 files changed, 141 insertions(+), 28 deletions(-) diff --git a/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd b/app/src/main/assets/dnsd/arm64-v8a/afwall_dnsd index 2b46eb8765b8594eaffae7af7d3c8fef3059f9d2..44d799543722590ddc51e76f9e053d0ea8dddbcc 100755 GIT binary patch delta 15083 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 delta 13586 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 Y&3XJ^9;RKJZ`18WYG9wUl#8|eKMwHl0{{R3 diff --git a/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd b/app/src/main/assets/dnsd/armeabi-v7a/afwall_dnsd index b2b762e6dc67f4606ae19b61d6e03012c1794ab1..0bb57ba8afa0d538e9a719a983f830e41b49552f 100755 GIT binary patch delta 12820 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�B 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 MG=!|clT4rf2lWMtKL7v# delta 11564 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 diff --git a/app/src/main/assets/dnsd/x86/afwall_dnsd b/app/src/main/assets/dnsd/x86/afwall_dnsd index 52701901b1d908da5cf90a74129adcbe1d338713..894a18d354df3608a368c20ed524a116c5c19639 100755 GIT binary patch delta 15521 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 delta 13674 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 delta 13165 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 diff --git a/dnsdaemon/jni/afwall_dnsd.c b/dnsdaemon/jni/afwall_dnsd.c index 6e603457e..4e57d091d 100644 --- a/dnsdaemon/jni/afwall_dnsd.c +++ b/dnsdaemon/jni/afwall_dnsd.c @@ -45,6 +45,9 @@ #define LOG_LINE_MAX 512 #define DEFAULT_PORT 5354 #define DEFAULT_TIMEOUT_MS 2500 +#define DEFAULT_POSITIVE_TTL 60 +#define DEFAULT_NEGATIVE_TTL 30 +#define MAX_CACHE_TTL 86400 typedef enum { DECISION_ALLOW = 0, @@ -132,6 +135,10 @@ typedef struct { uint64_t cache_hits; uint64_t cache_misses; uint64_t cache_stores; + uint64_t cache_positive_hits; + uint64_t cache_negative_hits; + uint64_t cache_positive_stores; + uint64_t cache_negative_stores; uint64_t cache_expired; uint64_t cache_evictions; uint64_t udp_queries; @@ -167,6 +174,7 @@ typedef struct { time_t expires_at; uint32_t hash; bool used; + bool negative; } cache_entry_t; static volatile sig_atomic_t g_running = 1; @@ -386,6 +394,21 @@ static int cache_entry_count(void) { return count; } +static int cache_entry_count_by_type(bool negative) { + int count = 0; + int i; + time_t now = time(NULL); + if (g_cache == NULL || g_cache_capacity <= 0) { + return 0; + } + for (i = 0; i < g_cache_capacity; i++) { + if (g_cache[i].used && g_cache[i].expires_at > now && g_cache[i].negative == negative) { + count++; + } + } + return count; +} + static void add_log(const char *domain, const char *action, int latency_ms) { log_entry_t *entry = &g_logs[g_log_pos % LOG_RING]; entry->seq = ++g_log_seq; @@ -930,17 +953,60 @@ static size_t skip_name(const uint8_t *packet, size_t len, size_t pos) { return len + 1; } -static uint32_t extract_min_ttl(const uint8_t *packet, size_t len) { +static bool read_rr_header(const uint8_t *packet, size_t len, size_t *pos, + uint16_t *type, uint32_t *ttl, uint16_t *rdlen, + size_t *rdata_pos) { + size_t rr_pos = skip_name(packet, len, *pos); + if (rr_pos + 10 > len) { + return false; + } + *type = read_u16(packet + rr_pos); + *ttl = read_u32(packet + rr_pos + 4); + *rdlen = read_u16(packet + rr_pos + 8); + *rdata_pos = rr_pos + 10; + if (*rdata_pos + *rdlen > len) { + return false; + } + *pos = *rdata_pos + *rdlen; + return true; +} + +static uint32_t clamp_cache_ttl(uint32_t ttl, uint32_t fallback) { + if (ttl == 0 || ttl == UINT32_MAX) { + ttl = fallback; + } + if (ttl > MAX_CACHE_TTL) { + ttl = MAX_CACHE_TTL; + } + return ttl; +} + +static bool response_is_negative_cache(const uint8_t *response, size_t response_len) { + uint16_t flags; + uint16_t an; + uint16_t rcode; + if (response_len < 12) { + return false; + } + flags = read_u16(response + 2); + rcode = flags & 0x000fu; + an = read_u16(response + 6); + return rcode == 3 || (rcode == 0 && an == 0); +} + +static uint32_t extract_cache_ttl(const uint8_t *packet, size_t len, bool negative) { uint16_t qd; uint16_t an; + uint16_t ns; size_t pos = 12; uint16_t i; - uint32_t min_ttl = 60; + uint32_t min_ttl = UINT32_MAX; if (len < 12) { return 0; } qd = read_u16(packet + 4); an = read_u16(packet + 6); + ns = read_u16(packet + 8); for (i = 0; i < qd; i++) { pos = skip_name(packet, len, pos); if (pos + 4 > len) { @@ -948,37 +1014,48 @@ static uint32_t extract_min_ttl(const uint8_t *packet, size_t len) { } pos += 4; } - if (an == 0) { - return 30; - } - min_ttl = UINT32_MAX; for (i = 0; i < an; i++) { - uint32_t ttl; + uint16_t type; uint16_t rdlen; - pos = skip_name(packet, len, pos); - if (pos + 10 > len) { - return 30; + uint32_t ttl; + size_t rdata_pos; + if (!read_rr_header(packet, len, &pos, &type, &ttl, &rdlen, &rdata_pos)) { + return negative ? DEFAULT_NEGATIVE_TTL : 0; } - ttl = read_u32(packet + pos + 4); - rdlen = read_u16(packet + pos + 8); - if (ttl < min_ttl) { + if (!negative && ttl < min_ttl) { min_ttl = ttl; } - pos += 10 + rdlen; - if (pos > len) { - return 30; - } } - if (min_ttl == UINT32_MAX || min_ttl == 0) { - return 30; + if (!negative) { + return clamp_cache_ttl(min_ttl, DEFAULT_POSITIVE_TTL); } - if (min_ttl > 86400) { - return 86400; + for (i = 0; i < ns; i++) { + uint16_t type; + uint16_t rdlen; + uint32_t ttl; + size_t rdata_pos; + size_t rpos; + if (!read_rr_header(packet, len, &pos, &type, &ttl, &rdlen, &rdata_pos)) { + return DEFAULT_NEGATIVE_TTL; + } + if (type != 6) { + continue; + } + rpos = skip_name(packet, len, rdata_pos); + rpos = skip_name(packet, len, rpos); + if (rpos + 20 <= rdata_pos + rdlen && rpos + 20 <= len) { + uint32_t minimum = read_u32(packet + rpos + 16); + uint32_t negative_ttl = ttl < minimum ? ttl : minimum; + if (negative_ttl < min_ttl) { + min_ttl = negative_ttl; + } + } } - return min_ttl; + return clamp_cache_ttl(min_ttl, DEFAULT_NEGATIVE_TTL); } -static bool cache_lookup(const char *domain, uint16_t qtype, const uint8_t *query, uint8_t *out, size_t *out_len) { +static bool cache_lookup(const char *domain, uint16_t qtype, const uint8_t *query, + uint8_t *out, size_t *out_len, bool *negative) { uint32_t h = hash_domain(domain, qtype); uint32_t start; uint32_t i; @@ -1004,6 +1081,9 @@ static bool cache_lookup(const char *domain, uint16_t qtype, const uint8_t *quer out[0] = query[0]; out[1] = query[1]; *out_len = entry->response_len; + if (negative != NULL) { + *negative = entry->negative; + } return true; } } @@ -1033,12 +1113,14 @@ static void cache_store(const char *domain, uint16_t qtype, const uint8_t *respo uint32_t probe_count; time_t now = time(NULL); bool evicting = false; + bool negative; if (g_cache == NULL || g_cache_capacity <= 0 || response_len < 12 || response_len > MAX_PACKET || !response_cacheable(response, response_len)) { return; } - ttl = extract_min_ttl(response, response_len); + negative = response_is_negative_cache(response, response_len); + ttl = extract_cache_ttl(response, response_len, negative); if (ttl == 0) { return; } @@ -1077,7 +1159,13 @@ static void cache_store(const char *domain, uint16_t qtype, const uint8_t *respo entry->response_len = response_len; entry->expires_at = now + ttl; entry->used = true; + entry->negative = negative; g_stats.cache_stores++; + if (negative) { + g_stats.cache_negative_stores++; + } else { + g_stats.cache_positive_stores++; + } } static int connect_upstream(const upstream_t *upstream, int socktype, int timeout_ms) { @@ -1686,6 +1774,7 @@ static void handle_dns_query(const config_t *cfg, const uint8_t *query, size_t q struct timeval upstream_start; struct timeval upstream_end; int upstream_latency_ms; + bool cache_negative = false; gettimeofday(&start, NULL); g_stats.queries++; if (tcp) { @@ -1708,11 +1797,16 @@ static void handle_dns_query(const config_t *cfg, const uint8_t *query, size_t q finish_dns_query(domain, reason, &start); return; } - if (cache_lookup(domain, qtype, query, response, response_len)) { + if (cache_lookup(domain, qtype, query, response, response_len, &cache_negative)) { g_stats.cache_hits++; + if (cache_negative) { + g_stats.cache_negative_hits++; + } else { + g_stats.cache_positive_hits++; + } g_stats.allowed++; - *action_out = "cache"; - finish_dns_query(domain, "cache", &start); + *action_out = cache_negative ? "cache_negative" : "cache"; + finish_dns_query(domain, *action_out, &start); return; } g_stats.cache_misses++; @@ -1896,6 +1990,9 @@ static void write_health_response(int client) { "generation=%llu\nupstreams=%d\nsplit_upstreams=%d\nupstream_probe=%s\n" "upstream_probe_ms=%d\nupstream_probe_index=%d\nupstream_probe_rcode=%d\n" "queries=%llu\nblocked=%llu\nallowed=%llu\ncache_size=%d\ncache_entries=%d\n" + "cache_positive_entries=%d\ncache_negative_entries=%d\n" + "cache_positive_hits=%llu\ncache_negative_hits=%llu\n" + "cache_positive_stores=%llu\ncache_negative_stores=%llu\n" "upstream_tcp_fallbacks=%llu\nupstream_truncated_responses=%llu\n" "memory_rss_kb=%ld\nmemory_hwm_kb=%ld\ncpu_user_ms=%llu\n" "cpu_system_ms=%llu\ncpu_total_ms=%llu\n" @@ -1916,6 +2013,12 @@ static void write_health_response(int client) { (unsigned long long) g_stats.allowed, g_cfg.cache_size, cache_entry_count(), + cache_entry_count_by_type(false), + cache_entry_count_by_type(true), + (unsigned long long) g_stats.cache_positive_hits, + (unsigned long long) g_stats.cache_negative_hits, + (unsigned long long) g_stats.cache_positive_stores, + (unsigned long long) g_stats.cache_negative_stores, (unsigned long long) g_stats.upstream_tcp_fallbacks, (unsigned long long) g_stats.upstream_truncated_responses, memory_rss_kb, @@ -2052,7 +2155,11 @@ static void handle_control(int fd) { "memory_rss_kb=%ld\nmemory_hwm_kb=%ld\ncpu_user_ms=%llu\n" "cpu_system_ms=%llu\ncpu_total_ms=%llu\n" "cache_size=%d\ncache_entries=%d\ncache_hits=%llu\ncache_misses=%llu\n" - "cache_hit_rate_ppm=%llu\ncache_stores=%llu\ncache_expired=%llu\ncache_evictions=%llu\n" + "cache_positive_entries=%d\ncache_negative_entries=%d\n" + "cache_positive_hits=%llu\ncache_negative_hits=%llu\n" + "cache_hit_rate_ppm=%llu\ncache_stores=%llu\n" + "cache_positive_stores=%llu\ncache_negative_stores=%llu\n" + "cache_expired=%llu\ncache_evictions=%llu\n" "upstream_requests=%llu\nupstream_successes=%llu\nupstream_failures=%llu\n" "upstream_tcp_fallbacks=%llu\nupstream_truncated_responses=%llu\n" "avg_latency_ms=%llu\nmax_latency_ms=%llu\nupstream_avg_latency_ms=%llu\n" @@ -2080,9 +2187,15 @@ static void handle_control(int fd) { cache_entry_count(), (unsigned long long) g_stats.cache_hits, (unsigned long long) g_stats.cache_misses, + cache_entry_count_by_type(false), + cache_entry_count_by_type(true), + (unsigned long long) g_stats.cache_positive_hits, + (unsigned long long) g_stats.cache_negative_hits, (unsigned long long) div_u64(g_stats.cache_hits * 1000000ULL, g_stats.cache_hits + g_stats.cache_misses), (unsigned long long) g_stats.cache_stores, + (unsigned long long) g_stats.cache_positive_stores, + (unsigned long long) g_stats.cache_negative_stores, (unsigned long long) g_stats.cache_expired, (unsigned long long) g_stats.cache_evictions, (unsigned long long) g_stats.upstream_requests, From 7298c4f4919813df5bfddd4b4c2a7645fe07cb76 Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 16:21:21 -0700 Subject: [PATCH 028/108] Add DNS blocklist presets --- .../preferences/RulesPreferenceFragment.java | 83 +++++++++++++++++++ .../java/dev/ukanth/ufirewall/util/G.java | 4 + app/src/main/res/values/strings.xml | 18 ++++ app/src/main/res/xml/rules_preferences.xml | 6 ++ 4 files changed, 111 insertions(+) diff --git a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java index 3f64c56ab..27f220e8f 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java +++ b/app/src/main/java/dev/ukanth/ufirewall/preferences/RulesPreferenceFragment.java @@ -20,6 +20,8 @@ import com.afollestad.materialdialogs.MaterialDialog; import java.io.File; +import java.util.ArrayList; +import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -79,6 +81,14 @@ private void wireDnsBlocklistActions() { }); } + Preference blocklistPresets = findPreference("dnsHijackBlocklistPresets"); + if (blocklistPresets != null) { + blocklistPresets.setOnPreferenceClickListener(preference -> { + showDnsBlocklistPresetDialog(); + return true; + }); + } + Preference updateBlocklists = findPreference("dnsHijackUpdateBlocklists"); if (updateBlocklists != null) { updateBlocklists.setOnPreferenceClickListener(preference -> { @@ -261,6 +271,79 @@ private String getClipboardText() { return text == null ? "" : text.toString(); } + private void showDnsBlocklistPresetDialog() { + if (getActivity() == null) { + return; + } + String[] names = getResources().getStringArray(R.array.dns_hijack_blocklist_preset_names); + String[] urls = getResources().getStringArray(R.array.dns_hijack_blocklist_preset_urls); + new MaterialDialog.Builder(getActivity()) + .title(R.string.dns_hijack_blocklist_presets_title) + .content(R.string.dns_hijack_blocklist_presets_dialog_summary) + .items(names) + .itemsCallbackMultiChoice(selectedPresetIndices(urls), (dialog, which, text) -> { + int added = 0; + int existing = 0; + for (int index : which) { + if (index < 0 || index >= urls.length) { + continue; + } + if (G.appendDnsHijackBlocklistUrl(urls[index])) { + added++; + } else { + existing++; + } + } + DnsBlocklistUpdateReceiver.scheduleOrCancel(ctx); + showDnsBlocklistPresetResult(added, existing); + return true; + }) + .positiveText(R.string.add) + .negativeText(R.string.Cancel) + .show(); + } + + private Integer[] selectedPresetIndices(String[] urls) { + ArrayList selected = new ArrayList<>(); + String configured = G.dnsHijackBlocklistUrls(); + if (configured == null || configured.trim().isEmpty()) { + return null; + } + for (int i = 0; i < urls.length; i++) { + if (containsConfiguredBlocklistUrl(configured, urls[i])) { + selected.add(i); + } + } + return selected.isEmpty() ? null : selected.toArray(new Integer[0]); + } + + private boolean containsConfiguredBlocklistUrl(String configured, String url) { + String normalizedUrl = url == null ? "" : url.trim().toLowerCase(Locale.US); + if (normalizedUrl.isEmpty()) { + return false; + } + String[] entries = configured.split("[\\r\\n,]+"); + for (String entry : entries) { + String normalizedEntry = entry == null ? "" : entry.trim().toLowerCase(Locale.US); + if (normalizedUrl.equals(normalizedEntry)) { + return true; + } + } + return false; + } + + private void showDnsBlocklistPresetResult(int added, int existing) { + if (getActivity() == null) { + return; + } + new MaterialDialog.Builder(getActivity()) + .title(R.string.dns_hijack_blocklist_presets_title) + .content(getString(R.string.dns_hijack_blocklist_presets_result, + added, existing)) + .positiveText(R.string.OK) + .show(); + } + private void runDnsBlocklistRollback() { runBlocklistTask(() -> DnsBlocklistManager.restorePrevious(ctx)); } diff --git a/app/src/main/java/dev/ukanth/ufirewall/util/G.java b/app/src/main/java/dev/ukanth/ufirewall/util/G.java index 816a8d11b..8fe81fec5 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/util/G.java +++ b/app/src/main/java/dev/ukanth/ufirewall/util/G.java @@ -403,6 +403,10 @@ public static String dnsHijackBlocklistUrls() { return dnsPolicyPrefs().getString(DNS_HIJACK_BLOCKLIST_URLS, ""); } + public static boolean appendDnsHijackBlocklistUrl(String url) { + return appendLinePreference(dnsPolicyPrefs(), DNS_HIJACK_BLOCKLIST_URLS, url); + } + public static boolean dnsHijackScheduledBlocklistUpdates() { return dnsPolicyPrefs().getBoolean(DNS_HIJACK_SCHEDULED_BLOCKLIST_UPDATES, false); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6753e165f..51dd71e94 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -351,6 +351,10 @@ Regular expressions that block matching queries. Blocklist URLs One remote hosts, domain, Pi-hole, or AdBlock-style list URL per line. + Blocklist presets + Add maintained DNS blocklist sources to the URL list. + Selected presets are added to the configured URL list. Run update to download and activate them. + Added %1$d preset URL(s). Already configured: %2$d. Scheduled blocklist updates Periodically download configured DNS blocklist URLs and reload the daemon after a successful compile. Blocklist update interval @@ -376,6 +380,20 @@ DNS daemon reload requested. DNS daemon restart requested. DNS daemon stop requested. + + + StevenBlack Unified hosts + AdAway hosts + OISD small + Hagezi Light + + + + https://raw.githubusercontent.com/stevenblack/hosts/master/hosts + https://adaway.org/hosts.txt + https://small.oisd.nl/ + https://raw.githubusercontent.com/hagezi/dns-blocklists/main/domains/light.txt + DNS Queries View recent daemon DNS queries and quickly add allow or block rules. %1$d DNS queries loaded. diff --git a/app/src/main/res/xml/rules_preferences.xml b/app/src/main/res/xml/rules_preferences.xml index 7bd46d2df..811c00385 100644 --- a/app/src/main/res/xml/rules_preferences.xml +++ b/app/src/main/res/xml/rules_preferences.xml @@ -223,6 +223,12 @@ android:summary="@string/dns_hijack_blocklist_urls_summary" android:title="@string/dns_hijack_blocklist_urls_title" /> + + Date: Fri, 26 Jun 2026 16:24:43 -0700 Subject: [PATCH 029/108] Report DNS blocklist update metadata --- .../ufirewall/dns/DnsBlocklistManager.java | 57 ++++++++++++++++--- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsBlocklistManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsBlocklistManager.java index abf4cf524..b8443d72f 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsBlocklistManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsBlocklistManager.java @@ -61,6 +61,7 @@ public static Result importFromUri(Context context, Uri uri) { result.message = "Unable to open selected blocklist"; return result; } + result.sources = 1; parsePossiblyJsonStream(input, result); activate(context, result); return result; @@ -80,6 +81,7 @@ public static Result importFromText(Context context, String text) { result.message = "No DNS blocklist text was provided"; return result; } + result.sources = 1; try (InputStream input = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8))) { parsePossiblyJsonStream(input, result); activate(context, result); @@ -147,8 +149,10 @@ public static Result restorePrevious(Context context) { try { copyIfExists(exactBackup, new File(dir, EXACT_FILE)); copyIfExists(suffixBackup, new File(dir, SUFFIX_FILE)); - writeMetadata(context, "rollback", countLines(new File(dir, EXACT_FILE)), - countLines(new File(dir, SUFFIX_FILE)), 0, 0, 0); + result.finish(); + writeMetadata(context, "rollback", "rollback", countLines(new File(dir, EXACT_FILE)), + countLines(new File(dir, SUFFIX_FILE)), 0, 0, 0, 0, 0, + result.durationMs()); result.message = "Restored previous DNS blocklist"; return result; } catch (IOException e) { @@ -555,11 +559,13 @@ private static void activate(Context context, Result result) throws IOException copyIfExists(suffix, new File(dir, SUFFIX_BACKUP)); writeRuleFile(new File(dir, EXACT_FILE + ".tmp"), exact, result.exactRules); writeRuleFile(new File(dir, SUFFIX_FILE + ".tmp"), suffix, result.suffixRules); - writeMetadata(context, result.sourceLabel, result.exactRules.size(), result.suffixRules.size(), - result.duplicates, result.invalid, result.skipped); + result.finish(); + writeMetadata(context, result.sourceLabel, "active", result.exactRules.size(), result.suffixRules.size(), + result.duplicates, result.invalid, result.skipped, result.sources, result.lines, + result.durationMs()); result.message = "Activated DNS blocklist: " + result.exactRules.size() + " exact, " + result.suffixRules.size() + " wildcard"; - ApplicationErrorLog.add(context, result.message); + ApplicationErrorLog.add(context, result.message + " in " + formatDuration(result.durationMs())); } private static void writeRuleFile(File tmp, File target, Set rules) throws IOException { @@ -580,17 +586,27 @@ private static void writeRuleFile(File tmp, File target, Set rules) thro } } - private static void writeMetadata(Context context, String source, int exact, int suffix, - int duplicates, int invalid, int skipped) throws IOException { + private static void writeMetadata(Context context, String source, String status, int exact, int suffix, + int duplicates, int invalid, int skipped, int sources, + int lines, long durationMs) throws IOException { File meta = new File(blocklistDir(context), META_FILE); String timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US).format(new Date()); try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(meta, false), StandardCharsets.UTF_8)) { writer.write("updated="); writer.write(timestamp); writer.write('\n'); + writer.write("status="); + writer.write(status == null ? "unknown" : status); + writer.write('\n'); writer.write("source="); writer.write(source == null ? "unknown" : source); writer.write('\n'); + writer.write("sources="); + writer.write(String.valueOf(sources)); + writer.write('\n'); + writer.write("lines="); + writer.write(String.valueOf(lines)); + writer.write('\n'); writer.write("exact="); writer.write(String.valueOf(exact)); writer.write('\n'); @@ -606,7 +622,17 @@ private static void writeMetadata(Context context, String source, int exact, int writer.write("skipped="); writer.write(String.valueOf(skipped)); writer.write('\n'); + writer.write("duration_ms="); + writer.write(String.valueOf(durationMs)); + writer.write('\n'); + } + } + + private static String formatDuration(long durationMs) { + if (durationMs < 1000L) { + return durationMs + "ms"; } + return String.format(Locale.US, "%.1fs", durationMs / 1000.0d); } private static int countLines(File file) throws IOException { @@ -645,6 +671,8 @@ public static final class Result { private final Set exactRules = new LinkedHashSet<>(); private final Set suffixRules = new LinkedHashSet<>(); private final StringBuilder notes = new StringBuilder(); + private final long startedAtMs = System.currentTimeMillis(); + private long finishedAtMs; private String sourceLabel; public int lines; public int duplicates; @@ -658,6 +686,17 @@ private Result(String sourceLabel) { this.sourceLabel = sourceLabel; } + private void finish() { + if (finishedAtMs == 0L) { + finishedAtMs = System.currentTimeMillis(); + } + } + + private long durationMs() { + long end = finishedAtMs == 0L ? System.currentTimeMillis() : finishedAtMs; + return Math.max(0L, end - startedAtMs); + } + public boolean hasRules() { return !exactRules.isEmpty() || !suffixRules.isEmpty(); } @@ -665,11 +704,15 @@ public boolean hasRules() { public String summary() { StringBuilder summary = new StringBuilder(); summary.append(message); + summary.append("\nStatus: ").append(failed ? "failed" : "complete"); + summary.append("\nSources: ").append(sources); + summary.append("\nLines: ").append(lines); summary.append("\nExact: ").append(exactRules.size()); summary.append("\nWildcard: ").append(suffixRules.size()); summary.append("\nDuplicates: ").append(duplicates); summary.append("\nInvalid: ").append(invalid); summary.append("\nSkipped: ").append(skipped); + summary.append("\nDuration: ").append(formatDuration(durationMs())); if (notes.length() > 0) { summary.append("\n\n").append(notes); } From 647a59968d5cf6142b1f22946d1ff0c44f6c36f6 Mon Sep 17 00:00:00 2001 From: Mainkill1 Date: Fri, 26 Jun 2026 16:33:18 -0700 Subject: [PATCH 030/108] Add DNS protection dashboard summary --- .../ufirewall/activity/LogHubActivity.java | 96 +++++++++++++++- .../ufirewall/dns/DnsHijackManager.java | 105 ++++++++++++++++++ app/src/main/res/layout/log_hub.xml | 86 ++++++++++++++ app/src/main/res/values/strings.xml | 2 + 4 files changed, 288 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/dev/ukanth/ufirewall/activity/LogHubActivity.java b/app/src/main/java/dev/ukanth/ufirewall/activity/LogHubActivity.java index e4803eeda..0d834500c 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/activity/LogHubActivity.java +++ b/app/src/main/java/dev/ukanth/ufirewall/activity/LogHubActivity.java @@ -11,7 +11,7 @@ import android.os.Environment; import android.os.Handler; import android.os.Looper; -import android.view.View; +import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; @@ -41,6 +41,8 @@ import dev.ukanth.ufirewall.BuildConfig; import dev.ukanth.ufirewall.R; import dev.ukanth.ufirewall.Api; +import dev.ukanth.ufirewall.broadcast.DnsBlocklistUpdateReceiver; +import dev.ukanth.ufirewall.dns.DnsBlocklistManager; import dev.ukanth.ufirewall.dns.DnsHijackManager; import dev.ukanth.ufirewall.log.Log; import dev.ukanth.ufirewall.log.LogInfo; @@ -59,6 +61,11 @@ public class LogHubActivity extends AppCompatActivity { private static final int EXPORT_APPLICATION_ERRORS = 4; private static final int EXPORT_DNS_QUERIES = 5; + private final ExecutorService dashboardExecutor = Executors.newSingleThreadExecutor(); + private final Handler mainHandler = new Handler(Looper.getMainLooper()); + private TextView dnsDashboardStatus; + private TextView dnsDashboardDetails; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -76,6 +83,14 @@ protected void onCreate(Bundle savedInstanceState) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); } + dnsDashboardStatus = findViewById(R.id.log_hub_dns_dashboard_status); + dnsDashboardDetails = findViewById(R.id.log_hub_dns_dashboard_details); + findViewById(R.id.log_hub_dns_dashboard_queries) + .setOnClickListener(v -> startActivity(new Intent(this, DnsQueriesActivity.class))); + findViewById(R.id.log_hub_dns_dashboard_update) + .setOnClickListener(v -> runDashboardBlocklistUpdate()); + findViewById(R.id.log_hub_dns_dashboard_repair) + .setOnClickListener(v -> runDashboardDnsRepair()); findViewById(R.id.log_hub_blocked_requests).setOnClickListener(v -> openBlockedRequests()); findViewById(R.id.log_hub_dns_queries).setOnClickListener(v -> startActivity(new Intent(this, DnsQueriesActivity.class))); findViewById(R.id.log_hub_iptables).setOnClickListener(v -> startActivity(new Intent(this, RulesActivity.class))); @@ -85,11 +100,90 @@ protected void onCreate(Bundle savedInstanceState) { findViewById(R.id.log_hub_export_logs).setOnClickListener(v -> showExportLogSelection()); } + @Override + protected void onResume() { + super.onResume(); + loadDnsDashboard(); + } + + @Override + protected void onDestroy() { + dashboardExecutor.shutdownNow(); + super.onDestroy(); + } + private void openBlockedRequests() { Intent intent = new Intent(this, G.oldLogView() ? OldLogActivity.class : LogActivity.class); startActivity(intent); } + private void loadDnsDashboard() { + if (dashboardExecutor.isShutdown() || dnsDashboardStatus == null || dnsDashboardDetails == null) { + return; + } + dnsDashboardStatus.setText(R.string.dns_dashboard_loading); + dnsDashboardDetails.setText(R.string.dns_dashboard_loading); + dashboardExecutor.execute(() -> { + DnsHijackManager.DnsDashboardSnapshot snapshot = + DnsHijackManager.getDashboardSnapshot(this); + mainHandler.post(() -> { + dnsDashboardStatus.setText(snapshot.statusLine); + dnsDashboardDetails.setText(snapshot.detailLine); + }); + }); + } + + private void runDashboardBlocklistUpdate() { + if (dashboardExecutor.isShutdown()) { + return; + } + dnsDashboardStatus.setText(R.string.dns_hijack_update_blocklists_title); + dashboardExecutor.execute(() -> { + DnsBlocklistManager.Result result = DnsBlocklistManager.updateFromConfiguredUrls(this); + mainHandler.post(() -> handleDashboardBlocklistResult(result)); + }); + } + + private void handleDashboardBlocklistResult(DnsBlocklistManager.Result result) { + if (result == null) { + return; + } + if (!result.failed) { + Api.setRulesUpToDate(false); + if (G.enableDnsHijack()) { + DnsHijackManager.requestReload(this); + } + DnsBlocklistUpdateReceiver.scheduleOrCancel(this); + Api.toast(this, getString(R.string.dns_hijack_blocklist_active)); + } else { + Api.toast(this, getString(R.string.dns_hijack_blocklist_failed)); + } + new MaterialDialog.Builder(this) + .title(result.failed ? R.string.dns_hijack_blocklist_failed : R.string.dns_hijack_blocklist_active) + .content(result.summary()) + .positiveText(R.string.OK) + .show(); + loadDnsDashboard(); + } + + private void runDashboardDnsRepair() { + String message = getString(R.string.dns_diagnostics_repair_queued); + dnsDashboardStatus.setText(message); + DnsHijackManager.repairDnsProtection(this, new RootCommand.Callback() { + @Override + public void cbFunc(RootCommand state) { + mainHandler.post(() -> { + if (state.exitCode == 0) { + Api.toast(LogHubActivity.this, message); + } else { + Api.toast(LogHubActivity.this, getString(R.string.error_apply)); + } + loadDnsDashboard(); + }); + } + }); + } + private void showExportLogSelection() { List items = new ArrayList<>(); List itemValues = new ArrayList<>(); diff --git a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java index bc40ea3f6..229d23ec6 100644 --- a/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java +++ b/app/src/main/java/dev/ukanth/ufirewall/dns/DnsHijackManager.java @@ -19,8 +19,10 @@ import java.net.SocketTimeoutException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import dev.ukanth.ufirewall.Api; import dev.ukanth.ufirewall.R; @@ -227,6 +229,55 @@ public static List getRecentQueries(Context context) { return parseQueryEntries(queryControl(context, "logs")); } + public static DnsDashboardSnapshot getDashboardSnapshot(Context context) { + String status = queryControl(context, "status"); + String health = queryControl(context, "health"); + Map statusValues = parseKeyValueLines(status); + Map healthValues = parseKeyValueLines(health); + Map blocklistValues = parseKeyValueLines(DnsBlocklistManager.getSummary(context)); + + boolean enabled = G.enableDnsHijack(); + boolean running = "1".equals(firstValue(statusValues, healthValues, "running")) + || status.contains("running=1") || health.contains("running=1"); + long queries = parseLong(firstValue(statusValues, healthValues, "queries"), 0L); + long blocked = parseLong(firstValue(statusValues, healthValues, "blocked"), 0L); + long upstreamLatency = parseLong(firstValue(healthValues, statusValues, "upstream_probe_ms"), -1L); + String upstreamProbe = firstValue(healthValues, statusValues, "upstream_probe"); + String profile = G.activeDnsHijackPolicyProfile(); + if (profile == null || profile.trim().isEmpty()) { + profile = "global"; + } + String blockPercent = queries <= 0L + ? "0%" + : String.format(Locale.US, "%.1f%%", (blocked * 100.0d) / queries); + String protection; + if (!enabled) { + protection = "DNS protection disabled"; + } else if (running) { + protection = "DNS protection active"; + } else { + protection = "DNS protection enabled, daemon unavailable"; + } + + String statusLine = protection + " | " + queries + " queries | " + blockPercent + " blocked"; + String blocklistUpdated = blocklistValues.containsKey("updated") + ? blocklistValues.get("updated") + : "never"; + String upstream = upstreamProbe == null || upstreamProbe.trim().isEmpty() + ? "unknown" + : upstreamProbe; + if (upstreamLatency >= 0L) { + upstream += " " + upstreamLatency + "ms"; + } + String details = "Daemon: " + (running ? "running" : "stopped") + + " | Redirect setting: " + (enabled ? "enabled" : "disabled") + + " | Profile: " + profile + + (G.dnsHijackUseProfilePolicy() ? " override" : " global") + + "\nUpstream: " + upstream + + " | Blocklist updated: " + blocklistUpdated; + return new DnsDashboardSnapshot(statusLine, details); + } + public static List getHistoricalQueries(Context context, String filter) { String cleanFilter = sanitizeHistoryFilter(filter); String command = cleanFilter.isEmpty() ? "history" : "history " + cleanFilter; @@ -362,6 +413,50 @@ private static List parseQueryEntries(String raw) { return entries; } + private static Map parseKeyValueLines(String raw) { + Map values = new HashMap<>(); + if (raw == null) { + return values; + } + String[] lines = raw.split("\\r?\\n"); + for (String line : lines) { + if (line == null) { + continue; + } + int separator = line.indexOf('='); + if (separator <= 0) { + continue; + } + String key = line.substring(0, separator).trim(); + String value = line.substring(separator + 1).trim(); + if (!key.isEmpty()) { + values.put(key, value); + } + } + return values; + } + + private static String firstValue(Map preferred, + Map fallback, + String key) { + String value = preferred.get(key); + if (value == null || value.trim().isEmpty()) { + value = fallback.get(key); + } + return value == null ? "" : value.trim(); + } + + private static long parseLong(String value, long fallback) { + if (value == null || value.trim().isEmpty()) { + return fallback; + } + try { + return Long.parseLong(value.trim()); + } catch (NumberFormatException e) { + return fallback; + } + } + private static String sanitizeHistoryFilter(String filter) { if (filter == null) { return ""; @@ -802,6 +897,16 @@ public String displayLine() { } } + public static final class DnsDashboardSnapshot { + public final String statusLine; + public final String detailLine; + + private DnsDashboardSnapshot(String statusLine, String detailLine) { + this.statusLine = statusLine; + this.detailLine = detailLine; + } + } + private static final class UpstreamTarget { private final String host; private final int port; diff --git a/app/src/main/res/layout/log_hub.xml b/app/src/main/res/layout/log_hub.xml index 0a101d50e..765776580 100644 --- a/app/src/main/res/layout/log_hub.xml +++ b/app/src/main/res/layout/log_hub.xml @@ -25,6 +25,92 @@ android:orientation="vertical" android:padding="12dp"> + + + + + + + + + + + + + + + + + +