Add config override and per-app proxy feature

This commit is contained in:
iKirby
2023-07-27 22:17:25 +08:00
committed by 世界
parent af0046ce1c
commit 9575764f40
25 changed files with 1052 additions and 17 deletions

View File

@@ -0,0 +1,49 @@
package io.nekohasekai.sfa.bg
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
import io.nekohasekai.sfa.database.Settings
import io.nekohasekai.sfa.ui.configoverride.PerAppProxyActivity
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
class AppChangeReceiver : BroadcastReceiver() {
companion object {
private const val TAG = "AppChangeReceiver"
}
override fun onReceive(context: Context, intent: Intent) {
Log.d(TAG, "onReceive: ${intent.action}")
checkUpdate(context, intent)
}
private fun checkUpdate(context: Context, intent: Intent) {
if (!Settings.perAppProxyEnabled) {
Log.d(TAG, "per app proxy disabled")
return
}
val perAppProxyUpdateOnChange = Settings.perAppProxyUpdateOnChange
if (perAppProxyUpdateOnChange != Settings.PER_APP_PROXY_DISABLED) {
Log.d(TAG, "update on change disabled")
return
}
val packageName = intent.dataString?.substringAfter("package:")
if (packageName.isNullOrBlank()) {
Log.d(TAG, "missing package name in intent")
return
}
val isChinaApp = PerAppProxyActivity.scanChinaApps(listOf(packageName)).isNotEmpty()
Log.d(TAG, "scan china app result for $packageName: $isChinaApp")
if ((perAppProxyUpdateOnChange == Settings.PER_APP_PROXY_INCLUDE) xor !isChinaApp) {
Settings.perAppProxyList = Settings.perAppProxyList + packageName
Log.d(TAG, "added to list")
} else {
Settings.perAppProxyList = Settings.perAppProxyList - packageName
Log.d(TAG, "removed from list")
}
}
}

View File

@@ -39,12 +39,14 @@ class BoxService(
private var initializeOnce = false
private fun initialize() {
if (initializeOnce) return
val baseDir = Application.application.getExternalFilesDir(null) ?: return
val baseDir = Application.application.filesDir
baseDir.mkdirs()
val workingDir = Application.application.getExternalFilesDir(null) ?: return
workingDir.mkdirs()
val tempDir = Application.application.cacheDir
tempDir.mkdirs()
Libbox.setup(baseDir.path, baseDir.path, tempDir.path, false)
Libbox.redirectStderr(File(baseDir, "stderr.log").path)
Libbox.setup(baseDir.path, workingDir.path, tempDir.path, false)
Libbox.redirectStderr(File(workingDir, "stderr.log").path)
initializeOnce = true
return
}
@@ -65,6 +67,14 @@ class BoxService(
)
)
}
fun reload() {
Application.application.sendBroadcast(
Intent(Action.SERVICE_RELOAD).setPackage(
Application.application.packageName
)
)
}
}
var fileDescriptor: ParcelFileDescriptor? = null
@@ -82,6 +92,9 @@ class BoxService(
Action.SERVICE_CLOSE -> {
stopService()
}
Action.SERVICE_RELOAD -> {
serviceReload()
}
}
}
}
@@ -94,7 +107,6 @@ class BoxService(
}
private suspend fun startService() {
initialize()
try {
val selectedProfileId = Settings.selectedProfile
if (selectedProfileId == -1L) {
@@ -224,6 +236,7 @@ class BoxService(
if (!receiverRegistered) {
service.registerReceiver(receiver, IntentFilter().apply {
addAction(Action.SERVICE_CLOSE)
addAction(Action.SERVICE_RELOAD)
})
receiverRegistered = true
}
@@ -231,6 +244,7 @@ class BoxService(
notification.show()
GlobalScope.launch(Dispatchers.IO) {
Settings.startedByUser = true
initialize()
try {
startCommandServer()
} catch (e: Exception) {

View File

@@ -1,10 +1,12 @@
package io.nekohasekai.sfa.bg
import android.content.Intent
import android.content.pm.PackageManager.NameNotFoundException
import android.net.ProxyInfo
import android.net.VpnService
import android.os.Build
import io.nekohasekai.libbox.TunOptions
import io.nekohasekai.sfa.database.Settings
class VPNService : VpnService(), PlatformInterfaceWrapper {
@@ -80,17 +82,43 @@ class VPNService : VpnService(), PlatformInterfaceWrapper {
builder.addRoute("::", 0)
}
val includePackage = options.includePackage
if (includePackage.hasNext()) {
while (includePackage.hasNext()) {
builder.addAllowedApplication(includePackage.next())
if (Settings.perAppProxyEnabled) {
val appList = Settings.perAppProxyList
if (Settings.perAppProxyMode == Settings.PER_APP_PROXY_INCLUDE) {
appList.forEach {
try {
builder.addAllowedApplication(it)
} catch (_: NameNotFoundException) {
}
}
builder.addAllowedApplication(packageName)
} else {
appList.forEach {
try {
builder.addDisallowedApplication(it)
} catch (_: NameNotFoundException) {
}
}
}
} else {
val includePackage = options.includePackage
if (includePackage.hasNext()) {
while (includePackage.hasNext()) {
try {
builder.addAllowedApplication(includePackage.next())
} catch (_: NameNotFoundException) {
}
}
}
}
val excludePackage = options.excludePackage
if (excludePackage.hasNext()) {
while (excludePackage.hasNext()) {
builder.addDisallowedApplication(excludePackage.next())
val excludePackage = options.excludePackage
if (excludePackage.hasNext()) {
while (excludePackage.hasNext()) {
try {
builder.addDisallowedApplication(excludePackage.next())
} catch (_: NameNotFoundException) {
}
}
}
}
}