From cb08d9ddeb74b2fdcaf4c9edf4f5e5fd455e3b61 Mon Sep 17 00:00:00 2001 From: PeratX <1215714524@qq.com> Date: Wed, 23 Oct 2019 20:13:11 +0800 Subject: [PATCH] DaedalusVpnService: listen network change and update upstream DNS --- .../java/org/itxtech/daedalus/Daedalus.java | 21 ++-- .../fragment/GlobalConfigFragment.java | 8 -- .../daedalus/server/AbstractDnsServer.java | 14 ++- .../daedalus/service/DaedalusVpnService.java | 116 ++++++++++++------ app/src/main/res/values-v21/styles.xml | 20 --- app/src/main/res/values-zh-rCN/strings.xml | 2 + app/src/main/res/values-zh-rTW/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + app/src/main/res/values/styles.xml | 17 ++- app/src/main/res/xml/perf_settings.xml | 8 +- 10 files changed, 123 insertions(+), 87 deletions(-) delete mode 100644 app/src/main/res/values-v21/styles.xml diff --git a/app/src/main/java/org/itxtech/daedalus/Daedalus.java b/app/src/main/java/org/itxtech/daedalus/Daedalus.java index 2043577..bfc3210 100644 --- a/app/src/main/java/org/itxtech/daedalus/Daedalus.java +++ b/app/src/main/java/org/itxtech/daedalus/Daedalus.java @@ -16,10 +16,14 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonParseException; import com.google.gson.stream.JsonReader; import org.itxtech.daedalus.activity.MainActivity; +import org.itxtech.daedalus.server.AbstractDnsServer; import org.itxtech.daedalus.server.DnsServer; import org.itxtech.daedalus.server.DnsServerHelper; import org.itxtech.daedalus.service.DaedalusVpnService; -import org.itxtech.daedalus.util.*; +import org.itxtech.daedalus.util.Configurations; +import org.itxtech.daedalus.util.Logger; +import org.itxtech.daedalus.util.Rule; +import org.itxtech.daedalus.util.RuleResolver; import java.io.File; import java.util.ArrayList; @@ -206,19 +210,8 @@ public class Daedalus extends Application { } public static void activateService(Context context) { - DaedalusVpnService.primaryServer = DnsServerHelper.getServerById(DnsServerHelper.getPrimary()); - DaedalusVpnService.secondaryServer = DnsServerHelper.getServerById(DnsServerHelper.getSecondary()); - if (getPrefs().getBoolean("settings_use_system_dns", false)) { - String[] servers = DnsServersDetector.getServers(context); - if (servers != null) { - if (servers.length >= 2) { - DaedalusVpnService.primaryServer = new DnsServer(servers[0], 0); - DaedalusVpnService.secondaryServer = new DnsServer(servers[1], 0); - } else { - DaedalusVpnService.primaryServer = DaedalusVpnService.secondaryServer = new DnsServer(servers[0]); - } - } - } + DaedalusVpnService.primaryServer = (AbstractDnsServer) DnsServerHelper.getServerById(DnsServerHelper.getPrimary()).clone(); + DaedalusVpnService.secondaryServer = (AbstractDnsServer) DnsServerHelper.getServerById(DnsServerHelper.getSecondary()).clone(); if (getInstance().prefs.getBoolean("settings_foreground", false) && Build.VERSION.SDK_INT > Build.VERSION_CODES.O) { Logger.info("Starting foreground service"); diff --git a/app/src/main/java/org/itxtech/daedalus/fragment/GlobalConfigFragment.java b/app/src/main/java/org/itxtech/daedalus/fragment/GlobalConfigFragment.java index 8ad7410..56a9c19 100644 --- a/app/src/main/java/org/itxtech/daedalus/fragment/GlobalConfigFragment.java +++ b/app/src/main/java/org/itxtech/daedalus/fragment/GlobalConfigFragment.java @@ -39,7 +39,6 @@ public class GlobalConfigFragment extends PreferenceFragmentCompat { add("secondary_server"); }}) { ListPreference listPref = findPreference(k); - listPref.setVisible(visible); listPref.setEntries(DnsServerHelper.getNames(Daedalus.getInstance())); listPref.setEntryValues(DnsServerHelper.getIds()); listPref.setSummary(DnsServerHelper.getDescription(listPref.getValue(), Daedalus.getInstance())); @@ -110,13 +109,6 @@ public class GlobalConfigFragment extends PreferenceFragmentCompat { updateOptions(advanced.isChecked(), "settings_advanced"); updateOptions(appFilter.isChecked(), "settings_app_filter"); - - findPreference("settings_use_system_dns").setOnPreferenceChangeListener((preference, newValue) -> { - boolean vis = !(boolean) newValue; - findPreference("primary_server").setVisible(vis); - findPreference("secondary_server").setVisible(vis); - return true; - }); } private void updateOptions(boolean checked, String pref) { diff --git a/app/src/main/java/org/itxtech/daedalus/server/AbstractDnsServer.java b/app/src/main/java/org/itxtech/daedalus/server/AbstractDnsServer.java index 1026c1e..d7760d5 100644 --- a/app/src/main/java/org/itxtech/daedalus/server/AbstractDnsServer.java +++ b/app/src/main/java/org/itxtech/daedalus/server/AbstractDnsServer.java @@ -1,5 +1,7 @@ package org.itxtech.daedalus.server; +import androidx.annotation.NonNull; + /** * Daedalus Project * @@ -11,7 +13,7 @@ package org.itxtech.daedalus.server; * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. */ -public class AbstractDnsServer { +public class AbstractDnsServer implements Cloneable { public static final int DNS_SERVER_DEFAULT_PORT = 53; protected String address; @@ -63,4 +65,14 @@ public class AbstractDnsServer { public boolean isHttpsServer() { return address.contains("/"); } + + @NonNull + @Override + public Object clone() { + try { + return super.clone(); + } catch (Exception ignored) { + } + return new AbstractDnsServer("", 0); + } } diff --git a/app/src/main/java/org/itxtech/daedalus/service/DaedalusVpnService.java b/app/src/main/java/org/itxtech/daedalus/service/DaedalusVpnService.java index b315426..eb410e4 100644 --- a/app/src/main/java/org/itxtech/daedalus/service/DaedalusVpnService.java +++ b/app/src/main/java/org/itxtech/daedalus/service/DaedalusVpnService.java @@ -4,14 +4,18 @@ import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageManager; +import android.net.ConnectivityManager; import android.net.VpnService; import android.os.Build; import android.os.ParcelFileDescriptor; import android.system.OsConstants; import android.util.Log; +import androidx.appcompat.app.AlertDialog; import androidx.core.app.NotificationCompat; import org.itxtech.daedalus.Daedalus; import org.itxtech.daedalus.R; @@ -19,10 +23,12 @@ import org.itxtech.daedalus.activity.MainActivity; import org.itxtech.daedalus.provider.Provider; import org.itxtech.daedalus.provider.ProviderPicker; import org.itxtech.daedalus.receiver.StatusBarBroadcastReceiver; +import org.itxtech.daedalus.server.AbstractDnsServer; +import org.itxtech.daedalus.server.DnsServer; +import org.itxtech.daedalus.server.DnsServerHelper; +import org.itxtech.daedalus.util.DnsServersDetector; import org.itxtech.daedalus.util.Logger; import org.itxtech.daedalus.util.RuleResolver; -import org.itxtech.daedalus.server.AbstractDnsServer; -import org.itxtech.daedalus.server.DnsServerHelper; import java.net.Inet4Address; import java.net.Inet6Address; @@ -54,20 +60,19 @@ public class DaedalusVpnService extends VpnService implements Runnable { public static AbstractDnsServer primaryServer; public static AbstractDnsServer secondaryServer; + private static InetAddress aliasPrimary; + private static InetAddress aliasSecondary; private NotificationCompat.Builder notification = null; - private boolean running = false; private long lastUpdate = 0; private boolean statisticQuery; private Provider provider; private ParcelFileDescriptor descriptor; - private Thread mThread = null; - public HashMap dnsServers; - private static boolean activated = false; + private static BroadcastReceiver receiver; public static boolean isActivated() { return activated; @@ -76,6 +81,44 @@ public class DaedalusVpnService extends VpnService implements Runnable { @Override public void onCreate() { super.onCreate(); + if (Daedalus.getPrefs().getBoolean("settings_use_system_dns", false)) { + registerReceiver(receiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + updateUpstreamServers(context); + } + }, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); + } + } + + public static void updateUpstreamServers(Context context) { + String[] servers = DnsServersDetector.getServers(context); + if (servers != null) { + if (servers.length >= 2 && (aliasPrimary == null || !aliasPrimary.getHostAddress().equals(servers[0])) && + (aliasSecondary == null || !aliasSecondary.getHostAddress().equals(servers[0])) && + (aliasPrimary == null || !aliasPrimary.getHostAddress().equals(servers[1])) && + (aliasSecondary == null || !aliasSecondary.getHostAddress().equals(servers[1]))) { + primaryServer.setAddress(servers[0]); + primaryServer.setPort(DnsServer.DNS_SERVER_DEFAULT_PORT); + secondaryServer.setAddress(servers[1]); + secondaryServer.setPort(DnsServer.DNS_SERVER_DEFAULT_PORT); + } else if ((aliasPrimary == null || !aliasPrimary.getHostAddress().equals(servers[0])) && + (aliasSecondary == null || !aliasSecondary.getHostAddress().equals(servers[0]))) { + primaryServer.setAddress(servers[0]); + primaryServer.setPort(DnsServer.DNS_SERVER_DEFAULT_PORT); + secondaryServer.setAddress(servers[0]); + secondaryServer.setPort(DnsServer.DNS_SERVER_DEFAULT_PORT); + } else { + StringBuilder buf = new StringBuilder(); + for (String server : servers) { + buf.append(server).append(" "); + } + Logger.error("Invalid upstream DNS " + buf); + } + Logger.info("Upstream DNS updated: " + primaryServer.getAddress() + " " + secondaryServer.getAddress()); + } else { + Logger.error("Cannot obtain upstream DNS server!"); + } } @Override @@ -85,7 +128,6 @@ public class DaedalusVpnService extends VpnService implements Runnable { case ACTION_ACTIVATE: activated = true; if (Daedalus.getPrefs().getBoolean("settings_notification", true)) { - NotificationManager manager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); NotificationCompat.Builder builder; @@ -127,12 +169,7 @@ public class DaedalusVpnService extends VpnService implements Runnable { } Daedalus.initRuleResolver(); - - if (this.mThread == null) { - this.mThread = new Thread(this, "DaedalusVpn"); - this.running = true; - this.mThread.start(); - } + startThread(); Daedalus.updateShortcut(getApplicationContext()); if (MainActivity.getInstance() != null) { MainActivity.getInstance().startActivity(new Intent(getApplicationContext(), MainActivity.class) @@ -147,9 +184,20 @@ public class DaedalusVpnService extends VpnService implements Runnable { return START_NOT_STICKY; } + private void startThread() { + if (this.mThread == null) { + this.mThread = new Thread(this, "DaedalusVpn"); + this.running = true; + this.mThread.start(); + } + } + @Override public void onDestroy() { stopThread(); + if (receiver != null) { + unregisterReceiver(receiver); + } } private void stopThread() { @@ -203,7 +251,8 @@ public class DaedalusVpnService extends VpnService implements Runnable { stopThread(); } - private InetAddress addDnsServer(Builder builder, String format, byte[] ipv6Template, AbstractDnsServer addr) throws UnknownHostException { + private InetAddress addDnsServer(Builder builder, String format, byte[] ipv6Template, AbstractDnsServer addr) + throws UnknownHostException { int size = dnsServers.size(); size++; if (addr.getAddress().contains("/")) {//https uri @@ -241,7 +290,6 @@ public class DaedalusVpnService extends VpnService implements Runnable { new Intent(this, MainActivity.class).putExtra(MainActivity.LAUNCH_FRAGMENT, MainActivity.FRAGMENT_SETTINGS), PendingIntent.FLAG_ONE_SHOT)); - //Set App Filter if (Daedalus.getPrefs().getBoolean("settings_app_filter_switch", false)) { ArrayList apps = Daedalus.configurations.getAppObjects(); if (apps.size() > 0) { @@ -278,22 +326,16 @@ public class DaedalusVpnService extends VpnService implements Runnable { statisticQuery = Daedalus.getPrefs().getBoolean("settings_count_query_times", false); byte[] ipv6Template = new byte[]{32, 1, 13, (byte) (184 & 0xFF), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - if (primaryServer.getAddress().contains(":") || secondaryServer.getAddress().contains(":")) {//IPv6 - try { - InetAddress addr = Inet6Address.getByAddress(ipv6Template); - Log.d(TAG, "configure: Adding IPv6 address" + addr); - builder.addAddress(addr, 120); - } catch (Exception e) { - Logger.logException(e); + try { + InetAddress addr = Inet6Address.getByAddress(ipv6Template); + Log.d(TAG, "configure: Adding IPv6 address" + addr); + builder.addAddress(addr, 120); + } catch (Exception e) { + Logger.logException(e); - ipv6Template = null; - } - } else { ipv6Template = null; } - InetAddress aliasPrimary; - InetAddress aliasSecondary; if (advanced) { dnsServers = new HashMap<>(); aliasPrimary = addDnsServer(builder, format, ipv6Template, primaryServer); @@ -303,8 +345,8 @@ public class DaedalusVpnService extends VpnService implements Runnable { aliasSecondary = InetAddress.getByName(secondaryServer.getAddress()); } - Logger.info("Daedalus VPN service is listening on " + primaryServer + " as " + aliasPrimary.getHostAddress()); - Logger.info("Daedalus VPN service is listening on " + secondaryServer + " as " + aliasSecondary.getHostAddress()); + Logger.info("Daedalus VPN service is listening on " + primaryServer.getAddress() + " as " + aliasPrimary.getHostAddress()); + Logger.info("Daedalus VPN service is listening on " + secondaryServer.getAddress() + " as " + aliasSecondary.getHostAddress()); builder.addDnsServer(aliasPrimary).addDnsServer(aliasSecondary); if (advanced) { @@ -325,13 +367,17 @@ public class DaedalusVpnService extends VpnService implements Runnable { Thread.sleep(1000); } } - } catch ( - InterruptedException ignored) { - } catch ( - Exception e) { + } catch (InterruptedException ignored) { + } catch (Exception e) { + MainActivity.getInstance().runOnUiThread(() -> + new AlertDialog.Builder(MainActivity.getInstance()) + .setTitle(R.string.error_occurred) + .setMessage(Logger.getExceptionMessage(e)) + .setPositiveButton(android.R.string.ok, (d, id) -> { + }) + .show()); Logger.logException(e); } finally { - Log.d(TAG, "quit"); stopThread(); } } @@ -354,11 +400,11 @@ public class DaedalusVpnService extends VpnService implements Runnable { } } - public static class VpnNetworkException extends Exception { public VpnNetworkException(String s) { super(s); } + public VpnNetworkException(String s, Throwable t) { super(s, t); } diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml deleted file mode 100644 index 1a384e6..0000000 --- a/app/src/main/res/values-v21/styles.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 79aca38..0aa5564 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -104,4 +104,6 @@ google.com 版本: + + 启动时出现了一个错误 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index c4d4e93..0cd2f72 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -101,4 +101,6 @@ google.com 版本: + + 啟動時出現了一個錯誤 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bb9e9e3..285da87 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -112,4 +112,6 @@ Version: Git commit: GitHub + + An error occurred at startup diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index ad9c1a1..a0f82ec 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,8 +1,5 @@ - - - - + diff --git a/app/src/main/res/xml/perf_settings.xml b/app/src/main/res/xml/perf_settings.xml index f4c90fc..589f1ea 100644 --- a/app/src/main/res/xml/perf_settings.xml +++ b/app/src/main/res/xml/perf_settings.xml @@ -6,10 +6,6 @@ android:key="settingsServer" android:title="@string/settings_server"> - +