From f55d14b4439092cdb7e61f3235214677f4cde6de Mon Sep 17 00:00:00 2001 From: arm64v8a <48624112+arm64v8a@users.noreply.github.com> Date: Sat, 18 Mar 2023 18:01:33 +0900 Subject: [PATCH] add shadowtls gui --- .../2.json | 12 +++- app/src/main/AndroidManifest.xml | 3 + .../sagernet/database/ProxyEntity.kt | 23 +++++-- .../nekohasekai/sagernet/fmt/ConfigBuilder.kt | 6 +- .../sagernet/fmt/KryoConverters.java | 7 ++ .../sagernet/ui/ConfigurationFragment.kt | 4 ++ .../nb4a/proxy/shadowtls/ShadowTLSBean.java | 61 +++++++++++++++++ .../nb4a/proxy/shadowtls/ShadowTLSFmt.kt | 15 +++++ .../shadowtls/ShadowTLSSettingsActivity.kt | 55 ++++++++++++++++ app/src/main/res/menu/add_profile_menu.xml | 3 + app/src/main/res/values-es/strings.xml | 16 +---- app/src/main/res/values-zh-rCN/strings.xml | 4 ++ app/src/main/res/values/arrays.xml | 5 ++ app/src/main/res/values/strings.xml | 2 + .../main/res/xml/shadowtls_preferences.xml | 65 +++++++++++++++++++ 15 files changed, 257 insertions(+), 24 deletions(-) create mode 100644 app/src/main/java/moe/matsuri/nb4a/proxy/shadowtls/ShadowTLSBean.java create mode 100644 app/src/main/java/moe/matsuri/nb4a/proxy/shadowtls/ShadowTLSFmt.kt create mode 100644 app/src/main/java/moe/matsuri/nb4a/proxy/shadowtls/ShadowTLSSettingsActivity.kt create mode 100644 app/src/main/res/xml/shadowtls_preferences.xml diff --git a/app/schemas/io.nekohasekai.sagernet.database.SagerDatabase/2.json b/app/schemas/io.nekohasekai.sagernet.database.SagerDatabase/2.json index 1322923..983ebc7 100644 --- a/app/schemas/io.nekohasekai.sagernet.database.SagerDatabase/2.json +++ b/app/schemas/io.nekohasekai.sagernet.database.SagerDatabase/2.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 2, - "identityHash": "937a517378a0cb35dc1f8bd181683882", + "identityHash": "9ec160533656482a17cbd563e9e3e416", "entities": [ { "tableName": "proxy_groups", @@ -80,7 +80,7 @@ }, { "tableName": "proxy_entities", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupId` INTEGER NOT NULL, `type` INTEGER NOT NULL, `userOrder` INTEGER NOT NULL, `tx` INTEGER NOT NULL, `rx` INTEGER NOT NULL, `status` INTEGER NOT NULL, `ping` INTEGER NOT NULL, `uuid` TEXT NOT NULL, `error` TEXT, `socksBean` BLOB, `httpBean` BLOB, `ssBean` BLOB, `vmessBean` BLOB, `trojanBean` BLOB, `trojanGoBean` BLOB, `naiveBean` BLOB, `hysteriaBean` BLOB, `tuicBean` BLOB, `sshBean` BLOB, `wgBean` BLOB, `chainBean` BLOB, `nekoBean` BLOB, `configBean` BLOB)", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupId` INTEGER NOT NULL, `type` INTEGER NOT NULL, `userOrder` INTEGER NOT NULL, `tx` INTEGER NOT NULL, `rx` INTEGER NOT NULL, `status` INTEGER NOT NULL, `ping` INTEGER NOT NULL, `uuid` TEXT NOT NULL, `error` TEXT, `socksBean` BLOB, `httpBean` BLOB, `ssBean` BLOB, `vmessBean` BLOB, `trojanBean` BLOB, `trojanGoBean` BLOB, `naiveBean` BLOB, `hysteriaBean` BLOB, `tuicBean` BLOB, `sshBean` BLOB, `wgBean` BLOB, `shadowTLSBean` BLOB, `chainBean` BLOB, `nekoBean` BLOB, `configBean` BLOB)", "fields": [ { "fieldPath": "id", @@ -208,6 +208,12 @@ "affinity": "BLOB", "notNull": false }, + { + "fieldPath": "shadowTLSBean", + "columnName": "shadowTLSBean", + "affinity": "BLOB", + "notNull": false + }, { "fieldPath": "chainBean", "columnName": "chainBean", @@ -342,7 +348,7 @@ "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '937a517378a0cb35dc1f8bd181683882')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '9ec160533656482a17cbd563e9e3e416')" ] } } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f785528..f06850e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -184,6 +184,9 @@ + diff --git a/app/src/main/java/io/nekohasekai/sagernet/database/ProxyEntity.kt b/app/src/main/java/io/nekohasekai/sagernet/database/ProxyEntity.kt index 602d233..228c625 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/database/ProxyEntity.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/database/ProxyEntity.kt @@ -15,6 +15,7 @@ import io.nekohasekai.sagernet.fmt.naive.NaiveBean import io.nekohasekai.sagernet.fmt.naive.buildNaiveConfig import io.nekohasekai.sagernet.fmt.naive.toUri import io.nekohasekai.sagernet.fmt.shadowsocks.* +import moe.matsuri.nb4a.proxy.shadowtls.ShadowTLSBean import io.nekohasekai.sagernet.fmt.socks.SOCKSBean import io.nekohasekai.sagernet.fmt.socks.toUri import io.nekohasekai.sagernet.fmt.ssh.SSHBean @@ -34,6 +35,7 @@ import moe.matsuri.nb4a.Protocols import moe.matsuri.nb4a.proxy.config.ConfigBean import moe.matsuri.nb4a.proxy.config.ConfigSettingActivity import moe.matsuri.nb4a.proxy.neko.* +import moe.matsuri.nb4a.proxy.shadowtls.ShadowTLSSettingsActivity @Entity( tableName = "proxy_entities", indices = [Index("groupId", name = "groupId")] @@ -60,6 +62,7 @@ data class ProxyEntity( var tuicBean: TuicBean? = null, var sshBean: SSHBean? = null, var wgBean: WireGuardBean? = null, + var shadowTLSBean: ShadowTLSBean? = null, var chainBean: ChainBean? = null, var nekoBean: NekoBean? = null, var configBean: ConfigBean? = null, @@ -70,16 +73,17 @@ data class ProxyEntity( const val TYPE_HTTP = 1 const val TYPE_SS = 2 const val TYPE_VMESS = 4 - const val TYPE_TROJAN = 6 + const val TYPE_TROJAN_GO = 7 const val TYPE_NAIVE = 9 const val TYPE_HYSTERIA = 15 + const val TYPE_TUIC = 20 const val TYPE_SSH = 17 const val TYPE_WG = 18 - const val TYPE_TUIC = 20 + const val TYPE_SHADOWTLS = 19 const val TYPE_CONFIG = 998 const val TYPE_NEKO = 999 @@ -103,10 +107,6 @@ data class ProxyEntity( } } - @Ignore - @Transient - var info: String = "" - @Ignore @Transient var dirty: Boolean = false @@ -167,6 +167,7 @@ data class ProxyEntity( TYPE_SSH -> sshBean = KryoConverters.sshDeserialize(byteArray) TYPE_WG -> wgBean = KryoConverters.wireguardDeserialize(byteArray) TYPE_TUIC -> tuicBean = KryoConverters.tuicDeserialize(byteArray) + TYPE_SHADOWTLS -> shadowTLSBean = KryoConverters.shadowTLSDeserialize(byteArray) TYPE_CHAIN -> chainBean = KryoConverters.chainDeserialize(byteArray) TYPE_NEKO -> nekoBean = KryoConverters.nekoDeserialize(byteArray) TYPE_CONFIG -> configBean = KryoConverters.configDeserialize(byteArray) @@ -185,6 +186,7 @@ data class ProxyEntity( TYPE_SSH -> "SSH" TYPE_WG -> "WireGuard" TYPE_TUIC -> "TUIC" + TYPE_SHADOWTLS -> "ShadowTLS" TYPE_CHAIN -> chainName TYPE_NEKO -> nekoBean!!.displayType() TYPE_CONFIG -> configBean!!.displayType() @@ -207,6 +209,7 @@ data class ProxyEntity( TYPE_SSH -> sshBean TYPE_WG -> wgBean TYPE_TUIC -> tuicBean + TYPE_SHADOWTLS -> shadowTLSBean TYPE_CHAIN -> chainBean TYPE_NEKO -> nekoBean TYPE_CONFIG -> configBean @@ -226,6 +229,7 @@ data class ProxyEntity( is TuicBean -> false is SSHBean -> false is WireGuardBean -> false + is ShadowTLSBean -> false is NekoBean -> nekoBean!!.haveStandardLink() is ConfigBean -> false else -> true @@ -245,6 +249,7 @@ data class ProxyEntity( is SSHBean -> toUniversalLink() is WireGuardBean -> toUniversalLink() is TuicBean -> toUniversalLink() + is ShadowTLSBean -> toUniversalLink() is ConfigBean -> toUniversalLink() is NekoBean -> shareLink() else -> null @@ -329,6 +334,7 @@ data class ProxyEntity( sshBean = null wgBean = null tuicBean = null + shadowTLSBean = null chainBean = null configBean = null nekoBean = null @@ -378,6 +384,10 @@ data class ProxyEntity( type = TYPE_TUIC tuicBean = bean } + is ShadowTLSBean -> { + type = TYPE_SHADOWTLS + shadowTLSBean = bean + } is ChainBean -> { type = TYPE_CHAIN chainBean = bean @@ -409,6 +419,7 @@ data class ProxyEntity( TYPE_SSH -> SSHSettingsActivity::class.java TYPE_WG -> WireGuardSettingsActivity::class.java TYPE_TUIC -> TuicSettingsActivity::class.java + TYPE_SHADOWTLS -> ShadowTLSSettingsActivity::class.java TYPE_CHAIN -> ChainSettingsActivity::class.java TYPE_NEKO -> NekoSettingActivity::class.java TYPE_CONFIG -> ConfigSettingActivity::class.java diff --git a/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt b/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt index 691a18a..72babe0 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt @@ -32,6 +32,8 @@ import moe.matsuri.nb4a.DNS.makeSingBoxRule import moe.matsuri.nb4a.SingBoxOptions.* import moe.matsuri.nb4a.plugin.Plugins import moe.matsuri.nb4a.proxy.config.ConfigBean +import moe.matsuri.nb4a.proxy.shadowtls.ShadowTLSBean +import moe.matsuri.nb4a.proxy.shadowtls.buildSingBoxOutboundShadowTLSBean import moe.matsuri.nb4a.utils.JavaUtil.gson import okhttp3.HttpUrl.Companion.toHttpUrlOrNull @@ -360,7 +362,9 @@ fun buildConfig( currentOutbound = when (bean) { is ConfigBean -> gson.fromJson(bean.config, currentOutbound.javaClass) - is StandardV2RayBean -> + is ShadowTLSBean -> // before StandardV2RayBean + buildSingBoxOutboundShadowTLSBean(bean).asMap() + is StandardV2RayBean -> // http/trojan/vmess/vless buildSingBoxOutboundStandardV2RayBean(bean).asMap() is HysteriaBean -> buildSingBoxOutboundHysteriaBean(bean).asMap() diff --git a/app/src/main/java/io/nekohasekai/sagernet/fmt/KryoConverters.java b/app/src/main/java/io/nekohasekai/sagernet/fmt/KryoConverters.java index 8000c02..b9a6338 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/fmt/KryoConverters.java +++ b/app/src/main/java/io/nekohasekai/sagernet/fmt/KryoConverters.java @@ -15,6 +15,7 @@ import io.nekohasekai.sagernet.fmt.hysteria.HysteriaBean; import io.nekohasekai.sagernet.fmt.internal.ChainBean; import io.nekohasekai.sagernet.fmt.naive.NaiveBean; import io.nekohasekai.sagernet.fmt.shadowsocks.ShadowsocksBean; +import moe.matsuri.nb4a.proxy.shadowtls.ShadowTLSBean; import io.nekohasekai.sagernet.fmt.socks.SOCKSBean; import io.nekohasekai.sagernet.fmt.ssh.SSHBean; import io.nekohasekai.sagernet.fmt.trojan.TrojanBean; @@ -128,6 +129,12 @@ public class KryoConverters { return deserialize(new TuicBean(), bytes); } + @TypeConverter + public static ShadowTLSBean shadowTLSDeserialize(byte[] bytes) { + if (JavaUtil.isEmpty(bytes)) return null; + return deserialize(new ShadowTLSBean(), bytes); + } + @TypeConverter public static ChainBean chainDeserialize(byte[] bytes) { if (JavaUtil.isEmpty(bytes)) return null; diff --git a/app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt b/app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt index 7565501..a396644 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt @@ -61,6 +61,7 @@ import moe.matsuri.nb4a.proxy.config.ConfigSettingActivity import moe.matsuri.nb4a.proxy.neko.NekoJSInterface import moe.matsuri.nb4a.proxy.neko.NekoSettingActivity import moe.matsuri.nb4a.proxy.neko.canShare +import moe.matsuri.nb4a.proxy.shadowtls.ShadowTLSSettingsActivity import okhttp3.internal.closeQuietly import java.net.InetAddress import java.net.InetSocketAddress @@ -354,6 +355,9 @@ class ConfigurationFragment @JvmOverloads constructor( R.id.action_new_wg -> { startActivity(Intent(requireActivity(), WireGuardSettingsActivity::class.java)) } + R.id.action_new_shadowtls -> { + startActivity(Intent(requireActivity(), ShadowTLSSettingsActivity::class.java)) + } R.id.action_new_config -> { startActivity(Intent(requireActivity(), ConfigSettingActivity::class.java)) } diff --git a/app/src/main/java/moe/matsuri/nb4a/proxy/shadowtls/ShadowTLSBean.java b/app/src/main/java/moe/matsuri/nb4a/proxy/shadowtls/ShadowTLSBean.java new file mode 100644 index 0000000..43cf283 --- /dev/null +++ b/app/src/main/java/moe/matsuri/nb4a/proxy/shadowtls/ShadowTLSBean.java @@ -0,0 +1,61 @@ +package moe.matsuri.nb4a.proxy.shadowtls; + +import androidx.annotation.NonNull; + +import com.esotericsoftware.kryo.io.ByteBufferInput; +import com.esotericsoftware.kryo.io.ByteBufferOutput; + +import org.jetbrains.annotations.NotNull; + +import io.nekohasekai.sagernet.fmt.KryoConverters; +import io.nekohasekai.sagernet.fmt.v2ray.StandardV2RayBean; + +public class ShadowTLSBean extends StandardV2RayBean { + + public Integer version; + public String password; + + @Override + public void initializeDefaultValues() { + super.initializeDefaultValues(); + + security = "tls"; + if (version == null) version = 3; + if (password == null) password = ""; + } + + @Override + public void serialize(ByteBufferOutput output) { + output.writeInt(0); + super.serialize(output); + output.writeInt(version); + output.writeString(password); + } + + @Override + public void deserialize(ByteBufferInput input) { + int version_ = input.readInt(); + super.deserialize(input); + version = input.readInt(); + password = input.readString(); + } + + @NotNull + @Override + public ShadowTLSBean clone() { + return KryoConverters.deserialize(new ShadowTLSBean(), KryoConverters.serialize(this)); + } + + public static final Creator CREATOR = new CREATOR() { + @NonNull + @Override + public ShadowTLSBean newInstance() { + return new ShadowTLSBean(); + } + + @Override + public ShadowTLSBean[] newArray(int size) { + return new ShadowTLSBean[size]; + } + }; +} diff --git a/app/src/main/java/moe/matsuri/nb4a/proxy/shadowtls/ShadowTLSFmt.kt b/app/src/main/java/moe/matsuri/nb4a/proxy/shadowtls/ShadowTLSFmt.kt new file mode 100644 index 0000000..e0aa5dc --- /dev/null +++ b/app/src/main/java/moe/matsuri/nb4a/proxy/shadowtls/ShadowTLSFmt.kt @@ -0,0 +1,15 @@ +package moe.matsuri.nb4a.proxy.shadowtls + +import io.nekohasekai.sagernet.fmt.v2ray.buildSingBoxOutboundTLS +import moe.matsuri.nb4a.SingBoxOptions + +fun buildSingBoxOutboundShadowTLSBean(bean: ShadowTLSBean): SingBoxOptions.Outbound_ShadowTLSOptions { + return SingBoxOptions.Outbound_ShadowTLSOptions().apply { + type = "shadowtls" + server = bean.serverAddress + server_port = bean.serverPort + version = bean.version + password = bean.password + tls = buildSingBoxOutboundTLS(bean) + } +} diff --git a/app/src/main/java/moe/matsuri/nb4a/proxy/shadowtls/ShadowTLSSettingsActivity.kt b/app/src/main/java/moe/matsuri/nb4a/proxy/shadowtls/ShadowTLSSettingsActivity.kt new file mode 100644 index 0000000..3999170 --- /dev/null +++ b/app/src/main/java/moe/matsuri/nb4a/proxy/shadowtls/ShadowTLSSettingsActivity.kt @@ -0,0 +1,55 @@ +package moe.matsuri.nb4a.proxy.shadowtls + +import android.os.Bundle +import androidx.preference.EditTextPreference +import androidx.preference.PreferenceFragmentCompat +import io.nekohasekai.sagernet.R +import io.nekohasekai.sagernet.database.preference.EditTextPreferenceModifiers +import io.nekohasekai.sagernet.ui.profile.ProfileSettingsActivity +import moe.matsuri.nb4a.proxy.PreferenceBinding +import moe.matsuri.nb4a.proxy.PreferenceBindingManager +import moe.matsuri.nb4a.proxy.Type + +class ShadowTLSSettingsActivity : ProfileSettingsActivity() { + + override fun createEntity() = ShadowTLSBean() + + private val pbm = PreferenceBindingManager() + private val name = pbm.add(PreferenceBinding(Type.Text, "name")) + private val serverAddress = pbm.add(PreferenceBinding(Type.Text, "serverAddress")) + private val serverPort = pbm.add(PreferenceBinding(Type.TextToInt, "serverPort")) + private val password = pbm.add(PreferenceBinding(Type.Text, "password")) + private val version = pbm.add(PreferenceBinding(Type.TextToInt, "version")) + private val sni = pbm.add(PreferenceBinding(Type.Text, "sni")) + private val alpn = pbm.add(PreferenceBinding(Type.Text, "alpn")) + private val certificates = pbm.add(PreferenceBinding(Type.Text, "certificates")) + private val allowInsecure = pbm.add(PreferenceBinding(Type.Bool, "allowInsecure")) + private val utlsFingerprint = pbm.add(PreferenceBinding(Type.Text, "utlsFingerprint")) + + override fun ShadowTLSBean.init() { + pbm.writeToCacheAll(this) + + } + + override fun ShadowTLSBean.serialize() { + pbm.fromCacheAll(this) + } + + override fun PreferenceFragmentCompat.createPreferences( + savedInstanceState: Bundle?, + rootKey: String?, + ) { + addPreferencesFromResource(R.xml.shadowtls_preferences) + pbm.setPreferenceFragment(this) + + serverPort.preference.apply { + this as EditTextPreference + setOnBindEditTextListener(EditTextPreferenceModifiers.Port) + } + password.preference.apply { + this as EditTextPreference + summaryProvider = PasswordSummaryProvider + } + } + +} diff --git a/app/src/main/res/menu/add_profile_menu.xml b/app/src/main/res/menu/add_profile_menu.xml index af2360e..52d264b 100644 --- a/app/src/main/res/menu/add_profile_menu.xml +++ b/app/src/main/res/menu/add_profile_menu.xml @@ -60,6 +60,9 @@ + diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 4750333..c48c746 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -193,20 +193,8 @@ Editar Compartir Añadir perfil - Seleccionar perfil - SOCKS - HTTP - Shadowsocks - ShadowsocksR - VMess - Trojan - Trojan Go - Naïve - Ping Tunnel - Hysteria - SSH - WireGuard - Cadena del proxy + Seleccionar perfil + Cadena del proxy Configuración personalizada Equilibrador Ajustes del equilibrador diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 6409c1c..dc61b1a 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -462,4 +462,8 @@ 日志级别 推广 重新启动应用程序以应用更改 + 启用 selector (免重载切换节点) + 前置代理 + 落地代理 + ShadowTLS 版本 \ No newline at end of file diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 99037dc..747124d 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -507,4 +507,9 @@ trace + + 2 + 3 + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6f8634a..ceef3fe 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -505,5 +505,7 @@ Anyone can write advanced plugins, which can control NekoBox. please download an Use selector Front proxy Landing Proxy + ShadowTLS + ShadowTLS Version \ No newline at end of file diff --git a/app/src/main/res/xml/shadowtls_preferences.xml b/app/src/main/res/xml/shadowtls_preferences.xml new file mode 100644 index 0000000..215c608 --- /dev/null +++ b/app/src/main/res/xml/shadowtls_preferences.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + +