Compare commits

..

13 Commits

Author SHA1 Message Date
2dust eb60e4a0e4 Merge pull request #1058 from yuhan6665/grpc
Grpc
2021-05-16 19:35:16 +08:00
yuhan6665 c3dfa8cedc Support gRPC import and export
New Format https://github.com/XTLS/Xray-core/issues/91
For Vmess QRcode https://github.com/2dust/v2rayN/wiki/%E5%88%86%E4%BA%AB%E9%93%BE%E6%8E%A5%E6%A0%BC%E5%BC%8F%E8%AF%B4%E6%98%8E(ver-2)
gRPC mode is mapped to "type"
2021-05-15 23:18:09 -04:00
yuhan6665 f58bf85b6d Update UI for gRPC
Separate transport header types for different networks
Change UI dynamically based on user selection of network
2021-05-15 23:04:58 -04:00
2dust 906d0714b5 Merge pull request #1050 from yuhan6665/fakedns
Fakedns
2021-05-08 11:28:42 +08:00
yuhan6665 701fed2525 Update settings UI, add new VPN section 2021-05-07 21:55:44 -04:00
yuhan6665 e83208465f Add vpn dns preference setting
Vpn Dns can now be changed separately from remote Dns
2021-05-07 21:17:11 -04:00
yuhan6665 2b031033d3 Add fake dns preference setting 2021-05-07 20:55:02 -04:00
2dust e0e16b5934 fix tcp http request 2021-05-07 20:50:52 -04:00
2dust 0748f994ef Merge pull request #1038 from yuhan6665/new-storage-fix
New storage fix
2021-05-01 18:20:11 +08:00
yuhan6665 233b34bda6 Fix scrolling by cache server config in ViewModel 2021-04-30 20:17:41 -04:00
yuhan6665 6ece3385fe Fix trojan sni saved as null when it should be empty 2021-04-30 20:17:41 -04:00
2dust 9b8a810445 Merge pull request #1028 from yuhan6665/master
Update tun2socks
2021-04-26 08:22:47 +08:00
yuhan6665 f63242d147 Update tun2socks
https://github.com/XTLS/badvpn/commit/60a66a363f78def8831309cff0932c0bd5535e8e
compiled with NDK 22.1.7171670
2021-04-25 19:56:14 -04:00
22 changed files with 350 additions and 174 deletions
+2 -2
View File
@@ -23,8 +23,8 @@ trap 'echo -e "Aborted, error $? in command: $BASH_COMMAND"; trap ERR; clear_tmp
install -m644 $__dir/tun2socks.mk $TMPDIR/
pushd $TMPDIR
git clone --depth=1 https://github.com/shadowsocks/badvpn.git
git clone --depth=1 https://github.com/shadowsocks/libancillary.git
git clone --depth=1 https://github.com/XTLS/badvpn.git
git clone --depth=1 https://github.com/XTLS/libancillary.git
$NDK_HOME/ndk-build \
NDK_PROJECT_PATH=. \
APP_BUILD_SCRIPT=./tun2socks.mk \
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
@@ -18,8 +18,11 @@ object AppConfig {
const val PREF_SNIFFING_ENABLED = "pref_sniffing_enabled"
const val PREF_PROXY_SHARING = "pref_proxy_sharing_enabled"
const val PREF_LOCAL_DNS_ENABLED = "pref_local_dns_enabled"
const val PREF_FAKE_DNS_ENABLED = "pref_fake_dns_enabled"
const val PREF_VPN_DNS = "pref_vpn_dns"
const val PREF_REMOTE_DNS = "pref_remote_dns"
const val PREF_DOMESTIC_DNS = "pref_domestic_dns"
const val PREF_LOCAL_DNS_PORT = "pref_local_dns_port"
const val PREF_FORWARD_IPV6 = "pref_forward_ipv6"
const val PREF_ROUTING_DOMAIN_STRATEGY = "pref_routing_domain_strategy"
const val PREF_ROUTING_MODE = "pref_routing_mode"
@@ -20,7 +20,7 @@ data class V2rayConfig(
val api: Any? = null,
val transport: Any? = null,
val reverse: Any? = null,
val fakedns: Any? = null,
var fakedns: FakednsBean? = null,
val browserForwarder: Any? = null) {
companion object {
const val DEFAULT_PORT = 443
@@ -57,7 +57,7 @@ data class V2rayConfig(
val network: String? = null)
data class SniffingBean(var enabled: Boolean,
val destOverride: List<String>,
val destOverride: ArrayList<String>,
val metadataOnly: Boolean? = null)
}
@@ -78,7 +78,7 @@ data class V2rayConfig(
val address: String? = null,
val port: Int? = null,
/*Freedom*/
val domainStrategy: String? = null,
var domainStrategy: String? = null,
val redirect: String? = null,
val userLevel: Int? = null,
/*Loopback*/
@@ -192,10 +192,10 @@ data class V2rayConfig(
}
data class GrpcSettingsBean(var serviceName: String = "",
val multiMode: Boolean? = null)
var multiMode: Boolean? = null)
fun populateTransportSettings(transport: String, headerType: String?, host: String?, path: String?, seed: String?,
quicSecurity: String?, key: String?): String {
quicSecurity: String?, key: String?, mode: String?, serviceName: String?): String {
var sni = ""
network = transport
when (network) {
@@ -250,7 +250,8 @@ data class V2rayConfig(
}
"grpc" -> {
val grpcSetting = GrpcSettingsBean()
grpcSetting.serviceName = path ?: ""
grpcSetting.multiMode = mode == "multi"
grpcSetting.serviceName = serviceName ?: ""
sni = host ?: ""
grpcSettings = grpcSetting
}
@@ -357,7 +358,7 @@ data class V2rayConfig(
}
"grpc" -> {
val grpcSetting = streamSettings?.grpcSettings ?: return null
listOf("",
listOf(if (grpcSetting.multiMode == true) "multi" else "gun",
"",
grpcSetting.serviceName)
}
@@ -376,9 +377,9 @@ data class V2rayConfig(
val tag: String? = null
) {
data class ServersBean(var address: String = "",
var port: Int = 0,
var domains: List<String>?,
var expectIPs: List<String>?,
var port: Int? = null,
var domains: List<String>? = null,
var expectIPs: List<String>? = null,
val clientIp: String? = null)
}
@@ -416,6 +417,9 @@ data class V2rayConfig(
var bufferSize: Int? = null)
}
data class FakednsBean(var ipPool: String = "198.18.0.0/15",
var poolSize: Int = 10000) // roughly 10 times smaller than total ip pool
fun getProxyOutbound(): OutboundBean? {
outbounds.forEach { outbound ->
if (outbound.protocol.equals(EConfigType.VMESS.name, true) ||
@@ -122,10 +122,12 @@ class V2RayVpnService : VpnService(), ServiceControl {
}
if(!enableLocalDns) {
Utils.getRemoteDnsServers()
.forEach {
builder.addDnsServer(it)
}
Utils.getVpnDnsServers()
.forEach {
if (Utils.isPureIpAddress(it)) {
builder.addDnsServer(it)
}
}
}
builder.setSession(V2RayServiceManager.currentConfig?.remarks.orEmpty())
@@ -47,7 +47,7 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
if (holder is MainViewHolder) {
val guid = mActivity.mainViewModel.serverList.getOrNull(position) ?: return
val config = MmkvManager.decodeServerConfig(guid) ?: return
val config = mActivity.mainViewModel.serversCache.getOrElse(guid, { MmkvManager.decodeServerConfig(guid) })?: return
val outbound = config.getProxyOutbound()
val aff = MmkvManager.decodeServerAffiliationInfo(guid)
@@ -5,6 +5,9 @@ import android.support.v7.app.AlertDialog
import android.text.TextUtils
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.AdapterView
import android.widget.ArrayAdapter
import com.tencent.mmkv.MMKV
import com.v2ray.ang.R
import com.v2ray.ang.dto.EConfigType
@@ -28,6 +31,7 @@ import kotlinx.android.synthetic.main.activity_server_vmess.et_remarks
import kotlinx.android.synthetic.main.activity_server_vmess.et_request_host
import kotlinx.android.synthetic.main.activity_server_vmess.sp_allow_insecure
import kotlinx.android.synthetic.main.activity_server_vmess.sp_header_type
import kotlinx.android.synthetic.main.activity_server_vmess.sp_header_type_title
import kotlinx.android.synthetic.main.activity_server_vmess.sp_network
import kotlinx.android.synthetic.main.activity_server_vmess.sp_stream_security
@@ -56,8 +60,14 @@ class ServerActivity : BaseActivity() {
private val networks: Array<out String> by lazy {
resources.getStringArray(R.array.networks)
}
private val headertypes: Array<out String> by lazy {
resources.getStringArray(R.array.headertypes)
private val tcpTypes: Array<out String> by lazy {
resources.getStringArray(R.array.header_type_tcp)
}
private val kcpAndQuicTypes: Array<out String> by lazy {
resources.getStringArray(R.array.header_type_kcp_and_quic)
}
private val grpcModes: Array<out String> by lazy {
resources.getStringArray(R.array.mode_type_grpc)
}
private val streamSecuritys: Array<out String> by lazy {
resources.getStringArray(R.array.streamsecurityxs)
@@ -79,6 +89,26 @@ class ServerActivity : BaseActivity() {
// EConfigType.VLESS -> setContentView(R.layout.activity_server_vless)
// EConfigType.TROJAN -> setContentView(R.layout.activity_server_trojan)
}
sp_network?.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
val types = transportTypes(networks[position])
sp_header_type?.isEnabled = types.size > 1
val adapter = ArrayAdapter(this@ServerActivity, android.R.layout.simple_spinner_item, types)
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
sp_header_type?.adapter = adapter
sp_header_type_title?.text = if (networks[position] == "grpc")
getString(R.string.server_lab_mode_type) else
getString(R.string.server_lab_head_type)
config?.getProxyOutbound()?.getTransportSettingDetails()?.let { transportDetails ->
sp_header_type.setSelection(Utils.arrayFind(types, transportDetails[0]))
et_request_host.text = Utils.getEditable(transportDetails[1])
et_path.text = Utils.getEditable(transportDetails[2])
}
}
override fun onNothingSelected(parent: AdapterView<*>?) {
// do nothing
}
}
if (config != null) {
bindingServer(config)
} else {
@@ -129,11 +159,6 @@ class ServerActivity : BaseActivity() {
if (network >= 0) {
sp_network?.setSelection(network)
}
outbound.getTransportSettingDetails()?.let { transportDetails ->
sp_header_type.setSelection(Utils.arrayFind(headertypes, transportDetails[0]))
et_request_host.text = Utils.getEditable(transportDetails[1])
et_path.text = Utils.getEditable(transportDetails[2])
}
return true
}
@@ -246,16 +271,20 @@ class ServerActivity : BaseActivity() {
}
private fun saveStreamSettings(streamSetting: V2rayConfig.OutboundBean.StreamSettingsBean, config: ServerConfig) {
val requestHost = et_request_host?.text.toString().trim()
val path = et_path?.text.toString().trim()
val network = if (sp_network != null) networks[sp_network.selectedItemPosition] else DEFAULT_NETWORK
val type = if (sp_header_type != null) transportTypes(network)[sp_header_type.selectedItemPosition] else "";
val requestHost = if (et_request_host != null) et_request_host.text.toString().trim() else ""
val path = if (et_path != null) et_path.text.toString().trim() else ""
var sni = streamSetting.populateTransportSettings(
if (sp_network != null) networks[sp_network.selectedItemPosition] else DEFAULT_NETWORK,
if (sp_header_type != null) headertypes[sp_header_type.selectedItemPosition] else "",
requestHost,
path,
path,
requestHost,
path
transport = network,
headerType = type,
host = requestHost,
path = path,
seed = path,
quicSecurity = requestHost,
key = path,
mode = type,
serviceName = path
)
val allowInsecure = if (sp_allow_insecure == null || allowinsecures[sp_allow_insecure.selectedItemPosition].isBlank()) {
false//settingsStorage?.decodeBool(PREF_ALLOW_INSECURE) ?: false
@@ -270,6 +299,18 @@ class ServerActivity : BaseActivity() {
)
}
private fun transportTypes(network: String?): Array<out String> {
return if (network == "tcp") {
tcpTypes
} else if (network == "kcp" || network == "quic") {
kcpAndQuicTypes
} else if (network == "grpc") {
grpcModes
} else {
arrayOf("---")
}
}
/**
* save server config
*/
@@ -4,6 +4,7 @@ import android.arch.lifecycle.ViewModelProviders
import android.content.Intent
import android.os.Bundle
import android.support.v7.preference.*
import android.text.TextUtils
import android.view.View
import com.v2ray.ang.R
import com.v2ray.ang.AppConfig
@@ -29,6 +30,10 @@ class SettingsActivity : BaseActivity() {
class SettingsFragment : PreferenceFragmentCompat() {
private val perAppProxy by lazy { findPreference(AppConfig.PREF_PER_APP_PROXY) as CheckBoxPreference }
private val localDns by lazy { findPreference(AppConfig.PREF_LOCAL_DNS_ENABLED) }
private val fakeDns by lazy { findPreference(AppConfig.PREF_FAKE_DNS_ENABLED) }
private val localDnsPort by lazy { findPreference(AppConfig.PREF_LOCAL_DNS_PORT) }
private val vpnDns by lazy { findPreference(AppConfig.PREF_VPN_DNS) }
private val sppedEnabled by lazy { findPreference(AppConfig.PREF_SPEED_ENABLED) as CheckBoxPreference }
private val sniffingEnabled by lazy { findPreference(AppConfig.PREF_SNIFFING_ENABLED) as CheckBoxPreference }
private val proxySharing by lazy { findPreference(AppConfig.PREF_PROXY_SHARING) as CheckBoxPreference }
@@ -141,9 +146,21 @@ class SettingsActivity : BaseActivity() {
restartProxy()
true
}
localDns?.setOnPreferenceChangeListener{ _, any ->
updateLocalDns(any as Boolean)
true
}
localDnsPort?.setOnPreferenceChangeListener { _, any ->
val nval = any as String
localDnsPort?.summary = if (TextUtils.isEmpty(nval)) "10807" else nval
true
}
vpnDns?.setOnPreferenceChangeListener { _, any ->
vpnDns?.summary = any as String
true
}
mode.setOnPreferenceChangeListener { _, newValue ->
updatePerAppProxy(newValue.toString())
updateMode(newValue.toString())
true
}
mode.dialogLayoutResource = R.layout.preference_with_help_link
@@ -188,32 +205,43 @@ class SettingsActivity : BaseActivity() {
override fun onStart() {
super.onStart()
val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(activity)
updatePerAppProxy(defaultSharedPreferences.getString(AppConfig.PREF_MODE, "VPN"))
remoteDns.summary = defaultSharedPreferences.getString(AppConfig.PREF_REMOTE_DNS, "")
updateMode(defaultSharedPreferences.getString(AppConfig.PREF_MODE, "VPN"))
var remoteDnsString = defaultSharedPreferences.getString(AppConfig.PREF_REMOTE_DNS, "")
domesticDns.summary = defaultSharedPreferences.getString(AppConfig.PREF_DOMESTIC_DNS, "")
if (remoteDns.summary == "") {
remoteDns.summary = AppConfig.DNS_AGENT
if (TextUtils.isEmpty(remoteDnsString)) {
remoteDnsString = AppConfig.DNS_AGENT
}
if ( domesticDns.summary == "") {
domesticDns.summary = AppConfig.DNS_DIRECT
}
remoteDns.summary = remoteDnsString
vpnDns?.summary = defaultSharedPreferences.getString(AppConfig.PREF_VPN_DNS, remoteDnsString)
// socksPort.summary = defaultSharedPreferences.getString(PREF_SOCKS_PORT, "10808")
// lanconnPort.summary = defaultSharedPreferences.getString(PREF_HTTP_PORT, "")
}
private fun updatePerAppProxy(mode: String?) {
if (mode == "VPN") {
perAppProxy.isEnabled = true
perAppProxy.isChecked = PreferenceManager.getDefaultSharedPreferences(activity)
.getBoolean(AppConfig.PREF_PER_APP_PROXY, false)
} else {
perAppProxy.isEnabled = false
perAppProxy.isChecked = false
private fun updateMode(mode: String?) {
val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(activity)
val vpn = mode == "VPN"
perAppProxy.isEnabled = vpn
perAppProxy.isChecked = PreferenceManager.getDefaultSharedPreferences(activity)
.getBoolean(AppConfig.PREF_PER_APP_PROXY, false)
localDns?.isEnabled = vpn
fakeDns?.isEnabled = vpn
localDnsPort?.isEnabled = vpn
vpnDns?.isEnabled = vpn
if (vpn) {
updateLocalDns(defaultSharedPreferences.getBoolean(AppConfig.PREF_LOCAL_DNS_ENABLED, false))
}
}
private fun updateLocalDns(enabled: Boolean) {
fakeDns?.isEnabled = enabled
localDnsPort?.isEnabled = enabled
vpnDns?.isEnabled = !enabled
}
}
fun onModeHelpClicked(view: View) {
@@ -131,7 +131,8 @@ object AngConfigManager {
}
config.outboundBean?.streamSettings?.let { streamSetting ->
val sni = streamSetting.populateTransportSettings(vmessBean.network, vmessBean.headerType,
vmessBean.requestHost, vmessBean.path, vmessBean.path, vmessBean.requestHost, vmessBean.path)
vmessBean.requestHost, vmessBean.path, vmessBean.path, vmessBean.requestHost, vmessBean.path,
vmessBean.headerType, vmessBean.path)
// val allowInsecure = if (vmessBean.allowInsecure.isBlank()) {
// settingsStorage?.decodeBool(AppConfig.PREF_ALLOW_INSECURE) ?: false
// } else {
@@ -209,7 +210,7 @@ object AngConfigManager {
vnext.users[0].alterId = Utils.parseInt(vmessQRCode.aid)
}
val sni = streamSetting.populateTransportSettings(vmessQRCode.net, vmessQRCode.type, vmessQRCode.host,
vmessQRCode.path, vmessQRCode.path, vmessQRCode.host, vmessQRCode.path)
vmessQRCode.path, vmessQRCode.path, vmessQRCode.host, vmessQRCode.path, vmessQRCode.type, vmessQRCode.path)
streamSetting.populateTlsSettings(vmessQRCode.tls, allowInsecure,
if (vmessQRCode.sni.isNotBlank()) vmessQRCode.sni else sni)
}
@@ -312,7 +313,8 @@ object AngConfigManager {
}
val sni = streamSetting.populateTransportSettings(queryParam["type"] ?: "tcp", queryParam["headerType"],
queryParam["host"], queryParam["path"], queryParam["seed"], queryParam["quicSecurity"], queryParam["key"])
queryParam["host"], queryParam["path"], queryParam["seed"], queryParam["quicSecurity"], queryParam["key"],
queryParam["mode"], queryParam["serviceName"])
streamSetting.populateTlsSettings(queryParam["security"] ?: "", allowInsecure, queryParam["sni"] ?: sni)
}
if (config == null){
@@ -337,7 +339,7 @@ object AngConfigManager {
val uri = URI(uriString)
check(uri.scheme == "vmess")
val (_, protocol, tlsStr, uuid, alterId) =
Regex("(tcp|http|ws|kcp|quic)(\\+tls)?:([0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12})-([0-9]+)")
Regex("(tcp|http|ws|kcp|quic|grpc)(\\+tls)?:([0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12})-([0-9]+)")
.matchEntire(uri.userInfo)?.groupValues
?: error("parse user info fail.")
val tls = tlsStr.isNotBlank()
@@ -357,8 +359,8 @@ object AngConfigManager {
val sni = streamSetting.populateTransportSettings(protocol, queryParam["type"],
queryParam["host"]?.split("|")?.get(0) ?: "",
queryParam["path"]?.takeIf { it.trim() != "/" } ?: "",
queryParam["seed"], queryParam["security"], queryParam["key"])
queryParam["path"]?.takeIf { it.trim() != "/" } ?: "", queryParam["seed"], queryParam["security"],
queryParam["key"], queryParam["mode"], queryParam["serviceName"])
streamSetting.populateTlsSettings(if (tls) TLS else "", allowInsecure, sni)
true
}.getOrElse { false }
@@ -501,6 +503,10 @@ object AngConfigManager {
dicQuery["quicSecurity"] = Utils.urlEncode(transportDetails[1])
dicQuery["key"] = Utils.urlEncode(transportDetails[2])
}
"grpc" -> {
dicQuery["mode"] = transportDetails[0]
dicQuery["serviceName"] = transportDetails[2]
}
}
}
val query = "?" + dicQuery.toList().joinToString(
@@ -15,7 +15,6 @@ import android.content.ClipData
import android.content.Intent
import android.net.Uri
import android.os.SystemClock
import android.text.TextUtils
import android.util.Log
import android.util.Patterns
import android.webkit.URLUtil
@@ -123,41 +122,31 @@ object Utils {
/**
* get remote dns servers from preference
*/
fun getRemoteDnsServers(): ArrayList<String> {
fun getRemoteDnsServers(): List<String> {
val remoteDns = settingsStorage?.decodeString(AppConfig.PREF_REMOTE_DNS) ?: AppConfig.DNS_AGENT
val ret = ArrayList<String>()
if (!TextUtils.isEmpty(remoteDns)) {
remoteDns
.split(",")
.forEach {
if (Utils.isPureIpAddress(it)) {
ret.add(it)
}
}
}
if (ret.size == 0) {
ret.add(AppConfig.DNS_AGENT)
val ret = remoteDns.split(",").filter { isPureIpAddress(it) || it.startsWith("https") }
if (ret.isEmpty()) {
return listOf(AppConfig.DNS_AGENT)
}
return ret
}
fun getVpnDnsServers(): List<String> {
val vpnDns = settingsStorage?.decodeString(AppConfig.PREF_VPN_DNS)
?: settingsStorage?.decodeString(AppConfig.PREF_REMOTE_DNS)
?: AppConfig.DNS_AGENT
return vpnDns.split(",").filter { isPureIpAddress(it) }
// allow empty, in that case dns will use system default
}
/**
* get remote dns servers from preference
*/
fun getDomesticDnsServers(): ArrayList<String> {
fun getDomesticDnsServers(): List<String> {
val domesticDns = settingsStorage?.decodeString(AppConfig.PREF_DOMESTIC_DNS) ?: AppConfig.DNS_DIRECT
val ret = ArrayList<String>()
if (!TextUtils.isEmpty(domesticDns)) {
domesticDns
.split(",")
.forEach {
if (Utils.isPureIpAddress(it)) {
ret.add(it)
}
}
}
if (ret.size == 0) {
ret.add(AppConfig.DNS_DIRECT)
val ret = domesticDns.split(",").filter { isPureIpAddress(it) || it.startsWith("https") }
if (ret.isEmpty()) {
return listOf(AppConfig.DNS_DIRECT)
}
return ret
}
@@ -391,7 +380,7 @@ object Utils {
val command = "/system/bin/ping -c 3 $url"
val process = Runtime.getRuntime().exec(command)
val allText = process.inputStream.bufferedReader().use { it.readText() }
if (!TextUtils.isEmpty(allText)) {
if (allText.isNotBlank()) {
val tempInfo = allText.substring(allText.indexOf("min/avg/max/mdev") + 19)
val temps = tempInfo.split("/".toRegex()).dropLastWhile({ it.isEmpty() }).toTypedArray()
if (temps.count() > 0 && temps[0].length < 10) {
@@ -8,15 +8,10 @@ import com.tencent.mmkv.MMKV
import com.v2ray.ang.AppConfig
import com.v2ray.ang.dto.V2rayConfig
import com.v2ray.ang.dto.EConfigType
import com.v2ray.ang.dto.V2rayConfig.Companion.DEFAULT_NETWORK
import com.v2ray.ang.dto.V2rayConfig.Companion.HTTP
object V2rayConfigUtil {
// private val requestObj: JsonObject by lazy {
// Gson().fromJson("""{"version":"1.1","method":"GET","path":["/"],"headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36","Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/53.0.2785.109 Mobile/14A456 Safari/601.1.46"],"Accept-Encoding":["gzip, deflate"],"Connection":["keep-alive"],"Pragma":"no-cache"}}""", JsonObject::class.java)
// }
// private val responseObj: JSONObject by lazy {
// JSONObject("""{"version":"1.1","status":"200","reason":"OK","headers":{"Content-Type":["application/octet-stream","video/mpeg"],"Transfer-Encoding":["chunked"],"Connection":["keep-alive"],"Pragma":"no-cache"}}""")
// }
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) }
@@ -66,10 +61,14 @@ object V2rayConfigUtil {
inbounds(v2rayConfig)
httpRequestObject(outbound)
v2rayConfig.outbounds[0] = outbound
routing(v2rayConfig)
fakedns(v2rayConfig)
if (settingsStorage?.decodeBool(AppConfig.PREF_LOCAL_DNS_ENABLED) == true) {
customLocalDns(v2rayConfig)
} else {
@@ -99,7 +98,17 @@ object V2rayConfigUtil {
}
}
v2rayConfig.inbounds[0].port = 10808
v2rayConfig.inbounds[0].sniffing?.enabled = settingsStorage?.decodeBool(AppConfig.PREF_SNIFFING_ENABLED) ?: true
val fakedns = settingsStorage?.decodeBool(AppConfig.PREF_FAKE_DNS_ENABLED)
?: false
val sniffAllTlsAndHttp = settingsStorage?.decodeBool(AppConfig.PREF_SNIFFING_ENABLED)
?: true
v2rayConfig.inbounds[0].sniffing?.enabled = fakedns || sniffAllTlsAndHttp
if (!sniffAllTlsAndHttp) {
v2rayConfig.inbounds[0].sniffing?.destOverride?.clear()
}
if (fakedns) {
v2rayConfig.inbounds[0].sniffing?.destOverride?.add("fakedns")
}
//v2rayConfig.inbounds[1].port = httpPort
@@ -116,16 +125,29 @@ object V2rayConfigUtil {
return true
}
private fun fakedns(v2rayConfig: V2rayConfig) {
if (settingsStorage?.decodeBool(AppConfig.PREF_FAKE_DNS_ENABLED) == true) {
v2rayConfig.fakedns = V2rayConfig.FakednsBean()
v2rayConfig.outbounds.filter { it.protocol == "freedom" }.forEach {
it.settings?.domainStrategy = "UseIP"
}
}
}
/**
* routing
*/
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) ?: "IPIfNonMatch"
v2rayConfig.routing.domainStrategy = settingsStorage?.decodeString(AppConfig.PREF_ROUTING_DOMAIN_STRATEGY)
?: "IPIfNonMatch"
val routingMode = settingsStorage?.decodeString(AppConfig.PREF_ROUTING_MODE) ?: "0"
// Hardcode googleapis.cn
@@ -242,31 +264,34 @@ object V2rayConfigUtil {
val hosts = mutableMapOf<String, String>()
val servers = ArrayList<Any>()
val remoteDns = Utils.getRemoteDnsServers()
remoteDns.forEach {
servers.add(it)
}
val domesticDns = Utils.getDomesticDnsServers()
val geositeCn = arrayListOf("geosite:cn")
val geoipCn = arrayListOf("geoip:cn")
val proxyDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_AGENT)
?: "")
val directDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_DIRECT)
?: "")
val agDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_AGENT) ?: "")
if (agDomain.size > 0) {
servers.add(V2rayConfig.DnsBean.ServersBean(remoteDns.first(), 53, agDomain, null))
if (settingsStorage?.decodeBool(AppConfig.PREF_FAKE_DNS_ENABLED) == true) {
// fakedns with all domains to make it always top priority
servers.add(V2rayConfig.DnsBean.ServersBean(address = "fakedns", domains = geositeCn.plus(proxyDomain).plus(directDomain)))
}
val dirDomain = userRule2Domian(settingsStorage?.decodeString(AppConfig.PREF_V2RAY_ROUTING_DIRECT) ?: "")
if (dirDomain.size > 0) {
servers.add(V2rayConfig.DnsBean.ServersBean(domesticDns.first(), 53, dirDomain, geoipCn))
remoteDns.forEach {
servers.add(it)
}
if (proxyDomain.size > 0) {
servers.add(V2rayConfig.DnsBean.ServersBean(remoteDns.first(), 53, proxyDomain, null))
}
if (directDomain.size > 0) {
servers.add(V2rayConfig.DnsBean.ServersBean(domesticDns.first(), 53, directDomain, geoipCn))
}
val routingMode = settingsStorage?.decodeString(AppConfig.PREF_ROUTING_MODE) ?: "0"
if (routingMode == "2" || routingMode == "3") {
servers.add(V2rayConfig.DnsBean.ServersBean(domesticDns.first(), 53, geositeCn, geoipCn))
}
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" })
}
@@ -364,4 +389,27 @@ object V2rayConfigUtil {
}
return true
}
private fun httpRequestObject(outbound: V2rayConfig.OutboundBean): Boolean {
try {
if (outbound.streamSettings?.network == DEFAULT_NETWORK
&& outbound.streamSettings?.tcpSettings?.header?.type == HTTP) {
val path = outbound.streamSettings?.tcpSettings?.header?.request?.path
val Host = outbound.streamSettings?.tcpSettings?.header?.request?.headers?.Host
val requestString: String by lazy {
"""{"version":"1.1","method":"GET","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36","Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/53.0.2785.109 Mobile/14A456 Safari/601.1.46"],"Accept-Encoding":["gzip, deflate"],"Connection":["keep-alive"],"Pragma":"no-cache"}}"""
}
outbound.streamSettings?.tcpSettings?.header?.request = Gson().fromJson(requestString, V2rayConfig.OutboundBean.StreamSettingsBean.TcpSettingsBean.HeaderBean.RequestBean::class.java)
outbound.streamSettings?.tcpSettings?.header?.request?.path = path!!
outbound.streamSettings?.tcpSettings?.header?.request?.headers?.Host = Host!!
}
} catch (e: Exception) {
e.printStackTrace()
return false
}
return true
}
}
@@ -21,13 +21,15 @@ import com.v2ray.ang.util.*
import com.v2ray.ang.util.MmkvManager.KEY_ANG_CONFIGS
import kotlinx.coroutines.*
import java.util.*
import java.util.concurrent.ConcurrentHashMap
class MainViewModel(application: Application) : AndroidViewModel(application) {
private val mainStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_MAIN, MMKV.MULTI_PROCESS_MODE) }
private val serverRawStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SERVER_RAW, MMKV.MULTI_PROCESS_MODE) }
var serverList= MmkvManager.decodeServerList()
var serverList = MmkvManager.decodeServerList()
private set
val serversCache = ConcurrentHashMap<String, ServerConfig>()
val isRunning by lazy { MutableLiveData<Boolean>() }
val updateListAction by lazy { MutableLiveData<Int>() }
val updateTestResultAction by lazy { MutableLiveData<String>() }
@@ -50,6 +52,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
fun reloadServerList() {
serverList = MmkvManager.decodeServerList()
updateCache()
updateListAction.value = -1
}
@@ -65,6 +68,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
val key = MmkvManager.encodeServerConfig("", config)
serverRawStorage?.encode(key, server)
serverList.add(key)
serversCache[key] = config
}
fun swapServer(fromPosition: Int, toPosition: Int) {
@@ -72,6 +76,17 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
mainStorage?.encode(KEY_ANG_CONFIGS, Gson().toJson(serverList))
}
fun updateCache() {
serversCache.clear()
GlobalScope.launch(Dispatchers.Default) {
serverList.forEach { guid ->
MmkvManager.decodeServerConfig(guid)?.let {
serversCache[guid] = it
}
}
}
}
fun testAllTcping() {
tcpingTestScope.coroutineContext[Job]?.cancelChildren()
Utils.closeAllTcpSockets()
@@ -80,7 +95,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
getApplication<AngApplication>().toast(R.string.connection_test_testing)
for (guid in serverList) {
MmkvManager.decodeServerConfig(guid)?.getProxyOutbound()?.let { outbound ->
serversCache.getOrElse(guid, { MmkvManager.decodeServerConfig(guid) })?.getProxyOutbound()?.let { outbound ->
val serverAddress = outbound.getServerAddress()
val serverPort = outbound.getServerPort()
if (serverAddress != null && serverPort != null) {
@@ -27,6 +27,7 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
Log.d(AppConfig.ANG_PACKAGE, "Observe settings changed: $key")
when(key) {
AppConfig.PREF_MODE,
AppConfig.PREF_VPN_DNS,
AppConfig.PREF_REMOTE_DNS,
AppConfig.PREF_DOMESTIC_DNS,
AppConfig.PREF_ROUTING_DOMAIN_STRATEGY,
@@ -39,6 +40,7 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
AppConfig.PREF_SPEED_ENABLED,
AppConfig.PREF_PROXY_SHARING,
AppConfig.PREF_LOCAL_DNS_ENABLED,
AppConfig.PREF_FAKE_DNS_ENABLED,
AppConfig.PREF_FORWARD_IPV6,
AppConfig.PREF_PER_APP_PROXY,
AppConfig.PREF_BYPASS_APPS, -> {
@@ -174,6 +174,7 @@
android:orientation="vertical">
<TextView
android:id="@+id/sp_header_type_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/server_lab_head_type" />
@@ -181,8 +182,7 @@
<Spinner
android:id="@+id/sp_header_type"
android:layout_width="match_parent"
android:layout_height="@dimen/edit_height"
android:entries="@array/headertypes" />
android:layout_height="@dimen/edit_height" />
</LinearLayout>
<LinearLayout
@@ -43,8 +43,9 @@
<string name="server_lab_network">传输协议(network)</string>
<string name="server_lab_more_function">功能设置(不清楚则保持默认值)</string>
<string name="server_lab_head_type">伪装类型(type)</string>
<string name="server_lab_mode_type">gRPC 传输模式 (mode)</string>
<string name="server_lab_request_host">伪装域名(host)(host/ws host/h2 host)/QUIC 加密方式</string>
<string name="server_lab_path">path(ws path/h2 path)/QUIC 加密密钥/kcp seed/grpc serviceName</string>
<string name="server_lab_path">path(ws path/h2 path)/QUIC 加密密钥/kcp seed/gRPC serviceName</string>
<string name="server_lab_stream_security">底层传输安全(tls)</string>
<string name="server_lab_allow_insecure">跳过证书验证(allowInsecure)</string>
<string name="server_lab_address3">服务器地址</string>
@@ -76,7 +77,7 @@
<!-- Preferences -->
<string name="title_settings">设置</string>
<string name="title_advanced">进阶设置</string>
<string name="title_vpn_settings">VPN 设置</string>
<string name="title_pref_per_app_proxy">分应用代理</string>
<string name="summary_pref_per_app_proxy">分应用代理仅支持 Android 5.0 Lollipop 及更高</string>
@@ -87,10 +88,13 @@
<string name="summary_pref_speed_enabled">在通知中显示当前速度\n小图标显示流量的路由情况</string>
<string name="title_pref_sniffing_enabled">启用流量探测</string>
<string name="summary_pref_sniffing_enabled">流量探测</string>
<string name="summary_pref_sniffing_enabled">流量探测域名 (默认启用)</string>
<string name="title_pref_local_dns_enabled">启用本地DNS</string>
<string name="summary_pref_local_dns_enabled">DNS由本地设备的v2Ray-core处理(测试)</string>
<string name="summary_pref_local_dns_enabled">DNS 请求导入 core 由 DNS 模块处理(推荐启用 如果需要路由绕过局域网及大陆地址)</string>
<string name="title_pref_fake_dns_enabled">启用虚拟DNS</string>
<string name="summary_pref_fake_dns_enabled">本地返回虚构解析结果 (减低延时 但个别应用可能无法使用)</string>
<string name="title_pref_forward_ipv6">IPv6 路由</string>
<string name="summary_pref_forward_ipv6">转发 IPv6 流量到远程服务器(测试)</string>
@@ -107,7 +111,9 @@
<string name="title_pref_remote_dns">远程DNS (可选)</string>
<string name="summary_pref_remote_dns">DNS</string>
<string name="title_pref_domestic_dns">境内DNS (可选,本地DNS模式下生效)</string>
<string name="title_pref_vpn_dns">VPN DNS (仅支持 IPv4/v6)</string>
<string name="title_pref_domestic_dns">境内DNS (可选)</string>
<string name="summary_pref_domestic_dns">DNS</string>
<string name="title_pref_socks_port">SOCKS5代理端口</string>
@@ -116,6 +122,9 @@
<string name="title_pref_http_port">HTTP代理端口</string>
<string name="summary_pref_http_port">HTTP代理端口</string>
<string name="title_pref_local_dns_port">本地DNS端口</string>
<string name="summary_pref_local_dns_port">本地DNS端口</string>
<string name="title_pref_feedback">反馈</string>
<string name="summary_pref_feedback">反馈改进或漏洞至 GitHub</string>
<string name="summary_pref_tg_group">加入Telegram Group</string>
@@ -43,8 +43,9 @@
<string name="server_lab_network">網路</string>
<string name="server_lab_more_function">更多功能</string>
<string name="server_lab_head_type">標頭類型</string>
<string name="server_lab_mode_type">gRPC 傳輸模式 (mode)</string>
<string name="server_lab_request_host">要求主機(host)(host/ws host/h2 host)/QUIC加密方式</string>
<string name="server_lab_path">path(ws path/h2 path)/QUIC加密密鑰/kcp seed/grpc serviceName</string>
<string name="server_lab_path">path(ws path/h2 path)/QUIC加密密鑰/kcp seed/gRPC serviceName</string>
<string name="server_lab_stream_security">傳輸層安全性(tls)</string>
<string name="server_lab_allow_insecure">跳過證書驗證(allowInsecure)</string>
<string name="server_lab_address3">伺服器位址</string>
@@ -77,7 +78,7 @@
<!-- Preferences -->
<string name="title_settings">設定</string>
<string name="title_advanced">進階設定</string>
<string name="title_vpn_settings">VPN 設定</string>
<string name="title_pref_per_app_proxy">Proxy 個別應用程式</string>
<string name="summary_pref_per_app_proxy">Proxy 個別應用程式模式只支援 Android 5.0 (Lollipop) 或更高</string>
@@ -88,10 +89,13 @@
<string name="summary_pref_speed_enabled">在通知中顯示當前速度\n小圖標顯示流量的路由情況</string>
<string name="title_pref_sniffing_enabled">啟用流量探測</string>
<string name="summary_pref_sniffing_enabled">流量探測</string>
<string name="summary_pref_sniffing_enabled">流量探測域名 (默認啟用)</string>
<string name="title_pref_local_dns_enabled">啟用本地DNS</string>
<string name="summary_pref_local_dns_enabled">DNS請求由本地的v2ray core處理(測試</string>
<string name="summary_pref_local_dns_enabled">DNS 請求導入 core 由 DNS 模塊處理(推薦啟用 如果需要路由略過局域網及中國大陸</string>
<string name="title_pref_fake_dns_enabled">啟用虛擬DNS</string>
<string name="summary_pref_fake_dns_enabled">本地返回虛構解析結果 (減低延時 但個別應用可能無法使用)</string>
<string name="title_pref_forward_ipv6">IPv6 路由</string>
<string name="summary_pref_forward_ipv6">向遠端重新導向 IPv6 流量(測試)</string>
@@ -108,7 +112,9 @@
<string name="title_pref_remote_dns">遠端DNS (可選)</string>
<string name="summary_pref_remote_dns">DNS</string>
<string name="title_pref_domestic_dns">境内DNS (可選,僅本地DNS模式下生效)</string>
<string name="title_pref_vpn_dns">VPN DNS (僅支持 IPv4/v6)</string>
<string name="title_pref_domestic_dns">境内DNS (可選)</string>
<string name="summary_pref_domestic_dns">DNS</string>
<string name="title_pref_socks_port">SOCKS5代理連接埠</string>
@@ -117,6 +123,8 @@
<string name="title_pref_http_port">HTTP代理連接埠</string>
<string name="summary_pref_http_port">HTTP代理連接埠</string>
<string name="title_pref_local_dns_port">本地DNS端口</string>
<string name="summary_pref_local_dns_port">本地DNS端口</string>
<string name="title_pref_feedback">回饋</string>
<string name="summary_pref_feedback">回饋提升或前往 GitHub 回報 Bug</string>
+9 -13
View File
@@ -27,9 +27,13 @@
<item>grpc</item>
</string-array>
<string-array name="headertypes" translatable="false">
<string-array name="header_type_tcp" translatable="false">
<item>none</item>
<item>http</item>
</string-array>
<string-array name="header_type_kcp_and_quic" translatable="false">
<item>none</item>
<item>srtp</item>
<item>utp</item>
<item>wechat-video</item>
@@ -37,18 +41,10 @@
<item>wireguard</item>
</string-array>
<string-array name="headertypetcps" translatable="false">
<item>none</item>
<item>http</item>
</string-array>
<string-array name="headertypekcps" translatable="false">
<item>none</item>
<item>srtp</item>
<item>utp</item>
<item>wechat-video</item>
<item>dtls</item>
<item>wireguard</item>
<string-array name="mode_type_grpc" translatable="false">
<item>gun</item>
<item>multi</item>
<!--Hide this option until core support it <item>guna</item>-->
</string-array>
<string-array name="streamsecuritys" translatable="false">
+16 -6
View File
@@ -40,11 +40,12 @@
<string name="server_lab_id">id</string>
<string name="server_lab_alterid">alterId</string>
<string name="server_lab_security">security</string>
<string name="server_lab_network">network</string>
<string name="server_lab_network">Network</string>
<string name="server_lab_more_function">more function</string>
<string name="server_lab_head_type">head type</string>
<string name="server_lab_mode_type">gRPC mode</string>
<string name="server_lab_request_host">request host(host/ws host/h2 host)/QUIC security</string>
<string name="server_lab_path">path(ws path/h2 path)/QUIC key/kcp seed/grpc serviceName</string>
<string name="server_lab_path">path(ws path/h2 path)/QUIC key/kcp seed/gRPC serviceName</string>
<string name="server_lab_stream_security">tls</string>
<string name="server_lab_allow_insecure">allowInsecure</string>
<string name="server_lab_address3">address</string>
@@ -77,7 +78,7 @@
<!-- Preferences -->
<string name="title_settings">Settings</string>
<string name="title_advanced">Advanced Settings</string>
<string name="title_vpn_settings">VPN Settings</string>
<string name="title_pref_per_app_proxy">Per-app proxy</string>
<string name="summary_pref_per_app_proxy">Per-app proxy mode only support Android 5.0 Lollipop or higher</string>
@@ -89,10 +90,14 @@
usage.</string>
<string name="title_pref_sniffing_enabled">Enable Sniffing</string>
<string name="summary_pref_sniffing_enabled">Sniffing</string>
<string name="summary_pref_sniffing_enabled">Try sniff domain from the packet (default on)</string>
<string name="title_pref_local_dns_enabled">Enable local DNS</string>
<string name="summary_pref_local_dns_enabled">DNS processed by v2ray-core (BETA)</string>
<string name="summary_pref_local_dns_enabled">DNS processed by cores DNS module (Recommended, if need routing Bypassing LAN and
mainland address)</string>
<string name="title_pref_fake_dns_enabled">Enable fake DNS</string>
<string name="summary_pref_fake_dns_enabled">local DNS returns fake IP address (faster, but it may not work for some apps)</string>
<string name="title_pref_forward_ipv6">IPv6 Route</string>
<string name="summary_pref_forward_ipv6">Redirect IPv6 traffic to remote (BETA)</string>
@@ -109,7 +114,9 @@
<string name="title_pref_remote_dns">Remote DNS (Optional)</string>
<string name="summary_pref_remote_dns">DNS</string>
<string name="title_pref_domestic_dns">Domestic DNS (Optional, effects on LocalDNS mode)</string>
<string name="title_pref_vpn_dns">VPN DNS (only IPv4/v6)</string>
<string name="title_pref_domestic_dns">Domestic DNS (Optional)</string>
<string name="summary_pref_domestic_dns">DNS</string>
<string name="title_pref_socks_port">SOCKS5 proxy port</string>
@@ -118,6 +125,9 @@
<string name="title_pref_http_port">HTTP proxy port</string>
<string name="summary_pref_http_port">HTTP proxy port</string>
<string name="title_pref_local_dns_port">Local DNS port</string>
<string name="summary_pref_local_dns_port">Local DNS port</string>
<string name="title_pref_feedback">Feedback</string>
<string name="summary_pref_feedback">Feedback enhancements or bugs to GitHub</string>
<string name="summary_pref_tg_group">Join Telegram Group</string>
+48 -33
View File
@@ -1,6 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/title_settings">
<CheckBoxPreference
android:key="pref_speed_enabled"
android:summary="@string/summary_pref_speed_enabled"
android:title="@string/title_pref_speed_enabled" />
<CheckBoxPreference
android:defaultValue="true"
android:key="pref_sniffing_enabled"
android:summary="@string/summary_pref_sniffing_enabled"
android:title="@string/title_pref_sniffing_enabled" />
<PreferenceCategory android:title="@string/title_vpn_settings">
<CheckBoxPreference
android:key="pref_per_app_proxy"
android:summary="@string/summary_pref_per_app_proxy"
@@ -10,24 +21,26 @@
<!--android:key="pref_mux_enabled"-->
<!--android:summary="@string/summary_pref_mux_enabled"-->
<!--android:title="@string/title_pref_mux_enabled" />-->
<CheckBoxPreference
android:key="pref_local_dns_enabled"
android:summary="@string/summary_pref_local_dns_enabled"
android:title="@string/title_pref_local_dns_enabled" />
<CheckBoxPreference
android:key="pref_speed_enabled"
android:summary="@string/summary_pref_speed_enabled"
android:title="@string/title_pref_speed_enabled" />
android:key="pref_fake_dns_enabled"
android:summary="@string/summary_pref_fake_dns_enabled"
android:title="@string/title_pref_fake_dns_enabled" />
<CheckBoxPreference
android:defaultValue="true"
android:key="pref_sniffing_enabled"
android:summary="@string/summary_pref_sniffing_enabled"
android:title="@string/title_pref_sniffing_enabled" />
<EditTextPreference
android:key="pref_local_dns_port"
android:summary="10807"
android:inputType="number"
android:title="@string/title_pref_local_dns_port" />
<CheckBoxPreference
android:defaultValue="false"
android:key="pref_proxy_sharing_enabled"
android:onClick="proxySharingOnClick"
android:summary="@string/summary_pref_proxy_sharing_enabled"
android:title="@string/title_pref_proxy_sharing_enabled" />
<EditTextPreference
android:key="pref_vpn_dns"
android:summary="@string/summary_pref_remote_dns"
android:title="@string/title_pref_vpn_dns" />
</PreferenceCategory>
@@ -40,6 +53,11 @@
android:summary="%s"
android:title="@string/title_pref_routing_domain_strategy" />
<Preference
android:key="pref_routing_custom"
android:summary="@string/title_pref_routing_custom"
android:title="@string/title_pref_routing_custom" />
<ListPreference
android:defaultValue="0"
android:entries="@array/routing_mode"
@@ -47,11 +65,6 @@
android:key="pref_routing_mode"
android:summary="%s"
android:title="@string/title_pref_routing_mode" />
<Preference
android:key="pref_routing_custom"
android:summary="@string/title_pref_routing_custom"
android:title="@string/title_pref_routing_custom" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/title_advanced">
@@ -62,19 +75,11 @@
android:title="@string/title_pref_forward_ipv6" />
<CheckBoxPreference
android:key="pref_local_dns_enabled"
android:summary="@string/summary_pref_local_dns_enabled"
android:title="@string/title_pref_local_dns_enabled" />
<EditTextPreference
android:key="pref_domestic_dns"
android:summary="@string/summary_pref_domestic_dns"
android:title="@string/title_pref_domestic_dns" />
<EditTextPreference
android:key="pref_remote_dns"
android:summary="@string/summary_pref_remote_dns"
android:title="@string/title_pref_remote_dns" />
android:defaultValue="false"
android:key="pref_proxy_sharing_enabled"
android:onClick="proxySharingOnClick"
android:summary="@string/summary_pref_proxy_sharing_enabled"
android:title="@string/title_pref_proxy_sharing_enabled" />
<Preference
android:key="pref_socks_port"
@@ -86,6 +91,16 @@
android:summary="10809"
android:title="@string/title_pref_http_port" />
<EditTextPreference
android:key="pref_remote_dns"
android:summary="@string/summary_pref_remote_dns"
android:title="@string/title_pref_remote_dns" />
<EditTextPreference
android:key="pref_domestic_dns"
android:summary="@string/summary_pref_domestic_dns"
android:title="@string/title_pref_domestic_dns" />
<ListPreference
android:defaultValue="VPN"
android:entries="@array/mode_entries"