diff --git a/core/src/main/java/com/github/shadowsocks/bg/ProxyInstance.kt b/core/src/main/java/com/github/shadowsocks/bg/ProxyInstance.kt index 4882a3fe58..c032df80e2 100644 --- a/core/src/main/java/com/github/shadowsocks/bg/ProxyInstance.kt +++ b/core/src/main/java/com/github/shadowsocks/bg/ProxyInstance.kt @@ -64,6 +64,7 @@ class ProxyInstance(val profile: Profile, private val route: String = profile.ro } private var configFile: File? = null + private var socks5AuthFile: File? = null var trafficMonitor: TrafficMonitor? = null val plugin by lazy { PluginManager.init(PluginConfiguration(profile.plugin ?: "")) } @@ -86,6 +87,7 @@ class ProxyInstance(val profile: Profile, private val route: String = profile.ro } config.put("dns", "unix://local_dns_path") config.put("mode", mode) + val socksPassword = DataStore.socksPassword config.put("locals", JSONArray().apply { // local SOCKS5 proxy put(JSONObject().apply { @@ -94,6 +96,7 @@ class ProxyInstance(val profile: Profile, private val route: String = profile.ro put("local_udp_address", DataStore.listenAddress) put("local_udp_port", DataStore.portProxy) put("mode", mode) + if (socksPassword.isNotEmpty()) put("socks5_auth_config_path", "socks5_auth") }) // local DNS proxy @@ -114,6 +117,22 @@ class ProxyInstance(val profile: Profile, private val route: String = profile.ro }) configFile.writeText(config.toString()) + // write SOCKS5 auth config file if password protection is enabled + if (socksPassword.isNotEmpty()) { + val authFile = File(configFile.parentFile ?: configFile.canonicalFile.parentFile, "socks5_auth") + socks5AuthFile = authFile + authFile.writeText(JSONObject().apply { + put("password", JSONObject().apply { + put("users", JSONArray().apply { + put(JSONObject().apply { + put("user_name", "shadowsocks") + put("password", socksPassword) + }) + }) + }) + }.toString()) + } + // build the command line val cmd = arrayListOf( File((service as Context).applicationInfo.nativeLibraryDir, Executable.SS_LOCAL).absolutePath, @@ -143,5 +162,7 @@ class ProxyInstance(val profile: Profile, private val route: String = profile.ro trafficMonitor = null configFile?.delete() // remove old config possibly in device storage configFile = null + socks5AuthFile?.delete() + socks5AuthFile = null } } diff --git a/core/src/main/java/com/github/shadowsocks/bg/VpnService.kt b/core/src/main/java/com/github/shadowsocks/bg/VpnService.kt index 5716d1fc09..17c58d7020 100644 --- a/core/src/main/java/com/github/shadowsocks/bg/VpnService.kt +++ b/core/src/main/java/com/github/shadowsocks/bg/VpnService.kt @@ -214,6 +214,13 @@ class VpnService : BaseVpnService(), BaseService.Interface { "--sock-path", "sock_path", "--dnsgw", "127.0.0.1:${DataStore.portLocalDns}", "--loglevel", "warning") + val socksPassword = DataStore.socksPassword + if (socksPassword.isNotEmpty()) { + cmd += "--username" + cmd += "shadowsocks" + cmd += "--password" + cmd += socksPassword + } if (profile.ipv6) { cmd += "--netif-ip6addr" cmd += PRIVATE_VLAN6_ROUTER diff --git a/core/src/main/java/com/github/shadowsocks/preference/DataStore.kt b/core/src/main/java/com/github/shadowsocks/preference/DataStore.kt index 5f3a772bf4..44dac24343 100644 --- a/core/src/main/java/com/github/shadowsocks/preference/DataStore.kt +++ b/core/src/main/java/com/github/shadowsocks/preference/DataStore.kt @@ -76,6 +76,9 @@ object DataStore : OnPreferenceDataStoreChangeListener { var portTransproxy: Int get() = getLocalPort(Key.portTransproxy, 8200) set(value) = publicStore.putString(Key.portTransproxy, value.toString()) + var socksPassword: String + get() = publicStore.getString(Key.socksPassword) ?: "" + set(value) = publicStore.putString(Key.socksPassword, value) /** * Initialize settings that have complicated default values. diff --git a/core/src/main/java/com/github/shadowsocks/utils/Constants.kt b/core/src/main/java/com/github/shadowsocks/utils/Constants.kt index 52b6de20ec..0644672ad3 100644 --- a/core/src/main/java/com/github/shadowsocks/utils/Constants.kt +++ b/core/src/main/java/com/github/shadowsocks/utils/Constants.kt @@ -40,6 +40,7 @@ object Key { const val portProxy = "portProxy" const val portLocalDns = "portLocalDns" const val portTransproxy = "portTransproxy" + const val socksPassword = "socksPassword" const val route = "route" diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 04ed7d9d67..87071c002e 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -14,6 +14,8 @@ SOCKS5 proxy port Local DNS port Transproxy port + SOCKS5 proxy password + Set a password to protect the local SOCKS5 proxy from unauthorized use Remote DNS %1$s↑\t%2$s↓ diff --git a/mobile/src/main/java/com/github/shadowsocks/GlobalSettingsPreferenceFragment.kt b/mobile/src/main/java/com/github/shadowsocks/GlobalSettingsPreferenceFragment.kt index cc7ac91647..2b503a6696 100644 --- a/mobile/src/main/java/com/github/shadowsocks/GlobalSettingsPreferenceFragment.kt +++ b/mobile/src/main/java/com/github/shadowsocks/GlobalSettingsPreferenceFragment.kt @@ -59,6 +59,7 @@ class GlobalSettingsPreferenceFragment : PreferenceFragmentCompat() { portLocalDns.setOnBindEditTextListener(EditTextPreferenceModifiers.Port) val portTransproxy = findPreference(Key.portTransproxy)!! portTransproxy.setOnBindEditTextListener(EditTextPreferenceModifiers.Port) + val socksPassword = findPreference(Key.socksPassword)!! val onServiceModeChange = Preference.OnPreferenceChangeListener { _, newValue -> portTransproxy.isEnabled = newValue as String? == Key.modeTransproxy true @@ -68,6 +69,7 @@ class GlobalSettingsPreferenceFragment : PreferenceFragmentCompat() { serviceMode.isEnabled = stopped portProxy.isEnabled = stopped portLocalDns.isEnabled = stopped + socksPassword.isEnabled = stopped if (stopped) onServiceModeChange.onPreferenceChange(serviceMode, DataStore.serviceMode) else { portTransproxy.isEnabled = false } diff --git a/mobile/src/main/res/xml/pref_global.xml b/mobile/src/main/res/xml/pref_global.xml index 9a4808d8b3..29b3369332 100644 --- a/mobile/src/main/res/xml/pref_global.xml +++ b/mobile/src/main/res/xml/pref_global.xml @@ -34,4 +34,10 @@ app:key="portTransproxy" app:title="@string/port_transproxy" app:useSimpleSummaryProvider="true"/> + diff --git a/tv/src/main/java/com/github/shadowsocks/tv/MainPreferenceFragment.kt b/tv/src/main/java/com/github/shadowsocks/tv/MainPreferenceFragment.kt index 198245f728..46a26c548a 100644 --- a/tv/src/main/java/com/github/shadowsocks/tv/MainPreferenceFragment.kt +++ b/tv/src/main/java/com/github/shadowsocks/tv/MainPreferenceFragment.kt @@ -56,6 +56,7 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo private lateinit var portProxy: EditTextPreference private lateinit var portLocalDns: EditTextPreference private lateinit var portTransproxy: EditTextPreference + private lateinit var socksPassword: EditTextPreference private val onServiceModeChange = Preference.OnPreferenceChangeListener { _, newValue -> portTransproxy.isEnabled = newValue as String? == Key.modeTransproxy true @@ -101,6 +102,7 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo shareOverLan.isEnabled = stopped portProxy.isEnabled = stopped portLocalDns.isEnabled = stopped + socksPassword.isEnabled = stopped if (stopped) onServiceModeChange.onPreferenceChange(serviceMode, DataStore.serviceMode) else { portTransproxy.isEnabled = false } @@ -141,6 +143,7 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo portLocalDns.setOnBindEditTextListener(EditTextPreferenceModifiers.Port) portTransproxy = findPreference(Key.portTransproxy)!! portTransproxy.setOnBindEditTextListener(EditTextPreferenceModifiers.Port) + socksPassword = findPreference(Key.socksPassword)!! serviceMode.onPreferenceChangeListener = onServiceModeChange findPreference(Key.about)!!.summary = getString(R.string.about_title, BuildConfig.VERSION_NAME) diff --git a/tv/src/main/res/xml/pref_main.xml b/tv/src/main/res/xml/pref_main.xml index 1e60152712..67e8dc963d 100644 --- a/tv/src/main/res/xml/pref_main.xml +++ b/tv/src/main/res/xml/pref_main.xml @@ -48,6 +48,11 @@ app:key="portTransproxy" app:title="@string/port_transproxy" app:useSimpleSummaryProvider="true"/> +