Merge branch '2dust:master' into master

This commit is contained in:
Το μοχθηρό ^_^ authored and GitHub committed 2024-02-16 00:54:06 +08:00
commit ce3dd73a81
13 files changed
+347 -114

No files matched your search

@@ -44,9 +44,14 @@ object AppConfig {
const val PREF_MUX_CONCURRENCY = "pref_mux_concurency"
const val PREF_MUX_XUDP_CONCURRENCY = "pref_mux_xudp_concurency"
const val PREF_MUX_XUDP_QUIC = "pref_mux_xudp_quic"
const val PREF_FRAGMENT_ENABLED = "pref_fragment_enabled"
const val PREF_FRAGMENT_PACKETS = "pref_fragment_packets"
const val PREF_FRAGMENT_LENGTH = "pref_fragment_length"
const val PREF_FRAGMENT_INTERVAL = "pref_fragment_interval"
const val HTTP_PROTOCOL: String = "http://"
const val HTTPS_PROTOCOL: String = "https://"
const val PROTOCOL_HTTP: String = "http://"
const val PROTOCOL_HTTPS: String = "https://"
const val PROTOCOL_FREEDOM: String = "freedom"
const val BROADCAST_ACTION_SERVICE = "com.v2ray.ang.action.service"
const val BROADCAST_ACTION_ACTIVITY = "com.v2ray.ang.action.activity"
@@ -61,6 +66,7 @@ object AppConfig {
const val TAG_AGENT = "proxy"
const val TAG_DIRECT = "direct"
const val TAG_BLOCKED = "block"
const val TAG_FRAGMENT = "fragment"
const val androidpackagenamelistUrl =
"https://raw.githubusercontent.com/2dust/androidpackagenamelist/master/proxy.txt"
@@ -61,13 +61,13 @@ data class V2rayConfig(
val metadataOnly: Boolean? = null)
}
data class OutboundBean(val tag: String = "proxy",
data class OutboundBean(var tag: String = "proxy",
var protocol: String,
var settings: OutSettingsBean? = null,
var streamSettings: StreamSettingsBean? = null,
val proxySettings: Any? = null,
val sendThrough: String? = null,
val mux: MuxBean? = MuxBean(false)) {
var mux: MuxBean? = MuxBean(false)) {
data class OutSettingsBean(var vnext: List<VnextBean>? = null,
var fragment: FragmentBean? = null,
@@ -141,7 +141,7 @@ data class V2rayConfig(
var realitySettings: TlsSettingsBean? = null,
var grpcSettings: GrpcSettingsBean? = null,
val dsSettings: Any? = null,
val sockopt: SockoptBean? = null
var sockopt: SockoptBean? = null
) {
data class TcpSettingsBean(var header: HeaderBean = HeaderBean(),
@@ -41,6 +41,10 @@ class SettingsActivity : BaseActivity() {
private val muxXudpConcurrency by lazy { findPreference<EditTextPreference>(AppConfig.PREF_MUX_XUDP_CONCURRENCY) }
private val muxXudpQuic by lazy { findPreference<ListPreference>(AppConfig.PREF_MUX_XUDP_QUIC) }
private val fragment by lazy { findPreference<CheckBoxPreference>(AppConfig.PREF_FRAGMENT_ENABLED) }
private val fragmentPackets by lazy { findPreference<ListPreference>(AppConfig.PREF_FRAGMENT_PACKETS) }
private val fragmentLength by lazy { findPreference<EditTextPreference>(AppConfig.PREF_FRAGMENT_LENGTH) }
private val fragmentInterval by lazy { findPreference<EditTextPreference>(AppConfig.PREF_FRAGMENT_INTERVAL) }
// val autoRestart by lazy { findPreference(PREF_AUTO_RESTART) as CheckBoxPreference }
private val remoteDns by lazy { findPreference<EditTextPreference>(AppConfig.PREF_REMOTE_DNS) }
@@ -168,6 +172,23 @@ class SettingsActivity : BaseActivity() {
updateMuxXudpConcurrency(newValue as String)
true
}
fragment?.setOnPreferenceChangeListener { _, newValue ->
updateFragment(newValue as Boolean)
true
}
fragmentPackets?.setOnPreferenceChangeListener { _, newValue ->
updateFragmentPackets(newValue as String)
true
}
fragmentLength?.setOnPreferenceChangeListener { _, newValue ->
updateFragmentLength(newValue as String)
true
}
fragmentInterval?.setOnPreferenceChangeListener { _, newValue ->
updateFragmentInterval(newValue as String)
true
}
}
override fun onStart() {
@@ -184,6 +205,10 @@ class SettingsActivity : BaseActivity() {
updateMux(defaultSharedPreferences.getBoolean(AppConfig.PREF_MUX_ENABLED, false))
muxConcurrency?.summary = defaultSharedPreferences.getString(AppConfig.PREF_MUX_CONCURRENCY, "8")
muxXudpConcurrency?.summary = defaultSharedPreferences.getString(AppConfig.PREF_MUX_XUDP_CONCURRENCY, "8")
updateFragment(defaultSharedPreferences.getBoolean(AppConfig.PREF_FRAGMENT_ENABLED, false))
fragmentPackets?.summary = defaultSharedPreferences.getString(AppConfig.PREF_FRAGMENT_PACKETS, "tlshello")
fragmentLength?.summary = defaultSharedPreferences.getString(AppConfig.PREF_FRAGMENT_LENGTH, "50-100")
fragmentInterval?.summary = defaultSharedPreferences.getString(AppConfig.PREF_FRAGMENT_INTERVAL, "10-20")
autoUpdateInterval?.summary = defaultSharedPreferences.getString(AppConfig.SUBSCRIPTION_AUTO_UPDATE_INTERVAL,AppConfig.SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL)
autoUpdateInterval?.isEnabled = defaultSharedPreferences.getBoolean(AppConfig.SUBSCRIPTION_AUTO_UPDATE, false)
@@ -261,9 +286,9 @@ class SettingsActivity : BaseActivity() {
private fun updateMux(enabled: Boolean) {
val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity())
muxConcurrency?.isEnabled = enabled
muxXudpConcurrency?.isEnabled = enabled
muxXudpQuic?.isEnabled = enabled
muxConcurrency?.isVisible = enabled
muxXudpConcurrency?.isVisible = enabled
muxXudpQuic?.isVisible = enabled
if (enabled) {
updateMuxConcurrency(defaultSharedPreferences.getString(AppConfig.PREF_MUX_CONCURRENCY, "8"))
updateMuxXudpConcurrency(defaultSharedPreferences.getString(AppConfig.PREF_MUX_XUDP_CONCURRENCY, "8"))
@@ -287,6 +312,27 @@ class SettingsActivity : BaseActivity() {
muxXudpQuic?.isEnabled = concurrency >= 0
}
}
private fun updateFragment(enabled: Boolean) {
val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity())
fragmentPackets?.isVisible = enabled
fragmentLength?.isVisible = enabled
fragmentInterval?.isVisible = enabled
if (enabled) {
updateFragmentPackets(defaultSharedPreferences.getString(AppConfig.PREF_FRAGMENT_PACKETS, "tlshello"))
updateFragmentLength(defaultSharedPreferences.getString(AppConfig.PREF_FRAGMENT_LENGTH, "50-100"))
updateFragmentInterval(defaultSharedPreferences.getString(AppConfig.PREF_FRAGMENT_INTERVAL, "10-20"))
}
}
private fun updateFragmentPackets(value: String?) {
fragmentPackets?.summary = value.toString()
}
private fun updateFragmentLength(value: String?) {
fragmentLength?.summary = value.toString()
}
private fun updateFragmentInterval(value: String?) {
fragmentInterval?.summary = value.toString()
}
}
fun onModeHelpClicked(view: View) {
@@ -25,8 +25,8 @@ class UrlSchemeActivity : BaseActivity() {
if ("text/plain" == type) {
intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
val uri = Uri.parse(it)
if (uri.scheme?.startsWith(AppConfig.HTTPS_PROTOCOL) == true || uri.scheme?.startsWith(
AppConfig.HTTP_PROTOCOL
if (uri.scheme?.startsWith(AppConfig.PROTOCOL_HTTPS) == true || uri.scheme?.startsWith(
AppConfig.PROTOCOL_HTTP
) == true
) {
val name = uri.getQueryParameter("name") ?: "Subscription"
@@ -11,8 +11,8 @@ import com.google.gson.GsonBuilder
import com.tencent.mmkv.MMKV
import com.v2ray.ang.AppConfig
import com.v2ray.ang.AppConfig.ANG_CONFIG
import com.v2ray.ang.AppConfig.HTTPS_PROTOCOL
import com.v2ray.ang.AppConfig.HTTP_PROTOCOL
import com.v2ray.ang.AppConfig.PROTOCOL_HTTPS
import com.v2ray.ang.AppConfig.PROTOCOL_HTTP
import com.v2ray.ang.AppConfig.WIREGUARD_LOCAL_ADDRESS_V4
import com.v2ray.ang.AppConfig.WIREGUARD_LOCAL_MTU
import com.v2ray.ang.R
@@ -24,7 +24,6 @@ import java.net.URI
import java.util.*
import com.v2ray.ang.extension.idnHost
import com.v2ray.ang.extension.removeWhiteSpace
import com.v2ray.ang.extension.toast
object AngConfigManager {
private val mainStorage by lazy {
@@ -216,8 +215,8 @@ object AngConfigManager {
}
//maybe sub
if (TextUtils.isEmpty(subid) && (str.startsWith(HTTP_PROTOCOL) || str.startsWith(
HTTPS_PROTOCOL
if (TextUtils.isEmpty(subid) && (str.startsWith(PROTOCOL_HTTP) || str.startsWith(
PROTOCOL_HTTPS
))
) {
MmkvManager.importUrlAsSubscription(str)
@@ -2,11 +2,12 @@ package com.v2ray.ang.util
import android.content.Context
import android.text.TextUtils
import android.util.Log
import com.google.gson.*
import com.tencent.mmkv.MMKV
import com.v2ray.ang.AppConfig
import com.v2ray.ang.AppConfig.ANG_PACKAGE
import com.v2ray.ang.AppConfig.PROTOCOL_FREEDOM
import com.v2ray.ang.AppConfig.TAG_DIRECT
import com.v2ray.ang.AppConfig.TAG_FRAGMENT
import com.v2ray.ang.AppConfig.WIREGUARD_LOCAL_ADDRESS_V4
import com.v2ray.ang.AppConfig.WIREGUARD_LOCAL_ADDRESS_V6
import com.v2ray.ang.dto.V2rayConfig
@@ -16,8 +17,18 @@ import com.v2ray.ang.dto.V2rayConfig.Companion.DEFAULT_NETWORK
import com.v2ray.ang.dto.V2rayConfig.Companion.HTTP
object V2rayConfigUtil {
private val serverRawStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SERVER_RAW, MMKV.MULTI_PROCESS_MODE) }
private val settingsStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SETTING, MMKV.MULTI_PROCESS_MODE) }
private val serverRawStorage by lazy {
MMKV.mmkvWithID(
MmkvManager.ID_SERVER_RAW,
MMKV.MULTI_PROCESS_MODE
)
}
private val settingsStorage by lazy {
MMKV.mmkvWithID(
MmkvManager.ID_SETTING,
MMKV.MULTI_PROCESS_MODE
)
}
data class Result(var status: Boolean, var content: String)
@@ -50,7 +61,10 @@ object V2rayConfigUtil {
/**
* 生成v2ray的客户端配置文件
*/
private fun getV2rayNonCustomConfig(context: Context, outbound: V2rayConfig.OutboundBean): Result {
private fun getV2rayNonCustomConfig(
context: Context,
outbound: V2rayConfig.OutboundBean
): Result {
val result = Result(false, "")
//取得默认配置
val assets = Utils.readTextFromAssets(context, "v2ray_config.json")
@@ -62,14 +76,15 @@ object V2rayConfigUtil {
val v2rayConfig = Gson().fromJson(assets, V2rayConfig::class.java) ?: return result
v2rayConfig.log.loglevel = settingsStorage?.decodeString(AppConfig.PREF_LOGLEVEL)
?: "warning"
?: "warning"
inbounds(v2rayConfig)
updateOutboundWithGlobalSettings(outbound)
v2rayConfig.outbounds[0] = outbound
updateOutboundFragment(v2rayConfig)
routing(v2rayConfig)
fakedns(v2rayConfig)
@@ -93,8 +108,14 @@ object V2rayConfigUtil {
*/
private fun inbounds(v2rayConfig: V2rayConfig): Boolean {
try {
val socksPort = Utils.parseInt(settingsStorage?.decodeString(AppConfig.PREF_SOCKS_PORT), AppConfig.PORT_SOCKS.toInt())
val httpPort = Utils.parseInt(settingsStorage?.decodeString(AppConfig.PREF_HTTP_PORT), AppConfig.PORT_HTTP.toInt())
val socksPort = Utils.parseInt(
settingsStorage?.decodeString(AppConfig.PREF_SOCKS_PORT),
AppConfig.PORT_SOCKS.toInt()
)
val httpPort = Utils.parseInt(
settingsStorage?.decodeString(AppConfig.PREF_HTTP_PORT),
AppConfig.PORT_HTTP.toInt()
)
v2rayConfig.inbounds.forEach { curInbound ->
if (settingsStorage?.decodeBool(AppConfig.PREF_PROXY_SHARING) != true) {
@@ -104,8 +125,9 @@ object V2rayConfigUtil {
}
v2rayConfig.inbounds[0].port = socksPort
val fakedns = settingsStorage?.decodeBool(AppConfig.PREF_FAKE_DNS_ENABLED)
?: false
val sniffAllTlsAndHttp = settingsStorage?.decodeBool(AppConfig.PREF_SNIFFING_ENABLED, true)
?: false
val sniffAllTlsAndHttp =
settingsStorage?.decodeBool(AppConfig.PREF_SNIFFING_ENABLED, true)
?: true
v2rayConfig.inbounds[0].sniffing?.enabled = fakedns || sniffAllTlsAndHttp
if (!sniffAllTlsAndHttp) {
@@ -131,9 +153,10 @@ object V2rayConfigUtil {
}
private fun fakedns(v2rayConfig: V2rayConfig) {
if (settingsStorage?.decodeBool(AppConfig.PREF_FAKE_DNS_ENABLED) == true) {
if (settingsStorage?.decodeBool(AppConfig.PREF_LOCAL_DNS_ENABLED) == true
|| settingsStorage?.decodeBool(AppConfig.PREF_FAKE_DNS_ENABLED) == true) {
v2rayConfig.fakedns = listOf(V2rayConfig.FakednsBean())
v2rayConfig.outbounds.filter { it.protocol == "freedom" }.forEach {
v2rayConfig.outbounds.filter { it.protocol == PROTOCOL_FREEDOM && it.tag == TAG_DIRECT }.forEach {
it.settings?.domainStrategy = "UseIP"
}
}
@@ -144,38 +167,49 @@ object V2rayConfigUtil {
*/
private fun routing(v2rayConfig: V2rayConfig): Boolean {
try {
routingUserRule(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_AGENT)
?: "", AppConfig.TAG_AGENT, v2rayConfig)
routingUserRule(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_DIRECT)
?: "", AppConfig.TAG_DIRECT, v2rayConfig)
routingUserRule(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_BLOCKED)
?: "", AppConfig.TAG_BLOCKED, v2rayConfig)
routingUserRule(
settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_AGENT)
?: "", AppConfig.TAG_AGENT, v2rayConfig
)
routingUserRule(
settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_DIRECT)
?: "", AppConfig.TAG_DIRECT, v2rayConfig
)
routingUserRule(
settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_BLOCKED)
?: "", AppConfig.TAG_BLOCKED, v2rayConfig
)
v2rayConfig.routing.domainStrategy = settingsStorage?.decodeString(AppConfig.PREF_ROUTING_DOMAIN_STRATEGY)
v2rayConfig.routing.domainStrategy =
settingsStorage?.decodeString(AppConfig.PREF_ROUTING_DOMAIN_STRATEGY)
?: "IPIfNonMatch"
// v2rayConfig.routing.domainMatcher = "mph"
val routingMode = settingsStorage?.decodeString(AppConfig.PREF_ROUTING_MODE) ?: ERoutingMode.GLOBAL_PROXY.value
val routingMode = settingsStorage?.decodeString(AppConfig.PREF_ROUTING_MODE)
?: ERoutingMode.GLOBAL_PROXY.value
// Hardcode googleapis.cn
val googleapisRoute = V2rayConfig.RoutingBean.RulesBean(
type = "field",
outboundTag = AppConfig.TAG_AGENT,
domain = arrayListOf("domain:googleapis.cn")
type = "field",
outboundTag = AppConfig.TAG_AGENT,
domain = arrayListOf("domain:googleapis.cn")
)
when (routingMode) {
ERoutingMode.BYPASS_LAN.value -> {
routingGeo("ip", "private", AppConfig.TAG_DIRECT, v2rayConfig)
}
ERoutingMode.BYPASS_MAINLAND.value -> {
routingGeo("", "cn", AppConfig.TAG_DIRECT, v2rayConfig)
v2rayConfig.routing.rules.add(0, googleapisRoute)
}
ERoutingMode.BYPASS_LAN_MAINLAND.value -> {
routingGeo("ip", "private", AppConfig.TAG_DIRECT, v2rayConfig)
routingGeo("", "cn", AppConfig.TAG_DIRECT, v2rayConfig)
v2rayConfig.routing.rules.add(0, googleapisRoute)
}
ERoutingMode.GLOBAL_DIRECT.value -> {
val globalDirect = V2rayConfig.RoutingBean.RulesBean(
type = "field",
@@ -192,7 +226,12 @@ object V2rayConfigUtil {
return true
}
private fun routingGeo(ipOrDomain: String, code: String, tag: String, v2rayConfig: V2rayConfig) {
private fun routingGeo(
ipOrDomain: String,
code: String,
tag: String,
v2rayConfig: V2rayConfig
) {
try {
if (!TextUtils.isEmpty(code)) {
//IP
@@ -277,51 +316,70 @@ object V2rayConfigUtil {
try {
if (settingsStorage?.decodeBool(AppConfig.PREF_FAKE_DNS_ENABLED) == true) {
val geositeCn = arrayListOf("geosite:cn")
val proxyDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_AGENT)
?: "")
val directDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_DIRECT)
?: "")
val proxyDomain = userRule2Domian(
settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_AGENT)
?: ""
)
val directDomain = userRule2Domian(
settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_DIRECT)
?: ""
)
// fakedns with all domains to make it always top priority
v2rayConfig.dns.servers?.add(0,
V2rayConfig.DnsBean.ServersBean(address = "fakedns", domains = geositeCn.plus(proxyDomain).plus(directDomain)))
v2rayConfig.dns.servers?.add(
0,
V2rayConfig.DnsBean.ServersBean(
address = "fakedns",
domains = geositeCn.plus(proxyDomain).plus(directDomain)
)
)
}
// DNS inbound对象
val remoteDns = Utils.getRemoteDnsServers()
if (v2rayConfig.inbounds.none { e -> e.protocol == "dokodemo-door" && e.tag == "dns-in" }) {
val dnsInboundSettings = V2rayConfig.InboundBean.InSettingsBean(
address = if (Utils.isPureIpAddress(remoteDns.first())) remoteDns.first() else "1.1.1.1",
port = 53,
network = "tcp,udp")
address = if (Utils.isPureIpAddress(remoteDns.first())) remoteDns.first() else "1.1.1.1",
port = 53,
network = "tcp,udp"
)
val localDnsPort = Utils.parseInt(settingsStorage?.decodeString(AppConfig.PREF_LOCAL_DNS_PORT), AppConfig.PORT_LOCAL_DNS.toInt())
val localDnsPort = Utils.parseInt(
settingsStorage?.decodeString(AppConfig.PREF_LOCAL_DNS_PORT),
AppConfig.PORT_LOCAL_DNS.toInt()
)
v2rayConfig.inbounds.add(
V2rayConfig.InboundBean(
tag = "dns-in",
port = localDnsPort,
listen = "127.0.0.1",
protocol = "dokodemo-door",
settings = dnsInboundSettings,
sniffing = null))
V2rayConfig.InboundBean(
tag = "dns-in",
port = localDnsPort,
listen = "127.0.0.1",
protocol = "dokodemo-door",
settings = dnsInboundSettings,
sniffing = null
)
)
}
// DNS outbound对象
if (v2rayConfig.outbounds.none { e -> e.protocol == "dns" && e.tag == "dns-out" }) {
v2rayConfig.outbounds.add(
V2rayConfig.OutboundBean(
protocol = "dns",
tag = "dns-out",
settings = null,
streamSettings = null,
mux = null))
V2rayConfig.OutboundBean(
protocol = "dns",
tag = "dns-out",
settings = null,
streamSettings = null,
mux = null
)
)
}
// DNS routing tag
v2rayConfig.routing.rules.add(0, V2rayConfig.RoutingBean.RulesBean(
v2rayConfig.routing.rules.add(
0, V2rayConfig.RoutingBean.RulesBean(
type = "field",
inboundTag = arrayListOf("dns-in"),
outboundTag = "dns-out",
domain = null)
domain = null
)
)
} catch (e: Exception) {
e.printStackTrace()
@@ -335,43 +393,73 @@ object V2rayConfigUtil {
val hosts = mutableMapOf<String, String>()
val servers = ArrayList<Any>()
val remoteDns = Utils.getRemoteDnsServers()
val proxyDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_AGENT)
?: "")
val proxyDomain = userRule2Domian(
settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_AGENT)
?: ""
)
remoteDns.forEach {
servers.add(it)
}
if (proxyDomain.size > 0) {
servers.add(V2rayConfig.DnsBean.ServersBean(remoteDns.first(), 53, proxyDomain, null))
servers.add(
V2rayConfig.DnsBean.ServersBean(
remoteDns.first(),
53,
proxyDomain,
null
)
)
}
// domestic DNS
val directDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_DIRECT)
?: "")
val routingMode = settingsStorage?.decodeString(AppConfig.PREF_ROUTING_MODE) ?: ERoutingMode.GLOBAL_PROXY.value
val directDomain = userRule2Domian(
settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_DIRECT)
?: ""
)
val routingMode = settingsStorage?.decodeString(AppConfig.PREF_ROUTING_MODE)
?: ERoutingMode.GLOBAL_PROXY.value
if (directDomain.size > 0 || routingMode == ERoutingMode.BYPASS_MAINLAND.value || routingMode == ERoutingMode.BYPASS_LAN_MAINLAND.value) {
val domesticDns = Utils.getDomesticDnsServers()
val geositeCn = arrayListOf("geosite:cn")
val geoipCn = arrayListOf("geoip:cn")
if (directDomain.size > 0) {
servers.add(V2rayConfig.DnsBean.ServersBean(domesticDns.first(), 53, directDomain, geoipCn))
servers.add(
V2rayConfig.DnsBean.ServersBean(
domesticDns.first(),
53,
directDomain,
geoipCn
)
)
}
if (routingMode == ERoutingMode.BYPASS_MAINLAND.value || routingMode == ERoutingMode.BYPASS_LAN_MAINLAND.value) {
servers.add(V2rayConfig.DnsBean.ServersBean(domesticDns.first(), 53, geositeCn, geoipCn))
servers.add(
V2rayConfig.DnsBean.ServersBean(
domesticDns.first(),
53,
geositeCn,
geoipCn
)
)
}
if (Utils.isPureIpAddress(domesticDns.first())) {
v2rayConfig.routing.rules.add(0, V2rayConfig.RoutingBean.RulesBean(
v2rayConfig.routing.rules.add(
0, V2rayConfig.RoutingBean.RulesBean(
type = "field",
outboundTag = AppConfig.TAG_DIRECT,
port = "53",
ip = arrayListOf(domesticDns.first()),
domain = null)
domain = null
)
)
}
}
val blkDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_BLOCKED)
?: "")
val blkDomain = userRule2Domian(
settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_BLOCKED)
?: ""
)
if (blkDomain.size > 0) {
hosts.putAll(blkDomain.map { it to "127.0.0.1" })
}
@@ -381,17 +469,20 @@ object V2rayConfigUtil {
// DNS dns对象
v2rayConfig.dns = V2rayConfig.DnsBean(
servers = servers,
hosts = hosts)
servers = servers,
hosts = hosts
)
// DNS routing
if (Utils.isPureIpAddress(remoteDns.first())) {
v2rayConfig.routing.rules.add(0, V2rayConfig.RoutingBean.RulesBean(
v2rayConfig.routing.rules.add(
0, V2rayConfig.RoutingBean.RulesBean(
type = "field",
outboundTag = AppConfig.TAG_AGENT,
port = "53",
ip = arrayListOf(remoteDns.first()),
domain = null)
domain = null
)
)
}
} catch (e: Exception) {
@@ -463,6 +554,7 @@ object V2rayConfigUtil {
outbound.streamSettings?.tcpSettings?.header?.request?.headers?.Host = host!!
}
} catch (e: Exception) {
e.printStackTrace()
return false
@@ -470,4 +562,39 @@ object V2rayConfigUtil {
return true
}
private fun updateOutboundFragment(v2rayConfig: V2rayConfig): Boolean {
try {
if (settingsStorage?.decodeBool(AppConfig.PREF_FRAGMENT_ENABLED, false) == true) {
val fragmentOutbound =
V2rayConfig.OutboundBean(protocol = PROTOCOL_FREEDOM, tag = TAG_FRAGMENT, mux = null)
fragmentOutbound.settings = V2rayConfig.OutboundBean.OutSettingsBean(
fragment = V2rayConfig.OutboundBean.OutSettingsBean.FragmentBean(
packets = settingsStorage?.decodeString(AppConfig.PREF_FRAGMENT_PACKETS)
?: "tlshello",
length = settingsStorage?.decodeString(AppConfig.PREF_FRAGMENT_LENGTH)
?: "50-100",
interval = settingsStorage?.decodeString(AppConfig.PREF_FRAGMENT_INTERVAL)
?: "10-20"
)
)
fragmentOutbound.streamSettings = V2rayConfig.OutboundBean.StreamSettingsBean(
sockopt = V2rayConfig.OutboundBean.StreamSettingsBean.SockoptBean(
TcpNoDelay = true,
mark = 255
)
)
v2rayConfig.outbounds.add(fragmentOutbound)
//proxy chain
v2rayConfig.outbounds[0].streamSettings?.sockopt =
V2rayConfig.OutboundBean.StreamSettingsBean.SockoptBean(
dialerProxy = TAG_FRAGMENT
)
}
} catch (e: Exception) {
e.printStackTrace()
return false
}
return true
}
}
@@ -41,6 +41,9 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
AppConfig.PREF_V2RAY_ROUTING_BLOCKED,
AppConfig.PREF_V2RAY_ROUTING_DIRECT,
AppConfig.SUBSCRIPTION_AUTO_UPDATE_INTERVAL,
AppConfig.PREF_FRAGMENT_PACKETS,
AppConfig.PREF_FRAGMENT_LENGTH,
AppConfig.PREF_FRAGMENT_INTERVAL,
AppConfig.PREF_MUX_XUDP_QUIC, -> {
settingsStorage?.encode(key, sharedPreferences.getString(key, ""))
}
@@ -55,6 +58,7 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
AppConfig.PREF_CONFIRM_REMOVE,
AppConfig.PREF_START_SCAN_IMMEDIATE,
AppConfig.SUBSCRIPTION_AUTO_UPDATE,
AppConfig.PREF_FRAGMENT_ENABLED,
AppConfig.PREF_MUX_ENABLED, -> {
settingsStorage?.encode(key, sharedPreferences.getBoolean(key, false))
}
@@ -103,6 +103,7 @@
<string name="title_pref_per_app_proxy">Proxy Theo Ứng Dụng</string>
<string name="summary_pref_per_app_proxy">- Bình thường: Ứng dụng đã chọn sẽ kết nối thông qua Proxy, chưa chọn sẽ kết nối trực tiếp. \n- Chế độ Bypass: Ứng dụng đã chọn sẽ kết nối trực tiếp, chưa chọn sẽ kết nối qua Proxy. \n- Nếu bạn đang ở Trung Quốc thì vào Menu, chọn Tự động chọn ứng dụng Proxy.</string>
<string name="title_mux_settings">Mux Settings</string>
<string name="title_pref_mux_enabled">Bật Mux</string>
<string name="summary_pref_mux_enabled">Giảm độ trễ trong bước bắt tay của kết nối TCP. Mux phân phối dữ liệu từ nhiều kết nối TCP trên một kết nối TCP duy nhất. Không nên sử dụng Mux để xem video, download file hoặc chạy speedtest vì thường không hiệu quả.</string>
<string name="title_pref_mux_concurency">TCP connections (từ 1 đến 1024)</string>
@@ -103,6 +103,7 @@
<string name="title_pref_per_app_proxy">分应用代理</string>
<string name="summary_pref_per_app_proxy">常规:勾选的App被代理,未勾选的直连;\n绕行模式:勾选的App直连,未勾选的被代理.\n不明白者在菜单中选择自动选中需代理应用</string>
<string name="title_mux_settings">Mux 多路复用 设置</string>
<string name="title_pref_mux_enabled">启用 Mux 多路复用</string>
<string name="summary_pref_mux_enabled">减低延时,但可能会断流,建议不要启用。\nTCP,UDP 及 QUIC 流量处理方式下方可选。</string>
<string name="title_pref_mux_concurency">TCP 复用子链接数(可填 -1 至 1024)</string>
@@ -225,6 +226,16 @@
<string name="connection_connected">"已连接,点击测试连接"</string>
<string name="connection_not_connected">"未连接"</string>
<string name="import_subscription_success">订阅导入成功</string>
<string name="import_subscription_failure">导入订阅失败</string>
<string name="menu_item_add_asset">添加</string>
<string name="menu_item_add_url">添加链接</string>
<string name="title_fragment_settings">分片(fragment) 设置</string>
<string name="title_pref_fragment_packets">分片方式</string>
<string name="title_pref_fragment_length">分片包长(最小-最大)</string>
<string name="title_pref_fragment_interval">分片间隔(最小-最大)</string>
<string name="title_pref_fragment_enabled">启用分片(fragment)</string>
<string-array name="share_method">
<item>二维码</item>
<item>导出至剪贴板</item>
@@ -255,9 +266,5 @@
<item>VPN</item>
<item>仅代理</item>
</string-array>
<string name="import_subscription_success">订阅导入成功</string>
<string name="import_subscription_failure">导入订阅失败</string>
<string name="menu_item_add_asset">添加</string>
<string name="menu_item_add_url">添加链接</string>
</resources>
@@ -103,6 +103,7 @@
<string name="title_pref_per_app_proxy">Proxy 個別應用程式</string>
<string name="summary_pref_per_app_proxy">常規:勾選的 App 啟用 Proxy,未勾選的直接連線;\n繞行模式:勾選的 App 直接連線,未勾選的啟用 Proxy。\n可在選單中選擇自動選中需 Proxy 應用</string>
<string name="title_mux_settings">Mux 設定</string>
<string name="title_pref_mux_enabled">啟用 Mux 多路復用</string>
<string name="summary_pref_mux_enabled">減低延時 但可能會斷流\nTCP,UDP 及 QUIC 流量處理方式下方可選</string>
<string name="title_pref_mux_concurency">TCP 復用子鏈接數(可填 -1 至 1024)</string>
@@ -225,6 +226,16 @@
<string name="connection_connected">"已連線,輕觸以檢查連線能力"</string>
<string name="connection_not_connected">"未連線"</string>
<string name="import_subscription_success">訂閱導入成功</string>
<string name="import_subscription_failure">導入訂閱失敗</string>
<string name="menu_item_add_asset">添加</string>
<string name="menu_item_add_url">添加連結</string>
<string name="title_fragment_settings">分片(fragment) 設定</string>
<string name="title_pref_fragment_packets">分片方式</string>
<string name="title_pref_fragment_length">分片包长(最小-最大)</string>
<string name="title_pref_fragment_interval">分片间隔(最小-最大)</string>
<string name="title_pref_fragment_enabled">启用分片(fragment)</string>
<string-array name="share_method">
<item>QR Code</item>
<item>匯出至剪貼簿</item>
@@ -254,9 +265,5 @@
<item>VPN</item>
<item>僅 Proxy</item>
</string-array>
<string name="import_subscription_success">訂閱導入成功</string>
<string name="import_subscription_failure">導入訂閱失敗</string>
<string name="menu_item_add_asset">添加</string>
<string name="menu_item_add_url">添加連結</string>
</resources>
@@ -60,6 +60,10 @@
<item>reality</item>
</string-array>
<string-array name="fragment_packets" translatable="false">
<item>tlshello</item>
</string-array>
<string-array name="streamsecurity_utls" translatable="false">
<item></item>
<item>chrome</item>
@@ -114,6 +114,7 @@
<string name="title_pref_per_app_proxy">Per-app proxy</string>
<string name="summary_pref_per_app_proxy">General: Checked App is proxy, unchecked direct connection; \nbypass mode: checked app directly connected, unchecked proxy. \nThe option to automatically select the proxy application in the menu</string>
<string name="title_mux_settings">Mux Settings</string>
<string name="title_pref_mux_enabled">Enable Mux</string>
<string name="summary_pref_mux_enabled">Faster, but it may cause unstable connectivity\ncustomize how to handle TCP, UDP and QUIC below</string>
<string name="title_pref_mux_concurency">TCP connections(range -1 to 1024)</string>
@@ -240,6 +241,11 @@
<string name="import_subscription_success">Subscription imported Successfully</string>
<string name="import_subscription_failure">Import subscription failed</string>
<string name="title_fragment_settings">Fragment Settings</string>
<string name="title_pref_fragment_packets">Fragment Packets</string>
<string name="title_pref_fragment_length">Fragment Length (min-max)</string>
<string name="title_pref_fragment_interval">Fragment Interval (min-max)</string>
<string name="title_pref_fragment_enabled">Enable Fragment</string>
<string-array name="share_method">
<item>QRcode</item>
+51 -25
View File
@@ -7,31 +7,6 @@
android:summary="@string/summary_pref_sniffing_enabled"
android:title="@string/title_pref_sniffing_enabled" />
<CheckBoxPreference
android:key="pref_mux_enabled"
android:summary="@string/summary_pref_mux_enabled"
android:title="@string/title_pref_mux_enabled" />
<EditTextPreference
android:key="pref_mux_concurency"
android:summary="8"
android:inputType="number"
android:title="@string/title_pref_mux_concurency" />
<EditTextPreference
android:key="pref_mux_xudp_concurency"
android:summary="8"
android:inputType="number"
android:title="@string/title_pref_mux_xudp_concurency" />
<ListPreference
android:defaultValue="reject"
android:entries="@array/mux_xudp_quic_entries"
android:entryValues="@array/mux_xudp_quic_value"
android:key="pref_mux_xudp_quic"
android:summary="%s"
android:title="@string/title_pref_mux_xudp_quic" />
<PreferenceCategory android:title="@string/title_vpn_settings">
<CheckBoxPreference
android:key="pref_per_app_proxy"
@@ -84,6 +59,57 @@
</PreferenceCategory>
<PreferenceCategory android:title="@string/title_mux_settings">
<CheckBoxPreference
android:key="pref_mux_enabled"
android:summary="@string/summary_pref_mux_enabled"
android:title="@string/title_pref_mux_enabled" />
<EditTextPreference
android:key="pref_mux_concurency"
android:summary="8"
android:inputType="number"
android:title="@string/title_pref_mux_concurency" />
<EditTextPreference
android:key="pref_mux_xudp_concurency"
android:summary="8"
android:inputType="number"
android:title="@string/title_pref_mux_xudp_concurency" />
<ListPreference
android:defaultValue="reject"
android:entries="@array/mux_xudp_quic_entries"
android:entryValues="@array/mux_xudp_quic_value"
android:key="pref_mux_xudp_quic"
android:summary="%s"
android:title="@string/title_pref_mux_xudp_quic" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/title_fragment_settings">
<CheckBoxPreference
android:key="pref_fragment_enabled"
android:title="@string/title_pref_fragment_enabled"/>
<ListPreference
android:key="pref_fragment_packets"
android:defaultValue="tlshello"
android:entries="@array/fragment_packets"
android:entryValues="@array/fragment_packets"
android:summary="%s"
android:title="@string/title_pref_fragment_packets" />
<EditTextPreference
android:key="pref_fragment_length"
android:summary="50-100"
android:title="@string/title_pref_fragment_length" />
<EditTextPreference
android:key="pref_fragment_interval"
android:summary="10-20"
android:title="@string/title_pref_fragment_interval" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/title_sub_setting">
<CheckBoxPreference
android:key="pref_auto_update_subscription"