mirror of
https://github.com/wanghongenpin/proxypin.git
synced 2026-04-05 08:25:08 +08:00
Optimize Android VPN
This commit is contained in:
@@ -7,6 +7,7 @@ import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.ProxyInfo
|
||||
import android.net.VpnService
|
||||
import android.os.Build
|
||||
import android.os.ParcelFileDescriptor
|
||||
@@ -232,9 +233,9 @@ class ProxyVpnService : VpnService(), ProtectSocket {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
setMetered(false)
|
||||
}
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
// setHttpProxy(ProxyInfo.buildDirectProxy(proxyHost, proxyPort))
|
||||
// }
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
setHttpProxy(ProxyInfo.buildDirectProxy(proxyHost, proxyPort))
|
||||
}
|
||||
}.establish()
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,10 @@ import com.network.proxy.vpn.util.ProcessInfoManager
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
/**
|
||||
* 进程信息插件
|
||||
@@ -27,13 +31,23 @@ class ProcessInfoPlugin : AndroidFlutterPlugin() {
|
||||
channel.setMethodCallHandler { call, result ->
|
||||
when (call.method) {
|
||||
"getProcessByPort" -> {
|
||||
// val host = call.argument<String>("host")
|
||||
val host = call.argument<String>("host")
|
||||
val port = call.argument<Int>("port")
|
||||
val appInfo = processInfoManager.getProcessInfoByPort(port!!)
|
||||
result.success(appInfo)
|
||||
if (port != null) {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
val appInfo = processInfoManager.getProcessInfoByPort(host, port)
|
||||
withContext(Dispatchers.Main) {
|
||||
result.success(appInfo)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result.error("INVALID_ARGUMENT", "Port is null", null)
|
||||
}
|
||||
}
|
||||
|
||||
else -> result.notImplemented()
|
||||
else -> {
|
||||
result.notImplemented()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,19 @@ import android.net.ConnectivityManager
|
||||
import android.os.Build
|
||||
import android.os.Process
|
||||
import android.system.OsConstants
|
||||
import android.util.Log
|
||||
import androidx.annotation.RequiresApi
|
||||
import com.network.proxy.ProxyVpnService
|
||||
import com.network.proxy.plugin.ProcessInfo
|
||||
import com.network.proxy.vpn.Connection
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import java.io.File
|
||||
import java.net.InetSocketAddress
|
||||
import java.nio.channels.SocketChannel
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
/**
|
||||
* 进程信息管理器,用于获取进程信息
|
||||
@@ -32,24 +40,24 @@ class ProcessInfoManager private constructor() {
|
||||
|
||||
var activity: Context? = null
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.N)
|
||||
fun setConnectionOwnerUid(connection: Connection) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
||||
return
|
||||
}
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
|
||||
val sourceAddress =
|
||||
InetSocketAddress(PacketUtil.intToIPAddress(connection.sourceIp), connection.sourcePort)
|
||||
val destinationAddress = InetSocketAddress(
|
||||
PacketUtil.intToIPAddress(connection.destinationIp), connection.destinationPort
|
||||
)
|
||||
val sourceAddress =
|
||||
InetSocketAddress(PacketUtil.intToIPAddress(connection.sourceIp), connection.sourcePort)
|
||||
val destinationAddress = InetSocketAddress(
|
||||
PacketUtil.intToIPAddress(connection.destinationIp), connection.destinationPort
|
||||
)
|
||||
|
||||
val uid = getProcessInfo(sourceAddress, destinationAddress)
|
||||
val channel = connection.channel
|
||||
if (uid != null && channel is SocketChannel) {
|
||||
val localAddress = channel.localAddress as InetSocketAddress
|
||||
val networkInfo =
|
||||
NetworkInfo(uid, destinationAddress.hostString, destinationAddress.port)
|
||||
localPortCache.put(localAddress.port, networkInfo)
|
||||
val uid = getProcessInfoUid(sourceAddress, destinationAddress)
|
||||
val channel = connection.channel
|
||||
if (uid != null && uid != Process.INVALID_UID && channel is SocketChannel) {
|
||||
val localAddress = channel.localAddress as InetSocketAddress
|
||||
val networkInfo =
|
||||
NetworkInfo(uid, destinationAddress.hostString, destinationAddress.port)
|
||||
localPortCache.put(localAddress.port, networkInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,8 +73,8 @@ class ProcessInfoManager private constructor() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun getProcessInfo(
|
||||
@RequiresApi(Build.VERSION_CODES.N)
|
||||
private fun getProcessInfoUid(
|
||||
localAddress: InetSocketAddress, remoteAddress: InetSocketAddress
|
||||
): Int? {
|
||||
// Log.d(TAG, "getProcessInfo: $localAddress $remoteAddress")
|
||||
@@ -74,11 +82,12 @@ class ProcessInfoManager private constructor() {
|
||||
if (activity == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
val connectivityManager: ConnectivityManager =
|
||||
activity!!.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
|
||||
val uid = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
connectivityManager.getConnectionOwnerUid(
|
||||
return connectivityManager.getConnectionOwnerUid(
|
||||
OsConstants.IPPROTO_TCP, localAddress, remoteAddress
|
||||
)
|
||||
} else {
|
||||
@@ -88,7 +97,7 @@ class ProcessInfoManager private constructor() {
|
||||
InetSocketAddress::class.java,
|
||||
InetSocketAddress::class.java
|
||||
)
|
||||
method.invoke(
|
||||
return method.invoke(
|
||||
connectivityManager, OsConstants.IPPROTO_TCP, localAddress, remoteAddress
|
||||
) as Int
|
||||
}
|
||||
@@ -96,10 +105,15 @@ class ProcessInfoManager private constructor() {
|
||||
if (uid != Process.INVALID_UID) {
|
||||
return uid
|
||||
}
|
||||
|
||||
Log.w(
|
||||
"ProcessInfoManager",
|
||||
"Failed to get UID for local address $localAddress and remote address $remoteAddress"
|
||||
)
|
||||
return null
|
||||
}
|
||||
|
||||
fun getProcessInfoByPort(localPort: Int): ProcessInfo? {
|
||||
suspend fun getProcessInfoByPort(host: String?, localPort: Int): ProcessInfo? {
|
||||
val networkInfo = localPortCache.get(localPort)
|
||||
if (networkInfo != null) {
|
||||
val processInfo = getProcessInfo(networkInfo.uid)
|
||||
@@ -109,6 +123,34 @@ class ProcessInfoManager private constructor() {
|
||||
put("remotePort", networkInfo.remotePort)
|
||||
}
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val localAddress = InetSocketAddress(host, localPort)
|
||||
val remoteAddress = InetSocketAddress(ProxyVpnService.host, ProxyVpnService.port)
|
||||
|
||||
val uid = getProcessInfoUid(localAddress, remoteAddress)
|
||||
|
||||
if (uid == null || uid == Process.INVALID_UID) {
|
||||
return@withContext null
|
||||
}
|
||||
|
||||
|
||||
val processInfo = getProcessInfo(uid)
|
||||
if (processInfo != null) {
|
||||
localPortCache.put(
|
||||
localPort, NetworkInfo(uid, remoteAddress.hostString, remoteAddress.port)
|
||||
)
|
||||
|
||||
return@withContext processInfo
|
||||
} else {
|
||||
Log.w("ProcessInfoManager", "No process info found for UID: $uid")
|
||||
null
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.w("ProcessInfoManager", "Access to /proc/net/tcp is restricted on non-rooted devices.")
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user