Improvements and fixes (v 1.2.0):

- Update ByeDPI to versions v0.13
- Added new options to UI editor
- Structured UI editor
- Changed default split position to 1
- Fixed listen ip validation
This commit is contained in:
dovecoteescapee 2024-08-23 18:22:09 +03:00
parent 9a6254869d
commit c95be6eb91
18 changed files with 212 additions and 172 deletions

View File

@ -29,7 +29,7 @@ height="80">](https://apt.izzysoft.de/fdroid/index/apk/io.github.dovecoteescapee
## Настройки
Для обхода некоторых блокировок может потребоваться изменить настройки. Подробнее о различных настройках можно прочитать в [документации ByeDPI](https://github.com/hufrea/byedpi/tree/v0.12#readme).
Для обхода некоторых блокировок может потребоваться изменить настройки. Подробнее о различных настройках можно прочитать в [документации ByeDPI](https://github.com/hufrea/byedpi/blob/v0.13/README.md).
## FAQ

View File

@ -30,7 +30,7 @@ This application runs a SOCKS5 proxy [ByeDPI](https://github.com/hufrea/byedpi)
## Settings
To bypass some blocks, you may need to change the settings. More about the various settings can be found in the [ByeDPI documentation](https://github.com/hufrea/byedpi/tree/v0.12#readme).
To bypass some blocks, you may need to change the settings. More about the various settings can be found in the [ByeDPI documentation](https://github.com/hufrea/byedpi/blob/v0.13/README.md).
## FAQ

View File

@ -11,8 +11,8 @@ android {
applicationId = "io.github.dovecoteescapee.byedpi"
minSdk = 21
targetSdk = 34
versionCode = 9
versionName = "1.1.1"
versionCode = 10
versionName = "1.2.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

@ -1 +1 @@
Subproject commit dcf5ed727c996d0073a6cb95d5eec45a793d28a2
Subproject commit 078842b084853bc30f33eaaec7acc510cf67e560

View File

@ -13,7 +13,10 @@ void clear_params(void);
char *ftob(const char *str, ssize_t *sl);
char *parse_cform(const char *str, ssize_t *size);
char *data_from_str(const char *str, ssize_t *size);
size_t parse_cform(char *buffer, size_t blen,
const char *str, size_t slen);
struct mphdr *parse_hosts(char *buffer, size_t size);

View File

@ -17,6 +17,7 @@ const enum demode DESYNC_METHODS[] = {
DESYNC_DISORDER,
DESYNC_FAKE,
DESYNC_OOB,
DESYNC_DISOOB,
};
enum hosts_mode {
@ -81,7 +82,7 @@ Java_io_github_dovecoteescapee_byedpi_core_ByeDpiProxy_jniCreateSocket(
jboolean split_at_host,
jint fake_ttl,
jstring fake_sni,
jstring custom_oob_data,
jbyte custom_oob_char,
jboolean host_mixed_case,
jboolean domain_mixed_case,
jboolean host_remove_spaces,
@ -91,7 +92,9 @@ Java_io_github_dovecoteescapee_byedpi_core_ByeDpiProxy_jniCreateSocket(
jint hosts_mode,
jstring hosts,
jboolean tfo,
jint udp_fake_count) {
jint udp_fake_count,
jboolean drop_sack,
jint fake_offset) {
struct sockaddr_ina s;
const char *address = (*env)->GetStringUTFChars(env, ip, 0);
@ -135,7 +138,7 @@ Java_io_github_dovecoteescapee_byedpi_core_ByeDpiProxy_jniCreateSocket(
}
const char *str = (*env)->GetStringUTFChars(env, hosts, 0);
dp->file_ptr = parse_cform(str, &dp->file_size);
dp->file_ptr = data_from_str(str, &dp->file_size);
(*env)->ReleaseStringUTFChars(env, hosts, str);
dp->hosts = parse_hosts(dp->file_ptr, dp->file_size);
if (!dp->hosts) {
@ -158,7 +161,7 @@ Java_io_github_dovecoteescapee_byedpi_core_ByeDpiProxy_jniCreateSocket(
if (hosts_mode == HOSTS_BLACKLIST) {
const char *str = (*env)->GetStringUTFChars(env, hosts, 0);
dp->file_ptr = parse_cform(str, &dp->file_size);
dp->file_ptr = data_from_str(str, &dp->file_size);
(*env)->ReleaseStringUTFChars(env, hosts, str);
dp->hosts = parse_hosts(dp->file_ptr, dp->file_size);
if (!dp->hosts) {
@ -170,6 +173,7 @@ Java_io_github_dovecoteescapee_byedpi_core_ByeDpiProxy_jniCreateSocket(
dp->ttl = fake_ttl;
dp->udp_fake_count = udp_fake_count;
dp->drop_sack = drop_sack;
dp->proto =
IS_HTTP * desync_http |
IS_HTTPS * desync_https |
@ -216,6 +220,8 @@ Java_io_github_dovecoteescapee_byedpi_core_ByeDpiProxy_jniCreateSocket(
}
if (mode == DESYNC_FAKE) {
dp->fake_offset = fake_offset;
const char *sni = (*env)->GetStringUTFChars(env, fake_sni, 0);
LOG(LOG_S, "fake_sni: %s", sni);
res = change_tls_sni(sni, fake_tls.data, fake_tls.size);
@ -227,17 +233,8 @@ Java_io_github_dovecoteescapee_byedpi_core_ByeDpiProxy_jniCreateSocket(
}
if (mode == DESYNC_OOB) {
const char *oob = (*env)->GetStringUTFChars(env, custom_oob_data, 0);
const size_t oob_len = strlen(oob);
oob_data.size = oob_len;
oob_data.data = malloc(oob_len);
if (oob_data.data == NULL) {
uniperror("malloc");
return -1;
}
memcpy(oob_data.data, oob, oob_len);
(*env)->ReleaseStringUTFChars(env, custom_oob_data, oob);
dp->oob_char[0] = custom_oob_char;
dp->oob_char[1] = 1;
}
if (dp->proto) {

View File

@ -15,9 +15,10 @@ void reset_params(void) {
params = default_params;
}
extern const struct option options[35];
extern const struct option options[38];
int parse_args(int argc, char **argv) {
int parse_args(int argc, char **argv)
{
int optc = sizeof(options)/sizeof(*options);
for (int i = 0, e = optc; i < e; i++)
optc += options[i].has_arg;
@ -50,8 +51,9 @@ int parse_args(int argc, char **argv) {
optind = optreset = 1;
while (!invalid && (rez = getopt_long_only(
while (!invalid && (rez = getopt_long(
argc, argv, opt, options, 0)) != -1) {
switch (rez) {
case 'N':
@ -64,6 +66,15 @@ int parse_args(int argc, char **argv) {
params.udp = 0;
break;
// case 'h':
// printf(help_text);
// reset_params();
// return 0;
// case 'v':
// printf("%s\n", VERSION);
// reset_params();
// return 0;
case 'i':
if (get_addr(optarg,
(struct sockaddr_ina *)&params.laddr) < 0)
@ -119,10 +130,6 @@ int parse_args(int argc, char **argv) {
reset_params();
return -1;
}
if (!optarg) {
dp->detect |= DETECT_TORST;
break;
}
end = optarg;
while (end && !invalid) {
switch (*end) {
@ -132,14 +139,9 @@ int parse_args(int argc, char **argv) {
case 'r':
dp->detect |= DETECT_HTTP_LOCAT;
break;
case 'c':
dp->detect |= DETECT_HTTP_CLERR;
break;
case 's':
dp->detect |= DETECT_TLS_INVSID;
break;
case 'a':
dp->detect |= DETECT_TLS_ALERT;
case 's':
dp->detect |= DETECT_TLS_ERR;
break;
case 'n':
break;
@ -161,8 +163,12 @@ int parse_args(int argc, char **argv) {
break;
case 'T':;
#ifdef __linux__
float f = strtof(optarg, &end);
val = (long)(f * 1000);
#else
val = strtol(optarg, &end, 0);
#endif
if (val <= 0 || val > UINT_MAX || *end)
invalid = 1;
else
@ -212,6 +218,7 @@ int parse_args(int argc, char **argv) {
case 's':
case 'd':
case 'o':
case 'q':
case 'f':
;
struct part *part = add((void *)&dp->parts,
@ -231,6 +238,8 @@ int parse_args(int argc, char **argv) {
break;
case 'o': part->m = DESYNC_OOB;
break;
case 'q': part->m = DESYNC_DISOOB;
break;
case 'f': part->m = DESYNC_FAKE;
}
break;
@ -263,13 +272,21 @@ int parse_args(int argc, char **argv) {
dp->md5sig = 1;
break;
case 'O':
val = strtol(optarg, &end, 0);
if (val <= 0 || *end)
invalid = 1;
else
dp->fake_offset = val;
break;
case 'n':
if (change_tls_sni(optarg, fake_tls.data, fake_tls.size)) {
fprintf(stderr, "error chsni\n");
perror("change_tls_sni");
reset_params();
return -1;
}
printf("sni: %s\n", optarg);
LOG(LOG_S, "sni: %s", optarg);
break;
case 'l':
@ -284,14 +301,11 @@ int parse_args(int argc, char **argv) {
break;
case 'e':
if (oob_data.data != oob_char) {
continue;
}
oob_data.data = ftob(optarg, &oob_data.size);
if (!oob_data.data) {
uniperror("read/parse");
val = parse_cform(dp->oob_char, 1, optarg, strlen(optarg));
if (val != 1) {
invalid = 1;
}
else dp->oob_char[1] = 1;
break;
case 'M':
@ -366,6 +380,10 @@ int parse_args(int argc, char **argv) {
}
break;
case 'Y':
dp->drop_sack = 1;
break;
case 'w': //
params.sfdelay = strtol(optarg, &end, 0);
if (params.sfdelay < 0 || optarg == end
@ -376,9 +394,11 @@ int parse_args(int argc, char **argv) {
case 'W':
params.wait_send = 0;
break;
#ifdef __linux__
case 'P':
params.protect_path = optarg;
break;
#endif
case 0:
break;
@ -387,13 +407,13 @@ int parse_args(int argc, char **argv) {
return -1;
default:
printf("?: %c\n", rez);
LOG(LOG_S, "Unknown option: -%c", rez);
reset_params();
return -1;
}
}
if (invalid) {
fprintf(stderr, "invalid value: -%c %s\n", rez, optarg);
LOG(LOG_S, "invalid value: -%c %s", rez, optarg);
reset_params();
return -1;
}

View File

@ -69,7 +69,7 @@ class ByeDpiProxy {
splitAtHost = preferences.splitAtHost,
fakeTtl = preferences.fakeTtl,
fakeSni = preferences.fakeSni,
oobData = preferences.oobData,
oobChar = preferences.oobChar,
hostMixedCase = preferences.hostMixedCase,
domainMixedCase = preferences.domainMixedCase,
hostRemoveSpaces = preferences.hostRemoveSpaces,
@ -80,6 +80,8 @@ class ByeDpiProxy {
hosts = preferences.hosts,
tcpFastOpen = preferences.tcpFastOpen,
udpFakeCount = preferences.udpFakeCount,
dropSack = preferences.dropSack,
fakeOffset = preferences.fakeOffset,
)
}
@ -101,7 +103,7 @@ class ByeDpiProxy {
splitAtHost: Boolean,
fakeTtl: Int,
fakeSni: String,
oobData: String,
oobChar: Byte,
hostMixedCase: Boolean,
domainMixedCase: Boolean,
hostRemoveSpaces: Boolean,
@ -112,6 +114,8 @@ class ByeDpiProxy {
hosts: String?,
tcpFastOpen: Boolean,
udpFakeCount: Int,
dropSack: Boolean,
fakeOffset: Int,
): Int
private external fun jniStartProxy(fd: Int): Int

View File

@ -48,7 +48,7 @@ class ByeDpiProxyUIPreferences(
splitAtHost: Boolean? = null,
fakeTtl: Int? = null,
fakeSni: String? = null,
oobData: String? = null,
oobChar: String? = null,
hostMixedCase: Boolean? = null,
domainMixedCase: Boolean? = null,
hostRemoveSpaces: Boolean? = null,
@ -59,6 +59,8 @@ class ByeDpiProxyUIPreferences(
hosts: String? = null,
tcpFastOpen: Boolean? = null,
udpFakeCount: Int? = null,
dropSack: Boolean? = null,
byedpiFakeOffset: Int? = null,
) : ByeDpiProxyPreferences {
val ip: String = ip ?: "127.0.0.1"
val port: Int = port ?: 1080
@ -71,11 +73,11 @@ class ByeDpiProxyUIPreferences(
val desyncHttps: Boolean = desyncHttps ?: true
val desyncUdp: Boolean = desyncUdp ?: false
val desyncMethod: DesyncMethod = desyncMethod ?: DesyncMethod.Disorder
val splitPosition: Int = splitPosition ?: 2
val splitPosition: Int = splitPosition ?: 1
val splitAtHost: Boolean = splitAtHost ?: false
val fakeTtl: Int = fakeTtl ?: 8
val fakeSni: String = fakeSni ?: "www.iana.org"
val oobData: String = oobData ?: "a"
val oobChar: Byte = (oobChar ?: "a")[0].code.toByte()
val hostMixedCase: Boolean = hostMixedCase ?: false
val domainMixedCase: Boolean = domainMixedCase ?: false
val hostRemoveSpaces: Boolean = hostRemoveSpaces ?: false
@ -90,6 +92,8 @@ class ByeDpiProxyUIPreferences(
else hosts?.trim()
val tcpFastOpen: Boolean = tcpFastOpen ?: false
val udpFakeCount: Int = udpFakeCount ?: 0
val dropSack: Boolean = dropSack ?: false
val fakeOffset: Int = byedpiFakeOffset ?: 0
constructor(preferences: SharedPreferences) : this(
ip = preferences.getString("byedpi_proxy_ip", null),
@ -107,7 +111,7 @@ class ByeDpiProxyUIPreferences(
splitAtHost = preferences.getBoolean("byedpi_split_at_host", false),
fakeTtl = preferences.getString("byedpi_fake_ttl", null)?.toIntOrNull(),
fakeSni = preferences.getString("byedpi_fake_sni", null),
oobData = preferences.getString("byedpi_oob_data", null),
oobChar = preferences.getString("byedpi_oob_data", null),
hostMixedCase = preferences.getBoolean("byedpi_host_mixed_case", false),
domainMixedCase = preferences.getBoolean("byedpi_domain_mixed_case", false),
hostRemoveSpaces = preferences.getBoolean("byedpi_host_remove_spaces", false),
@ -126,6 +130,8 @@ class ByeDpiProxyUIPreferences(
},
tcpFastOpen = preferences.getBoolean("byedpi_tcp_fast_open", false),
udpFakeCount = preferences.getString("byedpi_udp_fake_count", null)?.toIntOrNull(),
dropSack = preferences.getBoolean("byedpi_drop_sack", false),
byedpiFakeOffset = preferences.getString("byedpi_fake_offset", null)?.toIntOrNull(),
)
enum class DesyncMethod {
@ -133,7 +139,8 @@ class ByeDpiProxyUIPreferences(
Split,
Disorder,
Fake,
OOB;
OOB,
DISOOB;
companion object {
fun fromName(name: String): DesyncMethod {
@ -143,6 +150,7 @@ class ByeDpiProxyUIPreferences(
"disorder" -> Disorder
"fake" -> Fake
"oob" -> OOB
"disoob" -> DISOOB
else -> throw IllegalArgumentException("Unknown desync method: $name")
}
}

View File

@ -78,7 +78,8 @@ class ByeDpiUISettingsFragment : PreferenceFragmentCompat() {
val splitAtHost = findPreferenceNotNull<CheckBoxPreference>("byedpi_split_at_host")
val ttlFake = findPreferenceNotNull<EditTextPreference>("byedpi_fake_ttl")
val fakeSni = findPreferenceNotNull<EditTextPreference>("byedpi_fake_sni")
val oobData = findPreferenceNotNull<EditTextPreference>("byedpi_oob_data")
val fakeOffset = findPreferenceNotNull<EditTextPreference>("byedpi_fake_offset")
val oobChar = findPreferenceNotNull<EditTextPreference>("byedpi_oob_data")
val udpFakeCount = findPreferenceNotNull<EditTextPreference>("byedpi_udp_fake_count")
val hostMixedCase = findPreferenceNotNull<CheckBoxPreference>("byedpi_host_mixed_case")
val domainMixedCase = findPreferenceNotNull<CheckBoxPreference>("byedpi_domain_mixed_case")
@ -89,81 +90,36 @@ class ByeDpiUISettingsFragment : PreferenceFragmentCompat() {
findPreferenceNotNull<EditTextPreference>("byedpi_tlsrec_position")
val splitTlsRecAtSni = findPreferenceNotNull<CheckBoxPreference>("byedpi_tlsrec_at_sni")
when (hostsMode) {
Disable -> {
hostsBlacklist.isVisible = false
hostsWhitelist.isVisible = false
}
hostsBlacklist.isVisible = hostsMode == Blacklist
hostsWhitelist.isVisible = hostsMode == Whitelist
Blacklist -> {
hostsBlacklist.isVisible = true
hostsWhitelist.isVisible = false
}
val desyncEnabled = desyncMethod != None
splitPosition.isVisible = desyncEnabled
splitAtHost.isVisible = desyncEnabled
Whitelist -> {
hostsBlacklist.isVisible = false
hostsWhitelist.isVisible = true
}
}
val isFake = desyncMethod == Fake
ttlFake.isVisible = isFake
fakeSni.isVisible = isFake
fakeOffset.isVisible = isFake
val isOob = desyncMethod == OOB || desyncMethod == DISOOB
oobChar.isVisible = isOob
val desyncAllProtocols =
!desyncHttp.isChecked && !desyncHttps.isChecked && !desyncUdp.isChecked
if (desyncAllProtocols || desyncUdp.isChecked) {
udpFakeCount.isVisible = true
} else {
udpFakeCount.isVisible = false
}
val desyncHttpEnabled = desyncAllProtocols || desyncHttp.isChecked
hostMixedCase.isEnabled = desyncHttpEnabled
domainMixedCase.isEnabled = desyncHttpEnabled
hostRemoveSpaces.isEnabled = desyncHttpEnabled
when (desyncMethod) {
None -> {
splitPosition.isVisible = false
splitAtHost.isVisible = false
ttlFake.isVisible = false
fakeSni.isVisible = false
oobData.isVisible = false
hostMixedCase.isVisible = false
domainMixedCase.isVisible = false
hostRemoveSpaces.isVisible = false
}
val desyncUdpEnabled = desyncAllProtocols || desyncUdp.isChecked
udpFakeCount.isEnabled = desyncUdpEnabled
else -> {
splitPosition.isVisible = true
splitAtHost.isVisible = true
if (desyncAllProtocols || desyncHttp.isChecked) {
hostMixedCase.isVisible = true
domainMixedCase.isVisible = true
hostRemoveSpaces.isVisible = true
} else {
hostMixedCase.isVisible = false
domainMixedCase.isVisible = false
hostRemoveSpaces.isVisible = false
}
when (desyncMethod) {
Fake -> {
ttlFake.isVisible = true
fakeSni.isVisible = true
oobData.isVisible = false
}
OOB -> {
ttlFake.isVisible = false
fakeSni.isVisible = false
oobData.isVisible = true
}
else -> {
ttlFake.isVisible = false
fakeSni.isVisible = false
oobData.isVisible = false
}
}
}
}
splitTlsRecPosition.isVisible = splitTlsRec.isChecked
splitTlsRecAtSni.isVisible = splitTlsRec.isChecked
val desyncHttpsEnabled = desyncAllProtocols || desyncHttps.isChecked
splitTlsRec.isEnabled = desyncHttpsEnabled
val tlsRecEnabled = desyncHttpsEnabled && splitTlsRec.isChecked
splitTlsRecPosition.isEnabled = tlsRecEnabled
splitTlsRecAtSni.isEnabled = tlsRecEnabled
}
}

View File

@ -39,7 +39,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
setPreferencesFromResource(R.xml.main_settings, rootKey)
setEditTextPreferenceListener("dns_ip") {
it.isBlank() || checkIp(it)
it.isBlank() || checkNotLocalIp(it)
}
findPreferenceNotNull<DropDownPreference>("app_theme")

View File

@ -208,12 +208,6 @@ class ByeDpiVpnService : LifecycleVpnService() {
TProxyService.TProxyStartService(configPath.absolutePath, fd.fd)
try {
File(cacheDir, "config.tmp").delete()
} catch (e: SecurityException) {
Log.e(TAG, "Failed to delete config file", e)
}
Log.i(TAG, "Tun2Socks started")
}
@ -222,6 +216,12 @@ class ByeDpiVpnService : LifecycleVpnService() {
TProxyService.TProxyStopService()
try {
File(cacheDir, "config.tmp").delete()
} catch (e: SecurityException) {
Log.e(TAG, "Failed to delete config file", e)
}
tunFd?.close() ?: Log.w(TAG, "VPN not running")
tunFd = null

View File

@ -10,6 +10,16 @@ import androidx.preference.PreferenceFragmentCompat
private const val TAG = "ValidateUtils"
fun checkIp(ip: String): Boolean =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
InetAddresses.isNumericAddress(ip)
} else {
// This pattern doesn't not support IPv6
// @Suppress("DEPRECATION")
// Patterns.IP_ADDRESS.matcher(ip).matches()
true
}
fun checkNotLocalIp(ip: String): Boolean =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
InetAddresses.isNumericAddress(ip) && InetAddresses.parseNumericAddress(ip).let {
!it.isAnyLocalAddress && !it.isLoopbackAddress

View File

@ -26,6 +26,7 @@
<item name="disorder">Disorder</item>
<item name="fake">Fake</item>
<item name="oob">Out-of-band</item>
<item name="oob">Disordered out-of-band</item>
</array>
<array name="byedpi_desync_methods_entries">
<item name="none">none</item>
@ -33,6 +34,7 @@
<item name="disorder">disorder</item>
<item name="fake">fake</item>
<item name="oob">oob</item>
<item name="oob">disoob</item>
</array>
<array name="byedpi_hosts_modes">

View File

@ -1,5 +1,5 @@
<resources>
<string name="byedpi_docs">https://github.com/hufrea/byedpi/tree/v0.12#readme</string>
<string name="byedpi_docs">https://github.com/hufrea/byedpi/blob/v0.13/README.md</string>
<string name="app_name">ByeDPI</string>
<string name="vpn_connect">Connect</string>
<string name="vpn_disconnect">Disconnect</string>
@ -65,4 +65,11 @@
<string name="byedpi_tcp_fast_open_setting">TCP Fast Open</string>
<string name="byedpi_udp_fake_count">UDP fake count</string>
<string name="ipv6_setting">IPv6</string>
<string name="byedpi_fake_offset_setting">Fake offset</string>
<string name="byedpi_drop_sack_setting">Drop SACK</string>
<string name="desync_udp_category">UDP</string>
<string name="desync_http_category">HTTP</string>
<string name="desync_https_category">HTTPS</string>
<string name="byedpi_protocols_category">Protocols</string>
<string name="byedpi_protocols_hint">Uncheck all to desync all traffic</string>
</resources>

View File

@ -48,6 +48,11 @@
android:title="@string/byedpi_no_domain_setting"
android:defaultValue="false" />
<CheckBoxPreference
android:key="byedpi_tcp_fast_open"
android:title="@string/byedpi_tcp_fast_open_setting"
android:defaultValue="false" />
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
@ -75,11 +80,6 @@
android:inputType="textMultiLine"
app:useSimpleSummaryProvider="true" />
<CheckBoxPreference
android:key="byedpi_tcp_fast_open"
android:title="@string/byedpi_tcp_fast_open_setting"
android:defaultValue="false" />
<com.takisoft.preferencex.EditTextPreference
android:key="byedpi_default_ttl"
android:title="@string/byedpi_default_ttl_setting"
@ -95,6 +95,55 @@
android:defaultValue="disorder"
app:useSimpleSummaryProvider="true" />
<com.takisoft.preferencex.EditTextPreference
android:key="byedpi_split_position"
android:title="@string/byedpi_split_position_setting"
android:inputType="numberSigned"
android:defaultValue="1"
app:useSimpleSummaryProvider="true" />
<CheckBoxPreference
android:key="byedpi_split_at_host"
android:title="@string/byedpi_split_at_host_setting"
android:defaultValue="false" />
<CheckBoxPreference
android:key="byedpi_drop_sack"
android:title="@string/byedpi_drop_sack_setting"
android:defaultValue="false" />
<com.takisoft.preferencex.EditTextPreference
android:key="byedpi_fake_ttl"
android:title="@string/byedpi_fake_ttl_setting"
android:inputType="number"
android:defaultValue="8"
app:useSimpleSummaryProvider="true" />
<com.takisoft.preferencex.EditTextPreference
android:key="byedpi_fake_offset"
android:title="@string/byedpi_fake_offset_setting"
android:inputType="number"
android:defaultValue="0"
app:useSimpleSummaryProvider="true" />
<com.takisoft.preferencex.EditTextPreference
android:key="byedpi_fake_sni"
android:title="@string/sni_of_fake_packet"
android:defaultValue="www.iana.org"
app:useSimpleSummaryProvider="true" />
<com.takisoft.preferencex.EditTextPreference
android:key="byedpi_oob_data"
android:title="@string/oob_data"
android:defaultValue="a"
app:useSimpleSummaryProvider="true" />
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:title="@string/byedpi_protocols_category"
android:summary="@string/byedpi_protocols_hint">
<CheckBoxPreference
android:key="byedpi_desync_http"
android:title="@string/desync_http"
@ -110,43 +159,10 @@
android:title="@string/desync_udp"
android:defaultValue="false" />
<com.takisoft.preferencex.EditTextPreference
android:key="byedpi_split_position"
android:title="@string/byedpi_split_position_setting"
android:inputType="numberSigned"
android:defaultValue="2"
app:useSimpleSummaryProvider="true" />
</androidx.preference.PreferenceCategory>
<CheckBoxPreference
android:key="byedpi_split_at_host"
android:title="@string/byedpi_split_at_host_setting"
android:defaultValue="false" />
<com.takisoft.preferencex.EditTextPreference
android:key="byedpi_fake_ttl"
android:title="@string/byedpi_fake_ttl_setting"
android:inputType="number"
android:defaultValue="8"
app:useSimpleSummaryProvider="true" />
<com.takisoft.preferencex.EditTextPreference
android:key="byedpi_fake_sni"
android:title="@string/sni_of_fake_packet"
android:defaultValue="www.iana.org"
app:useSimpleSummaryProvider="true" />
<com.takisoft.preferencex.EditTextPreference
android:key="byedpi_oob_data"
android:title="@string/oob_data"
android:defaultValue="a"
app:useSimpleSummaryProvider="true" />
<com.takisoft.preferencex.EditTextPreference
android:key="byedpi_udp_fake_count"
android:title="@string/byedpi_udp_fake_count"
android:inputType="number"
android:defaultValue="0"
app:useSimpleSummaryProvider="true" />
<androidx.preference.PreferenceCategory
android:title="@string/desync_http_category">
<CheckBoxPreference
android:key="byedpi_host_mixed_case"
@ -163,6 +179,11 @@
android:title="@string/byedpi_host_remove_spaces_setting"
android:defaultValue="false"/>
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:title="@string/desync_https_category">
<CheckBoxPreference
android:key="byedpi_tlsrec_enabled"
android:title="@string/byedpi_tlsrec_enabled_setting"
@ -182,4 +203,16 @@
</androidx.preference.PreferenceCategory>
<androidx.preference.PreferenceCategory
android:title="@string/desync_udp_category">
<com.takisoft.preferencex.EditTextPreference
android:key="byedpi_udp_fake_count"
android:title="@string/byedpi_udp_fake_count"
android:inputType="number"
android:defaultValue="0"
app:useSimpleSummaryProvider="true" />
</androidx.preference.PreferenceCategory>
</PreferenceScreen>

View File

@ -1 +1 @@
<p><i>ByeDPI</i> runs a local VPN service to bypass DPI (Deep Packet Inspection) and censorship. It runs a SOCKS5 proxy <a href='https://github.com/hufrea/byedpi' target='_blank' rel='nofollow noopener'>ByeDPI</a> and redirects all traffic through it.</p><p>To bypass some blocks, you may need to change the settings. More about the various settings can be found in the <a href='https://github.com/hufrea/byedpi#readme-ov-file' target='_blank' rel='nofollow noopener'>ByeDPI documentation</a>.</p><p>The application uses the VPN mode on Android to redirect traffic, but does not send anything to a remote server. It does not encrypt traffic and does not hide your IP address.</p>
<p><i>ByeDPI</i> runs a local VPN service to bypass DPI (Deep Packet Inspection) and censorship. It runs a SOCKS5 proxy <a href='https://github.com/hufrea/byedpi' target='_blank' rel='nofollow noopener'>ByeDPI</a> and redirects all traffic through it.</p><p>To bypass some blocks, you may need to change the settings. More about the various settings can be found in the <a href='https://github.com/hufrea/byedpi/blob/main/README.md' target='_blank' rel='nofollow noopener'>ByeDPI documentation</a>.</p><p>The application uses the VPN mode on Android to redirect traffic, but does not send anything to a remote server. It does not encrypt traffic and does not hide your IP address.</p>

View File

@ -1 +1 @@
<p><i>ByeDPI</i> runs a local VPN service to bypass DPI (Deep Packet Inspection) and censorship. It runs a SOCKS5 proxy <a href='https://github.com/hufrea/byedpi' target='_blank' rel='nofollow noopener'>ByeDPI</a> and redirects all traffic through it.</p><p>To bypass some blocks, you may need to change the settings. More about the various settings can be found in the <a href='https://github.com/hufrea/byedpi#readme-ov-file' target='_blank' rel='nofollow noopener'>ByeDPI documentation</a>.</p><p>The application uses the VPN mode on Android to redirect traffic, but does not send anything to a remote server. It does not encrypt traffic and does not hide your IP address.</p>
<p><i>ByeDPI</i> runs a local VPN service to bypass DPI (Deep Packet Inspection) and censorship. It runs a SOCKS5 proxy <a href='https://github.com/hufrea/byedpi' target='_blank' rel='nofollow noopener'>ByeDPI</a> and redirects all traffic through it.</p><p>To bypass some blocks, you may need to change the settings. More about the various settings can be found in the <a href='https://github.com/hufrea/byedpi/blob/main/README.md' target='_blank' rel='nofollow noopener'>ByeDPI documentation</a>.</p><p>The application uses the VPN mode on Android to redirect traffic, but does not send anything to a remote server. It does not encrypt traffic and does not hide your IP address.</p>