Compare commits

..

18 Commits

Author SHA1 Message Date
krlvm
43db0955de
Remove dependency on ConstraintLayout (#133) 2024-09-05 09:01:39 +03:00
dovecoteescapee
9d289f096e Update fastlane descriptions 2024-08-23 18:45:57 +03:00
dovecoteescapee
c95be6eb91 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
2024-08-23 18:32:36 +03:00
dovecoteescapee
9a6254869d Improvements and fixes (v 1.1.1):
- Added TCP Fast Open and UDP fake count to UI editor
- Added IPv6 support
- Changed default split position to 2
- Improved DNS domain validation
- Adjusted QuickTile icon
- Added russian description for fastlane
2024-08-22 02:03:36 +03:00
dovecoteescapee
7a3850c7d3 Update README and links 2024-08-21 16:39:30 +03:00
Izzy
4da80c8372
initial Fastlane structures from IzzyOnDroid (#100) 2024-08-21 07:18:50 +03:00
dovecoteescapee
642f1ca477 Add screenshots 2024-08-19 03:58:31 +03:00
dovecoteescapee
b1f139f2ea Update README 2024-08-19 01:47:16 +03:00
dovecoteescapee
88e1b75dd5
Improvements and fixes (#96)
Improvements and fixes:
- Added Hosts to UI editor
- Allowed not to specify DNS
- Changed the level of saved logs to Debug
- Fixed bug with Reset button
2024-08-19 01:09:08 +03:00
dovecoteescapee
31d75606bc
Replace tun2socks with hev-socks5-tunnel (#94) 2024-08-18 22:02:46 +03:00
Viktor45
26463ae30f
Add Android TV banner (#86)
Basic AndroidTV leanback support for not to use sideload launcher at AndroidTV, still needed to make settings gear selectable by D-pad
2024-08-18 21:49:24 +03:00
dovecoteescapee
6580068112 Update FAQ 2024-08-12 17:51:26 +03:00
dovecoteescapee
88107def37 Disable dependenciesInfo 2024-08-12 17:31:48 +03:00
dovecoteescapee
f4b9d8de40 Add preview 2024-08-12 17:26:49 +03:00
dovecoteescapee
b7210d167e ntc -> NTC 2024-08-12 13:41:34 +03:00
dovecoteescapee
f57692b7f2
Merge pull request #81 from dovecoteescapee/dev
Add summary for cmd arguments
2024-08-11 16:07:27 +03:00
dovecoteescapee
6f8e0827a7 Add summary for cmd arguments 2024-08-11 16:06:42 +03:00
dovecoteescapee
96b23abaf0 Add issue templates 2024-08-11 15:27:52 +03:00
50 changed files with 761 additions and 388 deletions

67
.github/ISSUE_TEMPLATE/bug.yml vendored Normal file
View File

@ -0,0 +1,67 @@
name: Bug Report / Сообщение об ошибке
description: File a bug report / Сообщить об ошибке в программе
labels: [ bug ]
assignees: dovecoteescapee
body:
- type: markdown
attributes:
value: |
### If you have trouble with specific websites or or can't configure the app, please use the [discussions section](https://github.com/dovecoteescapee/ByeDPIAndroid/discussions) to discuss it. This template is only for reporting bugs in the ByeDPI program.
### Если у вас не работают какие-то сайты или не получается настроить приложение, используйте [раздел дискуссий](https://github.com/dovecoteescapee/ByeDPIAndroid/discussions) для обсуждения этого. Этот шаблон предназначен только для сообщений об ошибках в программе ByeDPI.
- type: textarea
id: bug
attributes:
label: Describe the bug / Описание ошибки
description: A clear and concise description of what the bug is / Четкое и краткое описание ошибки
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: To Reproduce / Как воспроизвести
description: Steps to reproduce the behavior / Шаги для воспроизведения проблемы
value: |
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected behavior / Ожидаемое поведение
description: A clear and concise description of what you expected to happen / Четкое и краткое описание ожидаемого поведения
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: Screenshots / Скриншоты
description: If applicable, add screenshots to help explain your problem / При необходимости добавьте скриншоты, чтобы объяснить вашу проблему
- type: textarea
id: environment
attributes:
label: Environment / Окружение
description: Please complete the following information / Пожалуйста, заполните следующую информацию
value: |
**Smartphone / Смартфон:**
- Device: [e.g. Pixel Fold, Samsung Galaxy S24]
- Android version: [e.g. 10]
- ByeDPI version: [e.g. 1.0.2]
validations:
required: true
- type: textarea
id: context
attributes:
label: Additional context / Дополнительная информация
description: Add any other context about the problem here / Добавьте любую другую информацию о проблеме здесь
- type: checkboxes
id: checklist
attributes:
label: Before you submit / Прежде чем отправить
options:
- label: I have searched the open and closed issues for duplicates / Я искал(а) открытые и закрытые задачи на предмет дубликатов
required: true
- label: This is not a question, feature request, or general feedback / Это не вопрос, предложение новой функциональности или общий отзыв
required: true

8
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Questions about the program on Github / Вопросы по програме на Github
url: https://github.com/dovecoteescapee/ByeDPIAndroid/discussions
about: Please do not ask questions in the issue tracker / Пожалуйста, не задавайте вопросы в трекере задач
- name: Questions about the program on NTC.party / Вопросы по програме на NTC.party
url: https://ntc.party/c/community-software/byedpi/39
about: Please do not ask questions in the issue tracker / Пожалуйста, не задавайте вопросы в трекере задач

35
.github/ISSUE_TEMPLATE/feature.yml vendored Normal file
View File

@ -0,0 +1,35 @@
name: Feature request / Предложить новую функциональность
description: Suggest an idea for this project / Предложить идею для проекта
labels: [ enhancement ]
assignees: dovecoteescapee
body:
- type: textarea
id: problem
attributes:
label: What problem does your proposal solve? / Какую проблему решает ваше предложение?
description: A clear and concise description of what the problem is / Четкое и краткое описание проблемы
validations:
required: true
- type: textarea
id: solution
attributes:
label: Describe the solution you'd like / Опишите решение, которое вы предлагаете
description: A clear and concise description of what you want to happen / Четкое и краткое описание того, что вы хотите, чтобы произошло
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Describe alternatives you've considered / Опишите альтернативные варианты, которые вы рассматривали
description: A clear and concise description of any alternative solutions or features you've considered / Четкое и краткое описание любых альтернативных решений или функций, которые вы рассматривали
validations:
required: true
- type: checkboxes
id: checklist
attributes:
label: Before you submit / Прежде чем отправить
options:
- label: I have searched the open and closed issues for duplicates / Я искал(а) открытые и закрытые задачи на предмет дубликатов
required: true
- label: I have verified that this feature does not already exist / Я убедился(ась), что эта функция еще не существует
required: true

1
.gitignore vendored
View File

@ -14,3 +14,4 @@
.externalNativeBuild
.cxx
local.properties
/app/src/main/jniLibs

8
.gitmodules vendored
View File

@ -1,6 +1,6 @@
[submodule "app/libs/tun2socks"]
path = app/libs/tun2socks
url = https://github.com/dovecoteescapee/tun2socks.git
[submodule "app/src/main/cpp/byedpi"]
[submodule "hev-socks5-tunnel"]
path = app/src/main/jni/hev-socks5-tunnel
url = https://github.com/heiher/hev-socks5-tunnel.git
[submodule "byedpi"]
path = app/src/main/cpp/byedpi
url = https://github.com/hufrea/byedpi.git

View File

@ -2,7 +2,11 @@
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/app/libs/tun2socks" vcs="Git" />
<mapping directory="$PROJECT_DIR$/app/src/main/cpp/byedpi" vcs="Git" />
<mapping directory="$PROJECT_DIR$/app/src/main/jni/hev-socks5-tunnel" vcs="Git" />
<mapping directory="$PROJECT_DIR$/app/src/main/jni/hev-socks5-tunnel/src/core" vcs="Git" />
<mapping directory="$PROJECT_DIR$/app/src/main/jni/hev-socks5-tunnel/third-part/hev-task-system" vcs="Git" />
<mapping directory="$PROJECT_DIR$/app/src/main/jni/hev-socks5-tunnel/third-part/lwip" vcs="Git" />
<mapping directory="$PROJECT_DIR$/app/src/main/jni/hev-socks5-tunnel/third-part/yaml" vcs="Git" />
</component>
</project>

View File

@ -3,44 +3,43 @@
[English](README.md) | **Русский**
<div style="text-align: center;">
<img src=".github/images/logo.svg" width="100%" height="200px">
<img alt="Логотип ByeDPI" src=".github/images/logo.svg" width="100%" height="200px">
</div>
---
Приложение для Android, которое запускает локальный VPN-сервис для обхода DPI (Deep Packet Inspection) и цензуры.
Приложение локально запускает [ByeDPI](https://github.com/hufrea/byedpi) и перенаправляет весь трафик через него.
Приложение локально запускает SOCKS5-прокси [ByeDPI](https://github.com/hufrea/byedpi) и перенаправляет весь трафик через него.
## Установка
[<img src="https://github.com/machiav3lli/oandbackupx/blob/034b226cea5c1b30eb4f6a6f313e4dadcbb0ece4/badge_github.png"
alt="Скачать с GitHub"
height="80">](https://github.com/dovecoteescapee/ByeDPIAndroid/releases)
[<img src="https://gitlab.com/IzzyOnDroid/repo/-/raw/master/assets/IzzyOnDroid.png"
alt="Скачать с IzzyOnDroid"
height="80">](https://apt.izzysoft.de/fdroid/index/apk/io.github.dovecoteescapee.byedpi)
### Или используйте Obtainium
1. Установите [Obtainium](https://github.com/ImranR98/Obtainium?tab=readme-ov-file#installation)
1. Установите [Obtainium](https://github.com/ImranR98/Obtainium/blob/main/README.md#installation)
2. Добавьте приложение по URL:
`https://github.com/dovecoteescapee/ByeDPIAndroid`
## Настройки
Для обхода некоторых блокировок может потребоваться изменить настройки. Подробнее о различных настройках можно прочитать в [документации ByeDPI](https://github.com/hufrea/byedpi#readme-ov-file).
Для обхода некоторых блокировок может потребоваться изменить настройки. Подробнее о различных настройках можно прочитать в [документации ByeDPI](https://github.com/hufrea/byedpi/blob/v0.13/README.md).
## FAQ
### Это вирус?
Нет. [Обсуждение проблемы](https://github.com/dovecoteescapee/ByeDPIAndroid/issues/61).
### У меня не получается настроить. Что делать?
Вы можете попросить помощи в [discussion](https://github.com/dovecoteescapee/ByeDPIAndroid/discussions).
### Как получать обновления?
### Приложение требует root-права?
Используйте [Obtainium](#или-используйте-obtainium).
Нет. Все функции приложения работают без root-прав.
### Это VPN?
@ -50,20 +49,30 @@
Никакие. Приложения не отправляет никакие данные на удаленный сервер. Весь трафик обрабатывается на устройстве.
### Как использовать ByeDPI вместе с AdGuard?
1. Запустите ByeDPI в режиме прокси.
2. Добавьте ByeDPI в исключения AdGuard на вкладке "Управление приложениями".
3. В настройках AdGuard укажите прокси:
```plaintext
Тип прокси: SOCKS5
Хост: 127.0.0.1
Порт: 1080 (по умолчанию)
```
### А есть для других платформ?
Для Windows существует [GoodByeDPI](https://github.com/ValdikSS/GoodbyeDPI), а для Linux и macOS [zapret](https://github.com/bol-van/zapret). Также, вы можете использовать оригинальный [ByeDPI](https://github.com/hufrea/byedpi) для запуска аналогичного прокси на Windows, Linux или macOS.
[Другие аналоги](https://github.com/ValdikSS/GoodbyeDPI?tab=readme-ov-file#similar-projects)
[Список аналогов](https://github.com/ValdikSS/GoodbyeDPI/blob/master/README.md#similar-projects)
### Что такое DPI?
DPI (Deep Packet Inspection) - это технология для анализа и фильтрации трафика. Она используется провайдерами и государственными органами для блокировки сайтов и сервисов.
DPI (Deep Packet Inspection) - это технология для анализа и фильтрации трафика. Она используется провайдерами и государственными органами для блокировки сайтов и сервисов.
## Зависимости
- [ByeDPI](https://github.com/hufrea/byedpi)
- [Tun2Socks](https://github.com/xjasonlyu/tun2socks)
- [hev-socks5-tunnel](https://github.com/heiher/hev-socks5-tunnel)
## Сборка
@ -72,22 +81,16 @@ DPI (Deep Packet Inspection) - это технология для анализа
1. JDK 8 или новее
2. Android SDK
3. Android NDK
4. Go 1.22 или новее
5. CMake 3.22.1 или новее
4. CMake 3.22.1 или новее
Сборка приложения:
1. Установите gomobile:
```bash
go install golang.org/x/mobile/cmd/gomobile@latest
gomobile init
```
2. Клонируйте репозиторий с подмодулями:
1. Клонируйте репозиторий с подмодулями:
```bash
git clone --recurse-submodules
```
3. Запустите скрипт сборки из корня репозитория:
2. Запустите скрипт сборки из корня репозитория:
```bash
./gradlew assembleRelease`
```
4. APK будет лежать в `app/build/outputs/apk/release/`
3. APK будет лежать в `app/build/outputs/apk/release/`

View File

@ -3,58 +3,68 @@
**English** | [Русский](README-ru.md)
<div style="text-align: center;">
<img src=".github/images/logo.svg" width="100%" height="200px">
<img alt="ByeDPI logo" src=".github/images/logo.svg" width="100%" height="200px">
</div>
---
Android application that runs a local VPN service to bypass DPI (Deep Packet Inspection) and censorship.
The application locally runs [ByeDPI](https://github.com/hufrea/byedpi) and redirects all traffic through it.
This application runs a SOCKS5 proxy [ByeDPI](https://github.com/hufrea/byedpi) and redirects all traffic through it.
## Installation
[<img src="https://github.com/machiav3lli/oandbackupx/blob/034b226cea5c1b30eb4f6a6f313e4dadcbb0ece4/badge_github.png"
alt="Get it on GitHub"
height="80">](https://github.com/dovecoteescapee/ByeDPIAndroid/releases)
[<img src="https://gitlab.com/IzzyOnDroid/repo/-/raw/master/assets/IzzyOnDroid.png"
alt="Get it on IzzyOnDroid"
height="80">](https://apt.izzysoft.de/fdroid/index/apk/io.github.dovecoteescapee.byedpi)
### Or use Obtainium
1. Install [Obtainium](https://github.com/ImranR98/Obtainium?tab=readme-ov-file#installation)
1. Install [Obtainium](https://github.com/ImranR98/Obtainium/blob/main/README.md#installation)
2. Add the app by URL:
`https://github.com/dovecoteescapee/ByeDPIAndroid`
## 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#readme-ov-file).
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
### Is this a virus?
No. [Discussion of the problem](https://github.com/dovecoteescapee/ByeDPIAndroid/issues/61).
### I can't configure it. What to do?
You can ask for help in [discussion](https://github.com/dovecoteescapee/ByeDPIAndroid/discussions).
### How to get updates?
### Does the application require root access?
Use [Obtainium](#or-use-obtainium).
No. All application features work without root.
### Is this a VPN?
No. 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.
### How to use ByeDPI with AdGuard?
1. Run ByeDPI in proxy mode.
2. Add ByeDPI to AdGuard exceptions on the "App management" tab.
3. In AdGuard settings, specify the proxy:
```plaintext
Proxy type: SOCKS5
Proxy host: 127.0.0.1
Proxy port: 1080 (default)
```
### What data does the application collect?
None. The application does not send any data to a remote server. All traffic is processed on the device.
### Are there any for other platforms?
For Windows, there is [GoodByeDPI](https://github.com/ValdikSS/GoodbyeDPI), and for Linux and macOS [zapret](https://github.com/bol-van/zapret). Also, you can use the original [ByeDPI](https://github.com/hufrea/byedpi) to run a similar proxy on Windows, Linux, or macOS.
[Other similar projects](https://github.com/ValdikSS/GoodbyeDPI?tab=readme-ov-file#similar-projects)
[Similar projects](https://github.com/ValdikSS/GoodbyeDPI/blob/master/README.md#similar-projects))
### What is DPI?
@ -63,7 +73,7 @@ DPI (Deep Packet Inspection) is a technology for analyzing and filtering traffic
## Dependencies
- [ByeDPI](https://github.com/hufrea/byedpi)
- [Tun2Socks](https://github.com/xjasonlyu/tun2socks)
- [hev-socks5-tunnel](https://github.com/heiher/hev-socks5-tunnel)
## Building
@ -72,22 +82,16 @@ For building the application, you need:
1. JDK 8 or later
2. Android SDK
3. Android NDK
4. Go 1.22 or later
5. CMake 3.22.1 or later
4. CMake 3.22.1 or later
To build the application:
1. Install gomobile:
```bash
go install golang.org/x/mobile/cmd/gomobile@latest
gomobile init
```
2. Clone the repository with submodules:
1. Clone the repository with submodules:
```bash
git clone --recurse-submodules
```
3. Run the build script from the root of the repository:
2. Run the build script from the root of the repository:
```bash
./gradlew assembleRelease
```
4. The APK will be in `app/build/outputs/apk/release/`
3. The APK will be in `app/build/outputs/apk/release/`

View File

@ -1,5 +1,3 @@
import com.android.build.gradle.internal.tasks.factory.dependsOn
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
@ -13,10 +11,17 @@ android {
applicationId = "io.github.dovecoteescapee.byedpi"
minSdk = 21
targetSdk = 34
versionCode = 7
versionName = "1.0.2"
versionCode = 10
versionName = "1.2.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
ndk {
abiFilters.add("armeabi-v7a")
abiFilters.add("arm64-v8a")
abiFilters.add("x86")
abiFilters.add("x86_64")
}
}
buildFeatures {
@ -50,18 +55,23 @@ android {
buildFeatures {
viewBinding = true
}
// https://android.izzysoft.de/articles/named/iod-scan-apkchecks?lang=en#blobs
dependenciesInfo {
// Disables dependency metadata when building APKs.
includeInApk = false
// Disables dependency metadata when building Android App Bundles.
includeInBundle = false
}
}
dependencies {
implementation(files("libs/tun2socks.aar"))
implementation("androidx.fragment:fragment-ktx:1.8.2")
implementation("androidx.core:core-ktx:1.13.1")
implementation("androidx.appcompat:appcompat:1.7.0")
implementation("androidx.preference:preference-ktx:1.2.1")
implementation("com.takisoft.preferencex:preferencex:1.1.0")
implementation("com.google.android.material:material:1.12.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.4")
implementation("androidx.lifecycle:lifecycle-service:2.8.4")
testImplementation("junit:junit:4.13.2")
@ -69,75 +79,25 @@ dependencies {
androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
}
abstract class BaseTun2SocksTask : DefaultTask() {
@get:InputDirectory
val tun2socksDir: File
get() = project.file("libs/tun2socks")
@get:OutputFile
val tun2socksOutput: File
get() = project.file("libs/tun2socks.aar")
@Internal
protected fun isUpToDate(): Boolean {
if (tun2socksOutput.exists()) {
val lastModified = tun2socksOutput.lastModified()
return !tun2socksDir.walkTopDown().any {
it.isFile && it.lastModified() > lastModified
}
}
return false
}
}
abstract class GetGomobileBind : BaseTun2SocksTask() {
@TaskAction
fun getBind() {
if (isUpToDate()) {
logger.lifecycle("No changes detected, skipping getBind.")
return
}
project.exec {
workingDir = tun2socksDir
commandLine("go", "get", "golang.org/x/mobile/bind")
}
}
}
abstract class BuildTun2Socks : BaseTun2SocksTask() {
@TaskAction
fun buildTun2Socks() {
if (isUpToDate()) {
logger.lifecycle("No changes detected, skipping buildTun2Socks.")
return
}
project.exec {
workingDir = tun2socksDir
commandLine(
"gomobile", "bind",
"-target", "android",
"-androidapi", "21",
"-o", tun2socksOutput,
"-trimpath",
"./engine"
)
}
}
}
val getGomobileBind = tasks.register<GetGomobileBind>("getGomobileBind") {
tasks.register<Exec>("runNdkBuild") {
group = "build"
description = "Get gomobile bind for compiling tun2socks"
val ndkDir = android.ndkDirectory
executable = if (System.getProperty("os.name").startsWith("Windows", ignoreCase = true)) {
"$ndkDir\\ndk-build.cmd"
} else {
"$ndkDir/ndk-build"
}
setArgs(listOf(
"NDK_PROJECT_PATH=build/intermediates/ndkBuild",
"NDK_LIBS_OUT=src/main/jniLibs",
"APP_BUILD_SCRIPT=src/main/jni/Android.mk",
"NDK_APPLICATION_MK=src/main/jni/Application.mk"
))
println("Command: $commandLine")
}
val buildTun2Socks = tasks.register<BuildTun2Socks>("buildTun2Socks") {
group = "build"
description = "Build tun2socks for Android"
dependsOn(getGomobileBind)
}
tasks.preBuild.dependsOn(buildTun2Socks)
tasks.preBuild {
dependsOn("runNdkBuild")
}

@ -1 +0,0 @@
Subproject commit e083dafcf534d85e7fce86b3d48ee5c7a63c604e

View File

@ -6,12 +6,18 @@
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-feature android:name="android.software.leanback"
android:required="false" />
<uses-feature android:name="android.hardware.touchscreen"
android:required="false" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:banner="@mipmap/ic_launcher_foreground"
android:logo="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
@ -25,6 +31,7 @@
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
</activity>

View File

@ -1,53 +1,14 @@
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html.
# For more examples on how to use CMake, see https://github.com/android/ndk-samples.
# Sets the minimum CMake version required for this project.
cmake_minimum_required(VERSION 3.22.1)
# Declares the project name. The project name can be accessed via ${ PROJECT_NAME},
# Since this is the top level CMakeLists.txt, the project name is also accessible
# with ${CMAKE_PROJECT_NAME} (both CMake variables are in-sync within the top level
# build script scope).
project("byedpi")
project(byedpi_native)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
#
# In this top level CMakeLists.txt, ${CMAKE_PROJECT_NAME} is used to define
# the target library name; in the sub-module's CMakeLists.txt, ${PROJECT_NAME}
# is preferred for the same purpose.
#
# In order to load a library into your app from Java/Kotlin, you must call
# System.loadLibrary() and pass the name of the library defined here;
# for GameActivity/NativeActivity derived applications, the same library name must be
# used in the AndroidManifest.xml file.
add_library(${CMAKE_PROJECT_NAME} SHARED
# List C/C++ source files with relative paths to this CMakeLists.txt.
byedpi/conev.c
byedpi/desync.c
byedpi/extend.c
byedpi/packets.c
byedpi/proxy.c
byedpi/main.c
byedpi/mpool.c
native-lib.c
utils.c
)
file(GLOB BYE_DPI_SRC byedpi/*.c)
list(REMOVE_ITEM BYE_DPI_SRC ${CMAKE_CURRENT_SOURCE_DIR}/byedpi/win_service.c)
include_directories("byedpi")
add_library(byedpi SHARED ${BYE_DPI_SRC} native-lib.c utils.c)
target_include_directories(byedpi PRIVATE byedpi)
set(CMAKE_C_FLAGS "-std=c99 -O2 -D_XOPEN_SOURCE=500")
target_compile_options(byedpi PRIVATE -std=c99 -O2 -D_XOPEN_SOURCE=500)
target_compile_definitions(byedpi PRIVATE ANDROID_APP)
add_compile_definitions(ANDROID_APP)
# Specifies libraries CMake should link to your target library. You
# can link libraries from various origins, such as libraries defined in this
# build script, prebuilt third-party libraries, or Android system libraries.
target_link_libraries(${CMAKE_PROJECT_NAME}
# List libraries link to the target library
android
log
)
target_link_libraries(byedpi PRIVATE android log)

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

View File

@ -13,6 +13,11 @@ void clear_params(void);
char *ftob(const char *str, ssize_t *sl);
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);
int parse_offset(struct part *part, const char *str);

View File

@ -12,11 +12,18 @@
#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,
DESYNC_DISOOB,
};
enum hosts_mode {
HOSTS_DISABLE,
HOSTS_BLACKLIST,
HOSTS_WHITELIST,
};
JNIEXPORT jint JNI_OnLoad(
@ -75,14 +82,19 @@ 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,
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,
jboolean tfo,
jint udp_fake_count,
jboolean drop_sack,
jint fake_offset) {
struct sockaddr_ina s;
const char *address = (*env)->GetStringUTFChars(env, ip, 0);
@ -98,6 +110,7 @@ Java_io_github_dovecoteescapee_byedpi_core_ByeDpiProxy_jniCreateSocket(
params.max_open = max_connections;
params.bfsize = buffer_size;
params.resolve = !no_domain;
params.tfo = tfo;
if (custom_ttl) {
params.def_ttl = default_ttl;
@ -112,6 +125,29 @@ Java_io_github_dovecoteescapee_byedpi_core_ByeDpiProxy_jniCreateSocket(
}
}
if (hosts_mode == HOSTS_WHITELIST) {
struct desync_params *dp = add(
(void *) &params.dp,
&params.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 = 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) {
perror("parse_hosts");
clear_params();
return -1;
}
}
struct desync_params *dp = add(
(void *) &params.dp,
&params.dp_count,
@ -123,7 +159,21 @@ 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 = 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) {
perror("parse_hosts");
clear_params();
return -1;
}
}
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 |
@ -170,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);
@ -181,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

@ -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) {

View File

@ -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())

View File

@ -69,13 +69,19 @@ 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,
tlsRecordSplit = preferences.tlsRecordSplit,
tlsRecordSplitPosition = preferences.tlsRecordSplitPosition,
tlsRecordSplitAtSni = preferences.tlsRecordSplitAtSni,
hostsMode = preferences.hostsMode.ordinal,
hosts = preferences.hosts,
tcpFastOpen = preferences.tcpFastOpen,
udpFakeCount = preferences.udpFakeCount,
dropSack = preferences.dropSack,
fakeOffset = preferences.fakeOffset,
)
}
@ -97,13 +103,19 @@ class ByeDpiProxy {
splitAtHost: Boolean,
fakeTtl: Int,
fakeSni: String,
oobData: String,
oobChar: Byte,
hostMixedCase: Boolean,
domainMixedCase: Boolean,
hostRemoveSpaces: Boolean,
tlsRecordSplit: Boolean,
tlsRecordSplitPosition: Int,
tlsRecordSplitAtSni: Boolean,
hostsMode: Int,
hosts: String?,
tcpFastOpen: Boolean,
udpFakeCount: Int,
dropSack: Boolean,
fakeOffset: Int,
): Int
private external fun jniStartProxy(fd: Int): Int

View File

@ -48,13 +48,19 @@ 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,
tlsRecordSplit: Boolean? = null,
tlsRecordSplitPosition: Int? = null,
tlsRecordSplitAtSni: Boolean? = null,
hostsMode: HostsMode? = null,
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
@ -67,17 +73,27 @@ class ByeDpiProxyUIPreferences(
val desyncHttps: Boolean = desyncHttps ?: true
val desyncUdp: Boolean = desyncUdp ?: false
val desyncMethod: DesyncMethod = desyncMethod ?: DesyncMethod.Disorder
val splitPosition: Int = splitPosition ?: 3
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
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()
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),
@ -95,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),
@ -103,6 +119,19 @@ 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
}
},
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 {
@ -110,7 +139,8 @@ class ByeDpiProxyUIPreferences(
Split,
Disorder,
Fake,
OOB;
OOB,
DISOOB;
companion object {
fun fromName(name: String): DesyncMethod {
@ -120,9 +150,27 @@ class ByeDpiProxyUIPreferences(
"disorder" -> Disorder
"fake" -> Fake
"oob" -> OOB
"disoob" -> DISOOB
else -> throw IllegalArgumentException("Unknown desync method: $name")
}
}
}
}
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")
}
}
}
}
}

View File

@ -0,0 +1,17 @@
package io.github.dovecoteescapee.byedpi.core
object TProxyService {
init {
System.loadLibrary("hev-socks5-tunnel")
}
@JvmStatic
external fun TProxyStartService(configPath: String, fd: Int)
@JvmStatic
external fun TProxyStopService()
@JvmStatic
@Suppress("unused")
external fun TProxyGetStats(): LongArray
}

View File

@ -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<ListPreference>("byedpi_desync_method")
.value.let { ByeDpiProxyUIPreferences.DesyncMethod.fromName(it) }
val hostsMode = findPreferenceNotNull<ListPreference>("byedpi_hosts_mode")
.value.let { ByeDpiProxyUIPreferences.HostsMode.fromName(it) }
val hostsBlacklist = findPreferenceNotNull<EditTextPreference>("byedpi_hosts_blacklist")
val hostsWhitelist = findPreferenceNotNull<EditTextPreference>("byedpi_hosts_whitelist")
val desyncHttp = findPreferenceNotNull<CheckBoxPreference>("byedpi_desync_http")
val desyncHttps = findPreferenceNotNull<CheckBoxPreference>("byedpi_desync_https")
val desyncUdp = findPreferenceNotNull<CheckBoxPreference>("byedpi_desync_udp")
@ -73,7 +78,9 @@ 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")
val hostRemoveSpaces =
@ -83,64 +90,36 @@ class ByeDpiUISettingsFragment : PreferenceFragmentCompat() {
findPreferenceNotNull<EditTextPreference>("byedpi_tlsrec_position")
val splitTlsRecAtSni = findPreferenceNotNull<CheckBoxPreference>("byedpi_tlsrec_at_sni")
when (desyncMethod) {
None -> {
desyncHttp.isVisible = false
desyncHttps.isVisible = false
desyncUdp.isVisible = false
splitPosition.isVisible = false
splitAtHost.isVisible = false
ttlFake.isVisible = false
fakeSni.isVisible = false
oobData.isVisible = false
hostMixedCase.isVisible = false
domainMixedCase.isVisible = false
hostRemoveSpaces.isVisible = false
}
hostsBlacklist.isVisible = hostsMode == Blacklist
hostsWhitelist.isVisible = hostsMode == Whitelist
else -> {
desyncHttp.isVisible = true
desyncHttps.isVisible = true
desyncUdp.isVisible = true
splitPosition.isVisible = true
splitAtHost.isVisible = true
val desyncEnabled = desyncMethod != None
splitPosition.isVisible = desyncEnabled
splitAtHost.isVisible = desyncEnabled
val desyncAllProtocols =
!desyncHttp.isChecked && !desyncHttps.isChecked && !desyncUdp.isChecked
val isFake = desyncMethod == Fake
ttlFake.isVisible = isFake
fakeSni.isVisible = isFake
fakeOffset.isVisible = isFake
if (desyncAllProtocols || desyncHttp.isChecked) {
hostMixedCase.isVisible = true
domainMixedCase.isVisible = true
hostRemoveSpaces.isVisible = true
} else {
hostMixedCase.isVisible = false
domainMixedCase.isVisible = false
hostRemoveSpaces.isVisible = false
}
val isOob = desyncMethod == OOB || desyncMethod == DISOOB
oobChar.isVisible = isOob
when (desyncMethod) {
Fake -> {
ttlFake.isVisible = true
fakeSni.isVisible = true
oobData.isVisible = false
}
val desyncAllProtocols =
!desyncHttp.isChecked && !desyncHttps.isChecked && !desyncUdp.isChecked
OOB -> {
ttlFake.isVisible = false
fakeSni.isVisible = false
oobData.isVisible = true
}
val desyncHttpEnabled = desyncAllProtocols || desyncHttp.isChecked
hostMixedCase.isEnabled = desyncHttpEnabled
domainMixedCase.isEnabled = desyncHttpEnabled
hostRemoveSpaces.isEnabled = desyncHttpEnabled
else -> {
ttlFake.isVisible = false
fakeSni.isVisible = false
oobData.isVisible = false
}
}
}
}
val desyncUdpEnabled = desyncAllProtocols || desyncUdp.isChecked
udpFakeCount.isEnabled = desyncUdpEnabled
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

@ -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() || checkNotLocalIp(it)
}
findPreferenceNotNull<DropDownPreference>("app_theme")
.setOnPreferenceChangeListener { _, newValue ->
@ -83,10 +85,18 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
val mode = findPreferenceNotNull<ListPreference>("byedpi_mode")
.value.let { Mode.fromString(it) }
val dns = findPreferenceNotNull<EditTextPreference>("dns_ip")
val ipv6 = findPreferenceNotNull<SwitchPreference>("ipv6_enable")
when (mode) {
Mode.VPN -> dns.isVisible = true
Mode.Proxy -> dns.isVisible = false
Mode.VPN -> {
dns.isVisible = true
ipv6.isVisible = true
}
Mode.Proxy -> {
dns.isVisible = false
ipv6.isVisible = false
}
}
}
}

View File

@ -8,13 +8,11 @@ import android.os.Build
import android.os.ParcelFileDescriptor
import android.util.Log
import androidx.lifecycle.lifecycleScope
import engine.Engine
import engine.Key
import io.github.dovecoteescapee.byedpi.BuildConfig
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
@ -23,11 +21,12 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import java.io.File
class ByeDpiVpnService : LifecycleVpnService() {
private val proxy = ByeDpiProxy()
private val byeDpiProxy = ByeDpiProxy()
private var proxyJob: Job? = null
private var vpn: ParcelFileDescriptor? = null
private var tunFd: ParcelFileDescriptor? = null
private val mutex = Mutex()
private var stopping: Boolean = false
@ -138,7 +137,7 @@ class ByeDpiVpnService : LifecycleVpnService() {
val preferences = getByeDpiPreferences()
proxyJob = lifecycleScope.launch(Dispatchers.IO) {
val code = proxy.startProxy(preferences)
val code = byeDpiProxy.startProxy(preferences)
withContext(Dispatchers.Main) {
if (code != 0) {
@ -164,7 +163,7 @@ class ByeDpiVpnService : LifecycleVpnService() {
return
}
proxy.stopProxy()
byeDpiProxy.stopProxy()
proxyJob?.join() ?: throw IllegalStateException("ProxyJob field null")
proxyJob = null
@ -174,30 +173,58 @@ class ByeDpiVpnService : LifecycleVpnService() {
private fun startTun2Socks() {
Log.i(TAG, "Starting tun2socks")
if (vpn != null) {
if (tunFd != null) {
throw IllegalStateException("VPN field not null")
}
val sharedPreferences = getPreferences()
val port = sharedPreferences.getString("byedpi_proxy_port", null)?.toInt() ?: 1080
val dns = sharedPreferences.getStringNotNull("dns_ip", "1.1.1.1")
val ipv6 = sharedPreferences.getBoolean("ipv6_enable", false)
val vpn = createBuilder(dns).establish()
val tun2socksConfig = """
| misc:
| task-stack-size: 81920
| socks5:
| mtu: 8500
| address: 127.0.0.1
| port: $port
| udp: udp
""".trimMargin("| ")
val configPath = try {
File.createTempFile("config", "tmp", cacheDir).apply {
writeText(tun2socksConfig)
}
} catch (e: Exception) {
Log.e(TAG, "Failed to create config file", e)
throw e
}
val fd = createBuilder(dns, ipv6).establish()
?: throw IllegalStateException("VPN connection failed")
this.vpn = vpn
// val fd = vpn.detachFd()
Engine.insert(createKey(vpn.fd, port))
Engine.start()
this.tunFd = fd
TProxyService.TProxyStartService(configPath.absolutePath, fd.fd)
Log.i(TAG, "Tun2Socks started")
}
private fun stopTun2Socks() {
Log.i(TAG, "Stopping tun2socks")
// Engine.stop() // sometimes crashes with fdsan
vpn?.close() ?: Log.w(TAG, "VPN not running") // Is engine close sockets?
vpn = null
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
Log.i(TAG, "Tun2socks stopped")
}
@ -212,6 +239,7 @@ class ByeDpiVpnService : LifecycleVpnService() {
setStatus(
when (newStatus) {
ServiceStatus.Connected -> AppStatus.Running
ServiceStatus.Disconnected,
ServiceStatus.Failed -> {
proxyJob = null
@ -241,7 +269,8 @@ class ByeDpiVpnService : LifecycleVpnService() {
ByeDpiVpnService::class.java,
)
private fun createBuilder(dns: String): Builder {
private fun createBuilder(dns: String, ipv6: Boolean): Builder {
Log.d(TAG, "DNS: $dns")
val builder = Builder()
builder.setSession("ByeDPI")
builder.setConfigureIntent(
@ -254,30 +283,22 @@ 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)
.addRoute("0.0.0.0", 0)
if (ipv6) {
builder.addAddress("fd00::1", 128)
.addRoute("::", 0)
}
if (dns.isNotBlank()) {
builder.addDnsServer(dns)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
builder.setMetered(false)
}
builder.addDisallowedApplication("io.github.dovecoteescapee.byedpi")
builder.addDisallowedApplication(applicationContext.packageName)
return builder
}
private fun createKey(fd: Int, port: Int): Key = Key().apply {
mark = 0
mtu = 0
device = "fd://${fd}"
setInterface("")
logLevel = if (BuildConfig.DEBUG) "debug" else "info"
proxy = "socks5://127.0.0.1:$port"
restAPI = ""
tcpSendBufferSize = ""
tcpReceiveBufferSize = ""
tcpModerateReceiveBuffer = false
}
}

View File

@ -9,7 +9,7 @@ import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ServiceLifecycleDispatcher
/**
* Based on @link [androidx.lifecycle.LifecycleService]
* Based on [androidx.lifecycle.LifecycleService]
*/
open class LifecycleVpnService : VpnService(), LifecycleOwner {
@Suppress("LeakingThis")
@ -28,10 +28,10 @@ open class LifecycleVpnService : VpnService(), LifecycleOwner {
}
@Deprecated("Deprecated in Java")
@Suppress("DEPRECATION")
@CallSuper
override fun onStart(intent: Intent?, startId: Int) {
dispatcher.onServicePreSuperOnStart()
@Suppress("DEPRECATION")
super.onStart(intent, startId)
}

View File

@ -58,4 +58,4 @@ fun createConnectionNotification(
PendingIntent.FLAG_IMMUTABLE,
)
)
.build()
.build()

View File

@ -3,7 +3,6 @@ package io.github.dovecoteescapee.byedpi.utility
import android.net.InetAddresses
import android.os.Build
import android.util.Log
import android.util.Patterns
import android.widget.Toast
import androidx.preference.EditTextPreference
import androidx.preference.PreferenceFragmentCompat
@ -15,8 +14,21 @@ fun checkIp(ip: String): Boolean =
InetAddresses.isNumericAddress(ip)
} else {
// This pattern doesn't not support IPv6
@Suppress("DEPRECATION")
Patterns.IP_ADDRESS.matcher(ip).matches()
// @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
}
} else {
// This pattern doesn't not support IPv6
// @Suppress("DEPRECATION")
// Patterns.IP_ADDRESS.matcher(ip).matches()
true
}
fun PreferenceFragmentCompat.setEditTestPreferenceListenerPort(key: String) {

View File

@ -0,0 +1,16 @@
# Copyright (C) 2023 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
include $(call all-subdir-makefiles)

View File

@ -0,0 +1,21 @@
# Copyright (C) 2023 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
APP_OPTIM := release
APP_PLATFORM := android-21
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
APP_CFLAGS := -O3 -DPKGNAME=io/github/dovecoteescapee/byedpi/core
APP_CPPFLAGS := -O3 -std=c++11
NDK_TOOLCHAIN_VERSION := clang

@ -0,0 +1 @@
Subproject commit 677bb4530cfc867cd44d88d298960c8d8d9fbfad

Binary file not shown.

Before

Width:  |  Height:  |  Size: 820 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 486 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M14.74,16.866C17.473,15.885 17.893,13.832 17.869,12.884C17.835,11.487 16.792,10.113 16.751,9.354C16.714,8.676 16.967,8.174 18.106,8.338C18.002,8.039 17.763,7.536 17.479,7.178C17.112,6.714 16.629,6.356 15.858,6.357C14.554,6.359 14.124,7.537 13.826,8.296C13.528,9.056 13.837,9.36 13.026,10.509C13.149,11.895 13.097,11.909 12.882,12.771C12.362,14.851 10.511,17.307 9.567,18.641C8.623,19.975 7.843,20.663 8.685,21.329C9.526,21.997 9.927,21.032 10.234,20.477C10.542,19.923 10.871,19.205 11.014,19.246C11.158,19.287 11.199,19.153 10.819,20.303C10.44,21.452 10.532,21.955 11.353,22.017C12.174,22.078 12.328,21.575 12.389,20.713C12.451,19.852 12.564,19.379 12.677,19.379C12.79,19.379 12.821,19.236 12.903,20.323C12.985,21.411 13.016,22.15 14.063,21.781C15.109,21.412 14.791,20.816 14.535,20.242C14.278,19.667 14.207,19.092 14.319,19.041C14.432,18.99 14.566,19.257 14.976,19.893C15.387,20.529 15.613,21.289 16.485,20.704C17.697,19.89 16.043,18.477 15.304,17.543C13.991,18.015 13.324,18.015 13.313,17.543C13.303,17.071 13.875,17.176 14.74,16.866ZM16.057,7.078C16.282,7.078 16.465,7.261 16.465,7.486C16.465,7.71 16.282,7.893 16.057,7.893C15.833,7.893 15.65,7.71 15.65,7.486C15.65,7.261 15.833,7.078 16.057,7.078Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M12.323,10.724C12.328,12.132 12.098,13.609 10.721,15.484C9.624,15.608 8.689,15.672 8.468,15.227C8.209,14.706 8.769,14.613 9.399,14.153C9.399,14.153 10.449,13.531 10.239,13.298C10.029,13.064 8.995,13.788 8.497,13.974C7.999,14.161 7.027,14.632 6.506,13.71C6.272,13.298 6.568,13.088 7.478,12.901C8.388,12.715 8.932,12.458 8.777,12.256C8.621,12.054 7.206,12.566 6.086,12.575C4.966,12.582 4.616,12.085 4.616,11.68C4.616,11.276 4.966,11.338 5.946,11.276C6.926,11.214 7.552,11.307 7.532,10.926C7.517,10.623 6.101,10.856 5.246,10.724C4.39,10.592 3.13,10.359 3.13,9.448C3.13,9.06 3.355,8.943 4.047,9.168C4.74,9.394 6.606,9.728 6.606,9.308C6.606,8.888 4.18,9.121 2.849,7.877C1.519,6.633 2.391,5.972 2.655,5.972C3.06,5.972 3.375,6.62 5.548,7.317C6.59,7.651 9.2,7.899 9.958,8.266C10.908,8.725 12.323,10.724 12.323,10.724Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M15.828,5.51C16.435,4.323 16.575,4.112 16.837,3.281C17.099,2.449 17.249,1.729 17.696,1.762C18.302,1.806 18.524,2.519 18.273,3.392C17.982,4.402 17.146,5.458 16.94,5.776C16.605,5.468 15.828,5.51 15.828,5.51Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M17.31,5.903C18.106,5.041 18.208,4.344 18.605,4.337C19.001,4.33 19.22,4.813 19.142,5.238C19.065,5.664 18.542,6.428 18.194,6.796C17.774,6.357 17.536,6.085 17.31,5.903Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M18.47,7.222C18.552,7.004 19.051,6.733 19.283,6.946C19.573,7.212 19.602,8.025 19.036,8.586C18.852,7.943 18.61,7.396 18.47,7.222Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M18.378,11.31C18.712,11.059 19.35,10.323 19.239,9.844C19.128,9.366 19.046,9.308 18.378,9.22C17.71,9.133 17.497,9.061 17.531,9.298C17.566,9.535 18.363,11.121 18.378,11.31Z"
android:fillColor="#ffffff"/>
</vector>

View File

@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
tools:context=".activities.MainActivity">
<com.google.android.material.button.MaterialButton
@ -11,42 +12,30 @@
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:paddingLeft="10pt"
android:paddingTop="5pt"
android:paddingRight="10pt"
android:paddingBottom="5pt"
android:textAllCaps="false"
android:textSize="24sp"
app:layout_constraintBottom_toTopOf="@+id/status_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="@string/vpn_connect" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/status_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/proxy_address"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/status_button"
app:layout_constraintVertical_chainStyle="packed"
android:layout_below="@+id/status_button"
android:layout_marginTop="8dp"
android:layout_centerHorizontal="true"
tools:text="@string/vpn_disconnected" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/proxy_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/status_text"
app:layout_constraintVertical_chainStyle="packed"
android:layout_below="@+id/status_text"
android:layout_centerHorizontal="true"
tools:text="127.0.0.1:1080" />
</androidx.constraintlayout.widget.ConstraintLayout>
</RelativeLayout>

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,5 +34,17 @@
<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">
<item name="disable">Disable</item>
<item name="blacklist">Blacklist</item>
<item name="whitelist">Whitelist</item>
</array>
<array name="byedpi_hosts_modes_entries">
<item name="disable">disable</item>
<item name="blacklist">blacklist</item>
<item name="whitelist">whitelist</item>
</array>
</resources>

View File

@ -1,4 +1,5 @@
<resources>
<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>
@ -57,4 +58,18 @@
<string name="sni_of_fake_packet">SNI of fake packet</string>
<string name="byedpi_proxy">Proxy</string>
<string name="byedpi_desync">Desync</string>
</resources>
<string name="command_line_arguments">Command line arguments</string>
<string name="byedpi_hosts_mode_setting">Hosts</string>
<string name="byedpi_hosts_blacklist_setting">Hosts blacklist</string>
<string name="byedpi_hosts_whitelist_setting">Hosts whitelist</string>
<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

@ -1,24 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:tag="byedpi_cmd_settings">
<Preference
android:key="byedpi_readme"
android:title="Documentation"
android:textColor="?attr/textFillColor"
android:icon="@drawable/ic_github_36">
<intent
android:action="android.intent.action.VIEW"
android:data="https://github.com/hufrea/byedpi/tree/main#readme-ov-file" />
android:data="@string/byedpi_docs" />
</Preference>
<androidx.preference.PreferenceCategory>
<com.takisoft.preferencex.EditTextPreference
android:key="byedpi_cmd_args"
android:title="Command line arguments"
android:dialogTitle="Command line arguments"
android:inputType="textMultiLine" />
android:title="@string/command_line_arguments"
android:dialogTitle="@string/command_line_arguments"
android:inputType="textMultiLine"
app:useSimpleSummaryProvider="true" />
</androidx.preference.PreferenceCategory>

View File

@ -6,11 +6,10 @@
<Preference
android:key="byedpi_readme"
android:title="@string/byedpi_readme_link"
android:textColor="?attr/textFillColor"
android:icon="@drawable/ic_github_36">
<intent
android:action="android.intent.action.VIEW"
android:data="https://github.com/hufrea/byedpi/tree/main#readme-ov-file" />
android:data="@string/byedpi_docs" />
</Preference>
<androidx.preference.PreferenceCategory
@ -27,14 +26,14 @@
android:title="@string/byedpi_proxy_port_setting"
android:inputType="number"
android:defaultValue="1080"
app:useSimpleSummaryProvider="true"/>
app:useSimpleSummaryProvider="true" />
<com.takisoft.preferencex.EditTextPreference
android:key="byedpi_max_connections"
android:title="@string/byedpi_max_connections_setting"
android:inputType="number"
android:defaultValue="512"
app:useSimpleSummaryProvider="true"/>
app:useSimpleSummaryProvider="true" />
<com.takisoft.preferencex.EditTextPreference
android:key="byedpi_buffer_size"
@ -48,11 +47,38 @@
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
android:title="@string/byedpi_desync">
<DropDownPreference
android:key="byedpi_hosts_mode"
android:title="@string/byedpi_hosts_mode_setting"
android:entries="@array/byedpi_hosts_modes"
android:entryValues="@array/byedpi_hosts_modes_entries"
android:defaultValue="disable"
app:useSimpleSummaryProvider="true" />
<com.takisoft.preferencex.EditTextPreference
android:key="byedpi_hosts_blacklist"
android:title="@string/byedpi_hosts_blacklist_setting"
android:dialogTitle="@string/byedpi_hosts_blacklist_setting"
android:inputType="textMultiLine"
app:useSimpleSummaryProvider="true" />
<com.takisoft.preferencex.EditTextPreference
android:key="byedpi_hosts_whitelist"
android:title="@string/byedpi_hosts_whitelist_setting"
android:dialogTitle="@string/byedpi_hosts_whitelist_setting"
android:inputType="textMultiLine"
app:useSimpleSummaryProvider="true" />
<com.takisoft.preferencex.EditTextPreference
android:key="byedpi_default_ttl"
android:title="@string/byedpi_default_ttl_setting"
@ -68,6 +94,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"
@ -83,36 +158,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="3"
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" />
<androidx.preference.PreferenceCategory
android:title="@string/desync_http_category">
<CheckBoxPreference
android:key="byedpi_host_mixed_case"
@ -129,6 +178,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"
@ -148,4 +202,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

@ -27,7 +27,12 @@
android:key="dns_ip"
android:title="@string/dbs_ip_setting"
android:defaultValue="1.1.1.1"
app:useSimpleSummaryProvider="true"/>
app:useSimpleSummaryProvider="true" />
<SwitchPreference
android:key="ipv6_enable"
android:title="@string/ipv6_setting"
android:defaultValue="false" />
</androidx.preference.PreferenceCategory>

View File

@ -0,0 +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/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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -0,0 +1 @@
Bypass censorship on Android

View File

@ -0,0 +1 @@
<p><i>ByeDPI</i> запускает локальный VPN-сервис для обхода DPI (Deep Packet Inspection) и цензуры. Приложение локально запускает SOCKS5-прокси <a href='https://github.com/hufrea/byedpi' target='_blank' rel='nofollow noopener'>ByeDPI</a> и перенаправляет весь трафик через него.</p><p>Для обхода некоторых блокировок может потребоваться изменить настройки. Подробнее о различных настройках можно прочитать в <a href='https://github.com/hufrea/byedpi/blob/main/README.md' target='_blank' rel='nofollow noopener'>документации ByeDPI</a>.</p><p>Приложение использует VPN-режим на Android для перенаправления трафика, но не передает ничего на удаленный сервер. Оно не шифрует трафик и не скрывает ваш IP-адрес.</p>

View File

@ -0,0 +1 @@
Обход цензуры на Android