Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions core/src/main/java/com/github/shadowsocks/bg/ProxyInstance.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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 ?: "")) }

Expand All @@ -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 {
Expand All @@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -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
}
}
7 changes: 7 additions & 0 deletions core/src/main/java/com/github/shadowsocks/bg/VpnService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down
2 changes: 2 additions & 0 deletions core/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
<string name="port_proxy">SOCKS5 proxy port</string>
<string name="port_local_dns">Local DNS port</string>
<string name="port_transproxy">Transproxy port</string>
<string name="socks5_proxy_password">SOCKS5 proxy password</string>
<string name="socks5_proxy_password_summary">Set a password to protect the local SOCKS5 proxy from unauthorized use</string>

<string name="remote_dns">Remote DNS</string>
<string name="traffic">%1$s↑\t%2$s↓</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class GlobalSettingsPreferenceFragment : PreferenceFragmentCompat() {
portLocalDns.setOnBindEditTextListener(EditTextPreferenceModifiers.Port)
val portTransproxy = findPreference<EditTextPreference>(Key.portTransproxy)!!
portTransproxy.setOnBindEditTextListener(EditTextPreferenceModifiers.Port)
val socksPassword = findPreference<EditTextPreference>(Key.socksPassword)!!
val onServiceModeChange = Preference.OnPreferenceChangeListener { _, newValue ->
portTransproxy.isEnabled = newValue as String? == Key.modeTransproxy
true
Expand All @@ -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
}
Expand Down
6 changes: 6 additions & 0 deletions mobile/src/main/res/xml/pref_global.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,10 @@
app:key="portTransproxy"
app:title="@string/port_transproxy"
app:useSimpleSummaryProvider="true"/>
<EditTextPreference
app:dialogLayout="@layout/preference_dialog_password"
app:key="socksPassword"
app:icon="@drawable/ic_settings_password"
app:title="@string/socks5_proxy_password"
app:summary="@string/socks5_proxy_password_summary"/>
</PreferenceScreen>
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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<Preference>(Key.about)!!.summary = getString(R.string.about_title, BuildConfig.VERSION_NAME)

Expand Down
5 changes: 5 additions & 0 deletions tv/src/main/res/xml/pref_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@
app:key="portTransproxy"
app:title="@string/port_transproxy"
app:useSimpleSummaryProvider="true"/>
<EditTextPreference
app:key="socksPassword"
app:title="@string/socks5_proxy_password"
app:summary="@string/socks5_proxy_password_summary"
app:useSimpleSummaryProvider="false"/>
</PreferenceCategory>

<Preference
Expand Down