diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 354635f..bb0d160 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -12,7 +12,7 @@ android { minSdk = 21 targetSdk = 34 versionCode = 8 - versionName = "1.1.0-beta" + versionName = "1.1.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/src/main/cpp/main.h b/app/src/main/cpp/main.h index f6f8f34..5952df9 100644 --- a/app/src/main/cpp/main.h +++ b/app/src/main/cpp/main.h @@ -13,6 +13,8 @@ void clear_params(void); char *ftob(const char *str, ssize_t *sl); +char *parse_cform(const char *str, ssize_t *size); + struct mphdr *parse_hosts(char *buffer, size_t size); int parse_offset(struct part *part, const char *str); diff --git a/app/src/main/cpp/native-lib.c b/app/src/main/cpp/native-lib.c index 19a60af..eceb14c 100644 --- a/app/src/main/cpp/native-lib.c +++ b/app/src/main/cpp/native-lib.c @@ -12,11 +12,17 @@ #include "utils.h" const enum demode DESYNC_METHODS[] = { - DESYNC_NONE, - DESYNC_SPLIT, - DESYNC_DISORDER, - DESYNC_FAKE, - DESYNC_OOB, + DESYNC_NONE, + DESYNC_SPLIT, + DESYNC_DISORDER, + DESYNC_FAKE, + DESYNC_OOB, +}; + +enum hosts_mode { + HOSTS_DISABLE, + HOSTS_BLACKLIST, + HOSTS_WHITELIST, }; JNIEXPORT jint JNI_OnLoad( @@ -81,8 +87,9 @@ Java_io_github_dovecoteescapee_byedpi_core_ByeDpiProxy_jniCreateSocket( jboolean host_remove_spaces, jboolean tls_record_split, jint tls_record_split_position, - jboolean tls_record_split_at_sni) { - + jboolean tls_record_split_at_sni, + jint hosts_mode, + jstring hosts) { struct sockaddr_ina s; const char *address = (*env)->GetStringUTFChars(env, ip, 0); @@ -112,6 +119,29 @@ Java_io_github_dovecoteescapee_byedpi_core_ByeDpiProxy_jniCreateSocket( } } + if (hosts_mode == HOSTS_WHITELIST) { + struct desync_params *dp = add( + (void *) ¶ms.dp, + ¶ms.dp_count, + sizeof(struct desync_params) + ); + if (!dp) { + uniperror("add"); + reset_params(); + return -1; + } + + const char *str = (*env)->GetStringUTFChars(env, hosts, 0); + dp->file_ptr = parse_cform(str, &dp->file_size); + (*env)->ReleaseStringUTFChars(env, hosts, str); + dp->hosts = parse_hosts(dp->file_ptr, dp->file_size); + if (!dp->hosts) { + perror("parse_hosts"); + clear_params(); + return -1; + } + } + struct desync_params *dp = add( (void *) ¶ms.dp, ¶ms.dp_count, @@ -123,6 +153,18 @@ Java_io_github_dovecoteescapee_byedpi_core_ByeDpiProxy_jniCreateSocket( return -1; } + if (hosts_mode == HOSTS_BLACKLIST) { + const char *str = (*env)->GetStringUTFChars(env, hosts, 0); + dp->file_ptr = parse_cform(str, &dp->file_size); + (*env)->ReleaseStringUTFChars(env, hosts, str); + dp->hosts = parse_hosts(dp->file_ptr, dp->file_size); + if (!dp->hosts) { + perror("parse_hosts"); + clear_params(); + return -1; + } + } + dp->ttl = fake_ttl; dp->proto = IS_HTTP * desync_http | diff --git a/app/src/main/java/io/github/dovecoteescapee/byedpi/activities/MainActivity.kt b/app/src/main/java/io/github/dovecoteescapee/byedpi/activities/MainActivity.kt index cb9d19d..45584a6 100644 --- a/app/src/main/java/io/github/dovecoteescapee/byedpi/activities/MainActivity.kt +++ b/app/src/main/java/io/github/dovecoteescapee/byedpi/activities/MainActivity.kt @@ -38,7 +38,7 @@ class MainActivity : AppCompatActivity() { private fun collectLogs(): String? = try { Runtime.getRuntime() - .exec("logcat *:I -d") + .exec("logcat *:D -d") .inputStream.bufferedReader() .use { it.readText() } } catch (e: Exception) { diff --git a/app/src/main/java/io/github/dovecoteescapee/byedpi/activities/SettingsActivity.kt b/app/src/main/java/io/github/dovecoteescapee/byedpi/activities/SettingsActivity.kt index e48ca95..880cc7d 100644 --- a/app/src/main/java/io/github/dovecoteescapee/byedpi/activities/SettingsActivity.kt +++ b/app/src/main/java/io/github/dovecoteescapee/byedpi/activities/SettingsActivity.kt @@ -4,6 +4,7 @@ import android.os.Bundle import android.view.Menu import android.view.MenuItem import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.FragmentManager import io.github.dovecoteescapee.byedpi.R import io.github.dovecoteescapee.byedpi.fragments.MainSettingsFragment import io.github.dovecoteescapee.byedpi.utility.getPreferences @@ -35,6 +36,7 @@ class SettingsActivity : AppCompatActivity() { R.id.action_reset_settings -> { getPreferences().edit().clear().apply() + supportFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE) supportFragmentManager .beginTransaction() .replace(R.id.settings, MainSettingsFragment()) diff --git a/app/src/main/java/io/github/dovecoteescapee/byedpi/core/ByeDpiProxy.kt b/app/src/main/java/io/github/dovecoteescapee/byedpi/core/ByeDpiProxy.kt index bce1ff0..ec069c3 100644 --- a/app/src/main/java/io/github/dovecoteescapee/byedpi/core/ByeDpiProxy.kt +++ b/app/src/main/java/io/github/dovecoteescapee/byedpi/core/ByeDpiProxy.kt @@ -76,6 +76,8 @@ class ByeDpiProxy { tlsRecordSplit = preferences.tlsRecordSplit, tlsRecordSplitPosition = preferences.tlsRecordSplitPosition, tlsRecordSplitAtSni = preferences.tlsRecordSplitAtSni, + hostsMode = preferences.hostsMode.ordinal, + hosts = preferences.hosts ) } @@ -104,6 +106,8 @@ class ByeDpiProxy { tlsRecordSplit: Boolean, tlsRecordSplitPosition: Int, tlsRecordSplitAtSni: Boolean, + hostsMode: Int, + hosts: String? ): Int private external fun jniStartProxy(fd: Int): Int diff --git a/app/src/main/java/io/github/dovecoteescapee/byedpi/core/ByeDpiProxyPreferences.kt b/app/src/main/java/io/github/dovecoteescapee/byedpi/core/ByeDpiProxyPreferences.kt index dcf295c..59c0c3e 100644 --- a/app/src/main/java/io/github/dovecoteescapee/byedpi/core/ByeDpiProxyPreferences.kt +++ b/app/src/main/java/io/github/dovecoteescapee/byedpi/core/ByeDpiProxyPreferences.kt @@ -55,6 +55,8 @@ class ByeDpiProxyUIPreferences( tlsRecordSplit: Boolean? = null, tlsRecordSplitPosition: Int? = null, tlsRecordSplitAtSni: Boolean? = null, + hostsMode: HostsMode? = null, + hosts: String? = null, ) : ByeDpiProxyPreferences { val ip: String = ip ?: "127.0.0.1" val port: Int = port ?: 1080 @@ -78,6 +80,12 @@ class ByeDpiProxyUIPreferences( val tlsRecordSplit: Boolean = tlsRecordSplit ?: false val tlsRecordSplitPosition: Int = tlsRecordSplitPosition ?: 0 val tlsRecordSplitAtSni: Boolean = tlsRecordSplitAtSni ?: false + val hostsMode: HostsMode = + if (hosts?.isBlank() != false) HostsMode.Disable + else hostsMode ?: HostsMode.Disable + val hosts: String? = + if (this.hostsMode == HostsMode.Disable) null + else hosts?.trim() constructor(preferences: SharedPreferences) : this( ip = preferences.getString("byedpi_proxy_ip", null), @@ -103,6 +111,15 @@ class ByeDpiProxyUIPreferences( tlsRecordSplitPosition = preferences.getString("byedpi_tlsrec_position", null) ?.toIntOrNull(), tlsRecordSplitAtSni = preferences.getBoolean("byedpi_tlsrec_at_sni", false), + hostsMode = preferences.getString("byedpi_hosts_mode", null) + ?.let { HostsMode.fromName(it) }, + hosts = preferences.getString("byedpi_hosts_mode", null)?.let { + when (HostsMode.fromName(it)) { + HostsMode.Blacklist -> preferences.getString("byedpi_hosts_blacklist", null) + HostsMode.Whitelist -> preferences.getString("byedpi_hosts_whitelist", null) + else -> null + } + } ) enum class DesyncMethod { @@ -125,4 +142,21 @@ class ByeDpiProxyUIPreferences( } } } + + enum class HostsMode { + Disable, + Blacklist, + Whitelist; + + companion object { + fun fromName(name: String): HostsMode { + return when (name) { + "disable" -> Disable + "blacklist" -> Blacklist + "whitelist" -> Whitelist + else -> throw IllegalArgumentException("Unknown hosts mode: $name") + } + } + } + } } diff --git a/app/src/main/java/io/github/dovecoteescapee/byedpi/services/TProxyService.kt b/app/src/main/java/io/github/dovecoteescapee/byedpi/core/TProxyService.kt similarity index 86% rename from app/src/main/java/io/github/dovecoteescapee/byedpi/services/TProxyService.kt rename to app/src/main/java/io/github/dovecoteescapee/byedpi/core/TProxyService.kt index 17775a6..86ff5cf 100644 --- a/app/src/main/java/io/github/dovecoteescapee/byedpi/services/TProxyService.kt +++ b/app/src/main/java/io/github/dovecoteescapee/byedpi/core/TProxyService.kt @@ -1,4 +1,4 @@ -package io.github.dovecoteescapee.byedpi.services +package io.github.dovecoteescapee.byedpi.core object TProxyService { init { diff --git a/app/src/main/java/io/github/dovecoteescapee/byedpi/fragments/ByeDpiUISettingsFragment.kt b/app/src/main/java/io/github/dovecoteescapee/byedpi/fragments/ByeDpiUISettingsFragment.kt index 570e5df..3b9e88c 100644 --- a/app/src/main/java/io/github/dovecoteescapee/byedpi/fragments/ByeDpiUISettingsFragment.kt +++ b/app/src/main/java/io/github/dovecoteescapee/byedpi/fragments/ByeDpiUISettingsFragment.kt @@ -6,6 +6,7 @@ import androidx.preference.* import io.github.dovecoteescapee.byedpi.R import io.github.dovecoteescapee.byedpi.core.ByeDpiProxyUIPreferences import io.github.dovecoteescapee.byedpi.core.ByeDpiProxyUIPreferences.DesyncMethod.* +import io.github.dovecoteescapee.byedpi.core.ByeDpiProxyUIPreferences.HostsMode.* import io.github.dovecoteescapee.byedpi.utility.* class ByeDpiUISettingsFragment : PreferenceFragmentCompat() { @@ -65,7 +66,11 @@ class ByeDpiUISettingsFragment : PreferenceFragmentCompat() { val desyncMethod = findPreferenceNotNull("byedpi_desync_method") .value.let { ByeDpiProxyUIPreferences.DesyncMethod.fromName(it) } + val hostsMode = findPreferenceNotNull("byedpi_hosts_mode") + .value.let { ByeDpiProxyUIPreferences.HostsMode.fromName(it) } + val hostsBlacklist = findPreferenceNotNull("byedpi_hosts_blacklist") + val hostsWhitelist = findPreferenceNotNull("byedpi_hosts_whitelist") val desyncHttp = findPreferenceNotNull("byedpi_desync_http") val desyncHttps = findPreferenceNotNull("byedpi_desync_https") val desyncUdp = findPreferenceNotNull("byedpi_desync_udp") @@ -83,6 +88,23 @@ class ByeDpiUISettingsFragment : PreferenceFragmentCompat() { findPreferenceNotNull("byedpi_tlsrec_position") val splitTlsRecAtSni = findPreferenceNotNull("byedpi_tlsrec_at_sni") + when (hostsMode) { + Disable -> { + hostsBlacklist.isVisible = false + hostsWhitelist.isVisible = false + } + + Blacklist -> { + hostsBlacklist.isVisible = true + hostsWhitelist.isVisible = false + } + + Whitelist -> { + hostsBlacklist.isVisible = false + hostsWhitelist.isVisible = true + } + } + when (desyncMethod) { None -> { desyncHttp.isVisible = false diff --git a/app/src/main/java/io/github/dovecoteescapee/byedpi/fragments/MainSettingsFragment.kt b/app/src/main/java/io/github/dovecoteescapee/byedpi/fragments/MainSettingsFragment.kt index d8ee026..150e04e 100644 --- a/app/src/main/java/io/github/dovecoteescapee/byedpi/fragments/MainSettingsFragment.kt +++ b/app/src/main/java/io/github/dovecoteescapee/byedpi/fragments/MainSettingsFragment.kt @@ -38,7 +38,9 @@ class MainSettingsFragment : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.main_settings, rootKey) - setEditTextPreferenceListener("dns_ip") { checkIp(it) } + setEditTextPreferenceListener("dns_ip") { + it.isBlank() || checkIp(it) + } findPreferenceNotNull("app_theme") .setOnPreferenceChangeListener { _, newValue -> diff --git a/app/src/main/java/io/github/dovecoteescapee/byedpi/services/ByeDpiVpnService.kt b/app/src/main/java/io/github/dovecoteescapee/byedpi/services/ByeDpiVpnService.kt index f5fdb7c..1fedb18 100644 --- a/app/src/main/java/io/github/dovecoteescapee/byedpi/services/ByeDpiVpnService.kt +++ b/app/src/main/java/io/github/dovecoteescapee/byedpi/services/ByeDpiVpnService.kt @@ -12,6 +12,7 @@ import io.github.dovecoteescapee.byedpi.R import io.github.dovecoteescapee.byedpi.activities.MainActivity import io.github.dovecoteescapee.byedpi.core.ByeDpiProxy import io.github.dovecoteescapee.byedpi.core.ByeDpiProxyPreferences +import io.github.dovecoteescapee.byedpi.core.TProxyService import io.github.dovecoteescapee.byedpi.data.* import io.github.dovecoteescapee.byedpi.utility.* import kotlinx.coroutines.Dispatchers @@ -268,6 +269,7 @@ class ByeDpiVpnService : LifecycleVpnService() { ) private fun createBuilder(dns: String): Builder { + Log.d(TAG, "DNS: $dns") val builder = Builder() builder.setSession("ByeDPI") builder.setConfigureIntent( @@ -282,7 +284,9 @@ class ByeDpiVpnService : LifecycleVpnService() { builder.addAddress("10.10.10.10", 32) builder.addRoute("0.0.0.0", 0) builder.addRoute("0:0:0:0:0:0:0:0", 0) - builder.addDnsServer(dns) + if (dns.isNotBlank()) { + builder.addDnsServer(dns) + } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { builder.setMetered(false) } diff --git a/app/src/main/jni/Application.mk b/app/src/main/jni/Application.mk index 4960cc5..85fd1ed 100644 --- a/app/src/main/jni/Application.mk +++ b/app/src/main/jni/Application.mk @@ -16,6 +16,6 @@ APP_OPTIM := release APP_PLATFORM := android-21 APP_ABI := armeabi-v7a arm64-v8a x86 x86_64 -APP_CFLAGS := -O3 -DPKGNAME=io/github/dovecoteescapee/byedpi/services +APP_CFLAGS := -O3 -DPKGNAME=io/github/dovecoteescapee/byedpi/core APP_CPPFLAGS := -O3 -std=c++11 NDK_TOOLCHAIN_VERSION := clang diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 43c2f3c..e6091da 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -34,4 +34,15 @@ fake oob + + + Disable + Blacklist + Whitelist + + + disable + blacklist + whitelist + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d2afc0d..4997612 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -57,4 +57,8 @@ SNI of fake packet Proxy Desync - \ No newline at end of file + Command line arguments + Hosts + Hosts blacklist + Hosts whitelist + diff --git a/app/src/main/res/xml/byedpi_cmd_settings.xml b/app/src/main/res/xml/byedpi_cmd_settings.xml index 25590ad..e014131 100644 --- a/app/src/main/res/xml/byedpi_cmd_settings.xml +++ b/app/src/main/res/xml/byedpi_cmd_settings.xml @@ -17,8 +17,8 @@ diff --git a/app/src/main/res/xml/byedpi_ui_settings.xml b/app/src/main/res/xml/byedpi_ui_settings.xml index a1c1f16..c752f2b 100644 --- a/app/src/main/res/xml/byedpi_ui_settings.xml +++ b/app/src/main/res/xml/byedpi_ui_settings.xml @@ -53,6 +53,28 @@ + + + + + +