DoH: now support using URI with domain without a rule

This commit is contained in:
PeratX 2019-07-14 20:27:55 +08:00
parent 2fb7406420
commit 4d9045655f
17 changed files with 78 additions and 85 deletions

View File

@ -8,7 +8,7 @@ android {
buildToolsVersion "28.0.3"
defaultConfig {
applicationId "org.itxtech.daedalus"
minSdkVersion 15
minSdkVersion 21
targetSdkVersion 28
versionCode 19
versionName "1.14.0"
@ -39,12 +39,12 @@ android {
dependencies {
//Support
implementation 'androidx.appcompat:appcompat:1.1.0-beta01'
implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.percentlayout:percentlayout:1.0.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'com.google.android.material:material:1.1.0-alpha07'
implementation 'androidx.recyclerview:recyclerview:1.1.0-alpha06'
implementation 'com.google.android.material:material:1.1.0-alpha08'
implementation 'androidx.recyclerview:recyclerview:1.1.0-beta01'
//DNS
implementation 'org.pcap4j:pcap4j-core:1.7.6'
implementation 'org.pcap4j:pcap4j-packetfactory-static:1.7.6'
@ -52,7 +52,7 @@ dependencies {
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.okhttp3:okhttp:3.14.1'
//Analytics
implementation 'com.google.firebase:firebase-core:16.0.9'
implementation 'com.google.firebase:firebase-core:17.0.1'
implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'
}

View File

@ -135,7 +135,6 @@ public class Daedalus extends Application {
}
public static void initRuleResolver() {
if (Daedalus.getPrefs().getBoolean("settings_local_rules_resolution", false)) {
ArrayList<String> pendingLoad = new ArrayList<>();
ArrayList<Rule> usingRules = configurations.getUsingRules();
if (usingRules != null && usingRules.size() > 0) {
@ -160,13 +159,11 @@ public class Daedalus extends Application {
}
} else {
RuleResolver.clear();
}
}
}
public static void setRulesChanged() {
if (DaedalusVpnService.isActivated() &&
getPrefs().getBoolean("settings_allow_dynamic_rule_reload", false)) {
if (DaedalusVpnService.isActivated()) {
initRuleResolver();
}
}

View File

@ -187,11 +187,7 @@ public class RuleConfigFragment extends ConfigFragment {
ClickPreference ruleImportExternal = (ClickPreference) findPreference("ruleImportExternal");
ruleImportExternal.setOnPreferenceClickListener(preference -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
performFileSearch();
} else {
Snackbar.make(getView(), R.string.notice_legacy_api, Snackbar.LENGTH_LONG).show();
}
performFileSearch();
return false;
});

View File

@ -17,7 +17,6 @@ import com.google.android.material.snackbar.Snackbar;
import org.itxtech.daedalus.Daedalus;
import org.itxtech.daedalus.R;
import org.itxtech.daedalus.activity.ConfigActivity;
import org.itxtech.daedalus.service.DaedalusVpnService;
import org.itxtech.daedalus.util.Rule;
import java.io.File;
@ -61,14 +60,6 @@ public class RulesFragment extends ToolbarFragment implements Toolbar.OnMenuItem
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback() {
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
if (!Daedalus.getPrefs().getBoolean("settings_allow_dynamic_rule_reload", false)) {
if (viewHolder instanceof RulesFragment.ViewHolder) {
Rule rule = Rule.getRuleById(((ViewHolder) viewHolder).getId());
if (rule != null && rule.isServiceAndUsing()) {
return 0;
}
}
}
return makeMovementFlags(0, ItemTouchHelper.START | ItemTouchHelper.END);
}
@ -121,11 +112,7 @@ public class RulesFragment extends ToolbarFragment implements Toolbar.OnMenuItem
}
if (id == R.id.action_reload) {
if (!Daedalus.getPrefs().getBoolean("settings_allow_dynamic_rule_reload", false)) {
Snackbar.make(getView(), R.string.notice_check_dynamic_rule_reload, Snackbar.LENGTH_SHORT).show();
} else {
Daedalus.setRulesChanged();
}
Daedalus.setRulesChanged();
}
return true;
}
@ -233,24 +220,18 @@ public class RulesFragment extends ToolbarFragment implements Toolbar.OnMenuItem
@Override
public void onClick(View v) {
if ((!Daedalus.getPrefs().getBoolean("settings_allow_dynamic_rule_reload", false) &&
!DaedalusVpnService.isActivated()) ||
Daedalus.getPrefs().getBoolean("settings_allow_dynamic_rule_reload", false)) {
Rule rule = Rule.getRuleById(id);
if (rule != null) {
rule.setUsing(!v.isSelected());
v.setSelected(!v.isSelected());
Daedalus.setRulesChanged();
}
}
}
@Override
public boolean onLongClick(View v) {
Rule rule = Rule.getRuleById(id);
if (rule != null &&
(Daedalus.getPrefs().getBoolean("settings_allow_dynamic_rule_reload", false) ||
!rule.isServiceAndUsing())) {
if (rule != null) {
Daedalus.getInstance().startActivity(new Intent(Daedalus.getInstance(), ConfigActivity.class)
.putExtra(ConfigActivity.LAUNCH_ACTION_ID, Integer.parseInt(id))
.putExtra(ConfigActivity.LAUNCH_ACTION_FRAGMENT, ConfigActivity.LAUNCH_FRAGMENT_RULE)

View File

@ -8,7 +8,6 @@ import org.minidns.dnsmessage.DnsMessage;
import org.pcap4j.packet.IpPacket;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
* Daedalus Project
@ -22,14 +21,8 @@ import java.util.concurrent.TimeUnit;
* (at your option) any later version.
*/
public class HttpsIetfProvider extends HttpsProvider {
private static final OkHttpClient HTTP_CLIENT = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.addInterceptor((chain) -> chain.proceed(chain.request().newBuilder()
.header("Accept", "application/dns-message")
.build()))
.build();
private OkHttpClient HTTP_CLIENT = getHttpClient("application/dns-message");
public HttpsIetfProvider(ParcelFileDescriptor descriptor, DaedalusVpnService service) {
super(descriptor, service);

View File

@ -13,7 +13,6 @@ import org.minidns.record.*;
import org.pcap4j.packet.IpPacket;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
* Daedalus Project
@ -32,14 +31,7 @@ public class HttpsJsonProvider extends HttpsProvider {
* https://developers.google.com/speed/public-dns/docs/dns-over-https
*/
private static final OkHttpClient HTTP_CLIENT = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.addInterceptor((chain) -> chain.proceed(chain.request().newBuilder()
.header("Accept", "application/dns-json")
.build()))
.build();
private OkHttpClient HTTP_CLIENT = getHttpClient("application/dns-json");
public HttpsJsonProvider(ParcelFileDescriptor descriptor, DaedalusVpnService service) {
super(descriptor, service);

View File

@ -8,9 +8,11 @@ import android.system.OsConstants;
import android.system.StructPollfd;
import android.util.Log;
import androidx.annotation.NonNull;
import okhttp3.OkHttpClient;
import org.itxtech.daedalus.Daedalus;
import org.itxtech.daedalus.service.DaedalusVpnService;
import org.itxtech.daedalus.util.Logger;
import org.itxtech.daedalus.util.server.DNSServerHelper;
import org.minidns.dnsmessage.DnsMessage;
import org.pcap4j.packet.IpPacket;
import org.pcap4j.packet.IpSelector;
@ -21,8 +23,10 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
/**
* Daedalus Project
@ -36,7 +40,8 @@ import java.util.LinkedList;
* (at your option) any later version.
*/
abstract public class HttpsProvider extends Provider {
protected static final String HTTPS_SUFFIX = "https://";
public static final String HTTPS_SUFFIX = "https://";
private static final String TAG = "HttpsProvider";
@ -46,6 +51,23 @@ abstract public class HttpsProvider extends Provider {
super(descriptor, service);
}
protected OkHttpClient getHttpClient(String accept) {
return new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.addInterceptor((chain) -> chain.proceed(chain.request().newBuilder()
.header("Accept", accept)
.build()))
.dns(hostname -> {
if (DNSServerHelper.domainCache.containsKey(hostname)) {
return DNSServerHelper.domainCache.get(hostname);
}
return Arrays.asList(InetAddress.getAllByName(hostname));
})
.build();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void process() {
try {

View File

@ -24,7 +24,7 @@ public class ProviderPicker {
//This section mush be the same as the one in arrays.xml
public static Provider getProvider(ParcelFileDescriptor descriptor, DaedalusVpnService service) {
switch (Integer.valueOf(Daedalus.getPrefs().getString("settings_dns_query_method", "0"))) {
switch (getDnsQueryMethod()) {
case DNS_QUERY_METHOD_UDP:
return new UdpProvider(descriptor, service);
case DNS_QUERY_METHOD_TCP:
@ -38,4 +38,8 @@ public class ProviderPicker {
}
return new UdpProvider(descriptor, service);
}
public static int getDnsQueryMethod() {
return Integer.valueOf(Daedalus.getPrefs().getString("settings_dns_query_method", "0"));
}
}

View File

@ -13,9 +13,7 @@ import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.system.OsConstants;
import android.util.Log;
import androidx.core.app.NotificationCompat;
import org.itxtech.daedalus.Daedalus;
import org.itxtech.daedalus.R;
import org.itxtech.daedalus.activity.MainActivity;
@ -129,7 +127,6 @@ public class DaedalusVpnService extends VpnService implements Runnable {
}
Daedalus.initRuleResolver();
DNSServerHelper.buildPortCache();
if (this.mThread == null) {
this.mThread = new Thread(this, "DaedalusVpn");
@ -190,7 +187,7 @@ public class DaedalusVpnService extends VpnService implements Runnable {
if (shouldRefresh) {
RuleResolver.clear();
DNSServerHelper.clearPortCache();
DNSServerHelper.clearCache();
Logger.info("Daedalus VPN service has stopped");
}
@ -237,6 +234,7 @@ public class DaedalusVpnService extends VpnService implements Runnable {
@Override
public void run() {
try {
DNSServerHelper.buildCache();
Builder builder = new Builder()
.setSession("Daedalus")
.setConfigureIntent(PendingIntent.getActivity(this, 0,

View File

@ -2,9 +2,9 @@ package org.itxtech.daedalus.util;
import com.google.gson.Gson;
import com.google.gson.stream.JsonReader;
import org.itxtech.daedalus.Daedalus;
import org.itxtech.daedalus.util.server.CustomDNSServer;
import org.itxtech.daedalus.util.server.DNSServer;
import java.io.File;
import java.io.FileReader;
@ -28,6 +28,7 @@ public class Configurations {
private static File file;
private ArrayList<DNSServer> builtInDNSServers;
private ArrayList<CustomDNSServer> customDNSServers;
private ArrayList<String> filterAppObjects;

View File

@ -1,7 +1,6 @@
package org.itxtech.daedalus.util;
import org.itxtech.daedalus.Daedalus;
import org.itxtech.daedalus.service.DaedalusVpnService;
import java.io.File;
import java.util.ArrayList;
@ -104,10 +103,6 @@ public class Rule {
this.downloadUrl = downloadUrl;
}
public boolean isServiceAndUsing() {
return DaedalusVpnService.isActivated() && isUsing();
}
public void addToConfig() {
if (getType() == Rule.TYPE_HOSTS) {
Daedalus.configurations.getHostsRules().add(this);
@ -123,11 +118,9 @@ public class Rule {
Daedalus.configurations.getDnsmasqRules().remove(this);
}
File file = new File(getFileName());
Logger.info("Delete rule " + getName() + " result: " + String.valueOf(file.delete()));
Logger.info("Delete rule " + getName() + " result: " + file.delete());
}
//STATIC METHODS
public static String[] getBuildInRuleNames() {
ArrayList<String> names = new ArrayList<>(Daedalus.RULES.size());
for (Rule rule : Daedalus.RULES) {

View File

@ -1,12 +1,18 @@
package org.itxtech.daedalus.util.server;
import android.content.Context;
import android.net.Uri;
import org.itxtech.daedalus.Daedalus;
import org.itxtech.daedalus.provider.HttpsProvider;
import org.itxtech.daedalus.provider.ProviderPicker;
import org.itxtech.daedalus.service.DaedalusVpnService;
import org.itxtech.daedalus.util.Logger;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
/**
* Daedalus Project
@ -21,12 +27,21 @@ import java.util.HashMap;
*/
public class DNSServerHelper {
private static HashMap<String, Integer> portCache = null;
public static HashMap<String, List<InetAddress>> domainCache = null;
public static void clearPortCache() {
public static void clearCache() {
portCache = null;
domainCache = null;
}
public static void buildPortCache() {
public static void buildCache() {
domainCache = new HashMap<>();
if (ProviderPicker.getDnsQueryMethod() >= ProviderPicker.DNS_QUERY_METHOD_HTTPS_IETF &&
!Daedalus.getPrefs().getBoolean("settings_dont_build_doh_cache", false)) {
buildDomainCache(getAddressById(getPrimary()));
buildDomainCache(getAddressById(getSecondary()));
}
portCache = new HashMap<>();
for (DNSServer server : Daedalus.DNS_SERVERS) {
portCache.put(server.getAddress(), server.getPort());
@ -35,7 +50,16 @@ public class DNSServerHelper {
for (CustomDNSServer server : Daedalus.configurations.getCustomDNSServers()) {
portCache.put(server.getAddress(), server.getPort());
}
}
private static void buildDomainCache(String addr) {
addr = HttpsProvider.HTTPS_SUFFIX + addr;
String host = Uri.parse(addr).getHost();
try {
domainCache.put(host, Arrays.asList(InetAddress.getAllByName(host)));
} catch (Exception e) {
Logger.logException(e);
}
}
public static int getPortOrDefault(InetAddress address, int defaultPort) {

View File

@ -60,12 +60,11 @@
<string name="settings_help_and_support">支持和帮助</string>
<string name="settings_advanced">高级系统设置</string>
<string name="settings_advanced_on">开启</string>
<string name="settings_local_rules_resolver">本地规则解析</string>
<string name="settings_manual">使用手册</string>
<string name="settings_manual_summary">访问 GitHub wiki 页面。</string>
<string name="settings_log_size">日志大小限制</string>
<string name="settings_debug_output">调试输出</string>
<string name="settings_allow_dynamic_rule_reload">允许动态更新规则</string>
<string name="settings_dont_build_doh_cache">不缓存 DoH DNS 的 IP地址</string>
<string name="settings_dark_theme">使用暗主题</string>
<string name="settings_dns_query_method">DNS 查询方式</string>

View File

@ -60,12 +60,11 @@
<string name="settings_help_and_support">支援與說明</string>
<string name="settings_advanced">進階系統設定</string>
<string name="settings_advanced_on">開啟</string>
<string name="settings_local_rules_resolver">本機規則解析</string>
<string name="settings_manual">使用手冊</string>
<string name="settings_manual_summary">造訪 GitHub wiki 頁面。</string>
<string name="settings_log_size">紀錄檔大小限制</string>
<string name="settings_debug_output">调试输出 TODO</string>
<string name="settings_allow_dynamic_rule_reload">允許動態規則重新載入</string>
<string name="settings_dont_build_doh_cache">不缓存 DoH DNS 的 IP地址</string>
<string name="settings_dark_theme">使用暗主题</string>
<string name="settings_rule_name">規則名稱</string>

View File

@ -59,11 +59,10 @@
<string name="settings_help_and_support">Help &amp; Support</string>
<string name="settings_advanced">Advanced System Settings</string>
<string name="settings_advanced_on">On</string>
<string name="settings_local_rules_resolver">Local Rules Resolver</string>
<string name="settings_log_size">Log Size Limit</string>
<string name="settings_manual">Manual</string>
<string name="settings_manual_summary">Visit GitHub wiki page.</string>
<string name="settings_allow_dynamic_rule_reload">Allow Dynamic Rule Reloading</string>
<string name="settings_dont_build_doh_cache">Don\'t build DNS Cache for DoH DNS</string>
<string name="settings_debug_output">Debug Output</string>
<string name="settings_dark_theme">Use Dark Theme</string>
<string name="settings_dns_query_method">DNS Query Method</string>

View File

@ -81,13 +81,8 @@
android:defaultValue="false"
android:enabled="false"/>
<SwitchPreference
android:key="settings_local_rules_resolution"
android:title="@string/settings_local_rules_resolver"
android:defaultValue="false"
android:enabled="false"/>
<SwitchPreference
android:key="settings_allow_dynamic_rule_reload"
android:title="@string/settings_allow_dynamic_rule_reload"
android:key="settings_dont_build_doh_cache"
android:title="@string/settings_dont_build_doh_cache"
android:defaultValue="false"
android:enabled="false"/>
<ListPreference

View File

@ -9,8 +9,8 @@ buildscript {
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.1'
classpath 'com.google.gms:google-services:4.2.0'
classpath 'com.android.tools.build:gradle:3.4.2'
classpath 'com.google.gms:google-services:4.3.0'
classpath 'io.fabric.tools:gradle:1.28.1'
// NOTE: Do not place your application dependencies here; they belong