17 Commits

Author SHA1 Message Date
zarazaex69 45da2479dd fix(v2ray): remove unused VPN DNS server retrieval 2026-04-10 18:14:58 +03:00
zarazaex69 1c936b2b31 fix(v2ray): simplify DNS server configuration logic 2026-04-10 17:50:56 +03:00
zarazaex69 dbe109eedb chore(mmkv): update database files and checksums 2026-04-10 17:41:59 +03:00
zarazaex69 7705aded77 fix(settings): validate VPN DNS servers with IP address check 2026-04-10 17:28:56 +03:00
zarazaex69 4a2d62b671 feat(dns): improve VPN DNS configuration and filtering 2026-04-10 16:33:32 +03:00
zarazaex69 4acca4e554 chore: remove unused list file 2026-04-10 16:19:23 +03:00
zarazaex69 b875613fb3 chore(mmkv): update MMKV database files and checksums 2026-04-10 12:55:40 +03:00
zarazaex69 d9d21061fa chore(mmkv): update SETTING database files 2026-04-10 12:52:23 +03:00
zarazaex69 fc7804fc1e chore(mmkv): update SETTING database files 2026-04-10 12:46:03 +03:00
zarazaex69 4e9de615a4 chore(mmkv): update asset database files and remove unused ASSET store 2026-04-10 12:43:38 +03:00
zarazaex69 7617ce898c chore: remove KEY subscription setup script 2026-04-10 12:41:09 +03:00
zarazaex69 8d284fd68a feat(subscription): add KEY subscription s 2026-04-10 11:49:49 +03:00
zarazaex69 0f28310801 refactor(config): deduplicate profiles during batch save operation 2026-04-10 11:27:30 +03:00
zarazaex69 a46123aeab chore(build): update APK binary with latest changes 2026-04-10 11:24:55 +03:00
zarazaex69 06579df2a4 feat(dns): add QUIC support and upgrade to DoH DNS servers 2026-04-10 11:07:20 +03:00
zarazaex69 56532f10d3 chore: add list of НИЩИЕ 2026-04-10 10:59:36 +03:00
zarazaex69 e843b92ef2 chore(build): update APK binary with latest changes 2026-04-09 12:28:34 +03:00
21 changed files with 62 additions and 41 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -30,7 +30,8 @@
"enabled": true,
"destOverride": [
"http",
"tls"
"tls",
"quic"
]
}
}
@@ -30,7 +30,8 @@
"enabled": true,
"destOverride": [
"http",
"tls"
"tls",
"quic"
]
}
},
@@ -47,7 +48,8 @@
"enabled": true,
"destOverride": [
"http",
"tls"
"tls",
"quic"
]
}
}
@@ -123,8 +123,7 @@ object AppConfig {
// const val IP_API_URL = "https://speed.cloudflare.com/meta"
const val IP_API_URL = "https://api.ip.sb/geoip"
/** DNS server addresses. */
const val DNS_PROXY = "1.1.1.1"
const val DNS_PROXY = "https://1.1.1.1/dns-query"
const val DNS_DIRECT = "223.5.5.5"
const val DNS_VPN = "1.1.1.1"
const val GEOSITE_PRIVATE = "geosite:private"
@@ -273,26 +273,35 @@ object AngConfigManager {
private fun batchSaveConfigs(configs: List<ProfileItem>, subid: String): Map<String, ProfileItem> {
val keyToProfile = mutableMapOf<String, ProfileItem>()
// Read serverList once
val serverList = MmkvManager.decodeServerList(subid)
var needSetSelected = MmkvManager.getSelectServer().isNullOrBlank()
configs.forEach { config ->
val key = Utils.getUuid()
// Save profile directly without updating serverList
MmkvManager.encodeProfileDirect(key, JsonUtil.toJson(config))
val existingProfiles = serverList.mapNotNull { guid ->
MmkvManager.decodeServerConfig(guid)?.let { guid to it }
}.toMap()
if (!serverList.contains(key)) {
serverList.add(0, key)
if (needSetSelected) {
MmkvManager.setSelectServer(key)
needSetSelected = false
configs.forEach { config ->
val existingKey = existingProfiles.entries.firstOrNull { (_, existing) ->
existing == config
}?.key
if (existingKey != null) {
keyToProfile[existingKey] = config
} else {
val key = Utils.getUuid()
MmkvManager.encodeProfileDirect(key, JsonUtil.toJson(config))
if (!serverList.contains(key)) {
serverList.add(0, key)
if (needSetSelected) {
MmkvManager.setSelectServer(key)
needSetSelected = false
}
}
keyToProfile[key] = config
}
keyToProfile[key] = config
}
// Write serverList once
MmkvManager.encodeServerList(serverList, subid)
return keyToProfile
}
@@ -346,7 +346,7 @@ object SettingsManager {
*/
fun getVpnDnsServers(): List<String> {
val vpnDns = MmkvManager.decodeSettingsString(AppConfig.PREF_VPN_DNS) ?: AppConfig.DNS_VPN
return vpnDns.split(",").filter { Utils.isPureIpAddress(it) }
return vpnDns.split(",").filter { it.isNotBlank() && Utils.isPureIpAddress(it) }
}
/**
@@ -438,7 +438,6 @@ object SettingsManager {
* Ensure default settings are present in MMKV.
*/
private fun ensureDefaultSettings() {
// Write defaults in the exact order requested by the user
ensureDefaultValue(AppConfig.PREF_MODE, AppConfig.VPN)
ensureDefaultValue(AppConfig.PREF_VPN_DNS, AppConfig.DNS_VPN)
ensureDefaultValue(AppConfig.PREF_VPN_MTU, AppConfig.VPN_MTU.toString())
@@ -453,6 +452,9 @@ object SettingsManager {
ensureDefaultValue(AppConfig.PREF_MUX_XUDP_CONCURRENCY, "8")
ensureDefaultValue(AppConfig.PREF_FRAGMENT_LENGTH, "50-100")
ensureDefaultValue(AppConfig.PREF_FRAGMENT_INTERVAL, "10-20")
ensureDefaultBoolValue(AppConfig.PREF_LOCAL_DNS_ENABLED, true)
ensureDefaultBoolValue(AppConfig.PREF_FAKE_DNS_ENABLED, true)
}
private fun ensureDefaultValue(key: String, default: String) {
@@ -461,6 +463,12 @@ object SettingsManager {
}
}
private fun ensureDefaultBoolValue(key: String, default: Boolean) {
if (MmkvManager.decodeSettingsBool(key) == null) {
MmkvManager.encodeSettings(key, default)
}
}
private fun migrateAutoSort() {
val migrationKey = "auto_sort_migrated_v2"
if (MmkvManager.decodeSettingsBool(migrationKey, false)) {
@@ -592,12 +592,13 @@ object V2rayConfigManager {
val hosts = mutableMapOf<String, Any>()
val servers = ArrayList<Any>()
//remote Dns
val remoteDns = SettingsManager.getRemoteDnsServers()
val domesticDns = SettingsManager.getDomesticDnsServers()
val proxyDomain = getUserRule2Domain(AppConfig.TAG_PROXY)
remoteDns.forEach {
servers.add(it)
}
val directDomain = getUserRule2Domain(AppConfig.TAG_DIRECT)
val isCnRoutingMode = directDomain.contains(AppConfig.GEOSITE_CN)
val geoipCn = arrayListOf(AppConfig.GEOIP_CN)
if (proxyDomain.isNotEmpty()) {
servers.add(
V2rayConfig.DnsBean.ServersBean(
@@ -607,11 +608,6 @@ object V2rayConfigManager {
)
}
// domestic DNS
val domesticDns = SettingsManager.getDomesticDnsServers()
val directDomain = getUserRule2Domain(AppConfig.TAG_DIRECT)
val isCnRoutingMode = directDomain.contains(AppConfig.GEOSITE_CN)
val geoipCn = arrayListOf(AppConfig.GEOIP_CN)
if (directDomain.isNotEmpty()) {
servers.add(
V2rayConfig.DnsBean.ServersBean(
@@ -624,16 +620,17 @@ object V2rayConfigManager {
)
}
//block dns
remoteDns.forEach {
servers.add(it)
}
val blkDomain = getUserRule2Domain(AppConfig.TAG_BLOCKED)
if (blkDomain.isNotEmpty()) {
hosts.putAll(blkDomain.map { it to AppConfig.LOOPBACK })
}
// hardcode googleapi rule to fix play store problems
hosts[AppConfig.GOOGLEAPIS_CN_DOMAIN] = AppConfig.GOOGLEAPIS_COM_DOMAIN
// hardcode popular Android Private DNS rule to fix localhost DNS problem
hosts[AppConfig.DNS_ALIDNS_DOMAIN] = AppConfig.DNS_ALIDNS_ADDRESSES
hosts[AppConfig.DNS_CLOUDFLARE_ONE_DOMAIN] = AppConfig.DNS_CLOUDFLARE_ONE_ADDRESSES
hosts[AppConfig.DNS_CLOUDFLARE_DNS_COM_DOMAIN] = AppConfig.DNS_CLOUDFLARE_DNS_COM_ADDRESSES
@@ -643,7 +640,6 @@ object V2rayConfigManager {
hosts[AppConfig.DNS_QUAD9_DOMAIN] = AppConfig.DNS_QUAD9_ADDRESSES
hosts[AppConfig.DNS_YANDEX_DOMAIN] = AppConfig.DNS_YANDEX_ADDRESSES
//User DNS hosts
try {
val userHosts = MmkvManager.decodeSettingsString(AppConfig.PREF_DNS_HOSTS)
if (userHosts.isNotNullEmpty()) {
@@ -657,14 +653,12 @@ object V2rayConfigManager {
Log.e(AppConfig.TAG, "Failed to configure user DNS hosts", e)
}
// DNS dns
v2rayConfig.dns = V2rayConfig.DnsBean(
servers = servers,
hosts = hosts,
tag = AppConfig.TAG_DNS
)
// DNS routing
v2rayConfig.routing.rules.add(
RulesBean(
outboundTag = AppConfig.TAG_DIRECT,
@@ -228,13 +228,13 @@ class V2RayVpnService : VpnService(), ServiceControl {
}
}
// Configure DNS servers
//if (MmkvManager.decodeSettingsBool(AppConfig.PREF_LOCAL_DNS_ENABLED) == true) {
// builder.addDnsServer(PRIVATE_VLAN4_ROUTER)
//} else {
SettingsManager.getVpnDnsServers().forEach {
if (Utils.isPureIpAddress(it)) {
builder.addDnsServer(it)
if (MmkvManager.decodeSettingsBool(AppConfig.PREF_LOCAL_DNS_ENABLED) == true) {
builder.addDnsServer(vpnConfig.ipv4Router)
} else {
SettingsManager.getVpnDnsServers().forEach {
if (Utils.isPureIpAddress(it)) {
builder.addDnsServer(it)
}
}
}
BIN
View File
Binary file not shown.
+8
View File
@@ -136,9 +136,17 @@ fun main() {
)
println("Добавлена подписка БЕЛЫЕ W: $guid2")
val guid3 = manager.addSubscription(
remarks = "KEY",
url = "https://key.zarazaex.xyz/sub",
autoUpdate = true
)
println("Добавлена подписка KEY: $guid3")
println("\nОбновление подписок...")
manager.updateSubscription(guid1, "https://raw.githubusercontent.com/zieng2/wl/refs/heads/main/vless_universal.txt")
manager.updateSubscription(guid2, "https://raw.githubusercontent.com/whoahaow/rjsxrd/refs/heads/main/githubmirror/bypass/bypass-all.txt")
manager.updateSubscription(guid3, "https://key.zarazaex.xyz/sub")
println("\nПодписки успешно добавлены и обновлены в $mmkvPath")
}