简体   繁体   English

某些应用程序如何阻止其他应用程序访问 WiFi/mobile.networks?

[英]How do some apps block others from reaching WiFi/mobile-networks?

Background背景

I've noticed various firewall apps on the Play Store being able to let the user choose which apps are allowed to use Wi-Fi and/or mobile.network for Inte.net connection.我注意到 Play Store 上的各种防火墙应用程序能够让用户选择允许哪些应用程序使用 Wi-Fi 和/或 mobile.network 进行 Inte.net 连接。 These app use VPN to have the control they need.这些应用程序使用 VPN 来获得所需的控制权。

An example for this is Xproguard Firewall: Xproguard 防火墙就是一个例子:

https://play.google.com/store/apps/details?id=com.xproguard.firewall https://play.google.com/store/apps/details?id=com.xproguard.firewall

The problem问题

I want to try to make something similar.我想尝试做类似的东西。 For this, I sadly can't find much material on the web, and actually found various unanswered questions even here on StackOverflow.为此,我很遗憾在 web 上找不到太多资料,实际上什至在 StackOverflow 上也发现了各种未解决的问题。

What I've found and tried我发现并尝试过的

I've found a sample called "ToyVpn" ( here ), but it seems much more complex than what I wanted, and I'm not even sure it can do what I'm trying to do.我找到了一个名为“ToyVpn”的示例( 此处),但它似乎比我想要的要复杂得多,而且我什至不确定它能否完成我想做的事情。

So I tried something from scratch.所以我从头开始尝试了一些东西。 I've succeeded to have a working VPN (or at least so it seems).我已经成功地拥有了一个可用的 VPN(或者至少看起来是这样)。 I took Google Chrome as the app to block, because it's easy to test it and because I can see that the firewall app also succeeded to block it.我将谷歌浏览器作为要阻止的应用程序,因为它很容易测试,而且我可以看到防火墙应用程序也成功阻止了它。 This is what I got:这就是我得到的:

manifest显现

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission
        android:name="android.permission.QUERY_ALL_PACKAGES"
        tools:ignore="QueryAllPackagesPermission" />

    <application
        android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true" android:theme="@style/Theme.Firewall" tools:targetApi="31">
        <activity
            android:name=".MainActivity" android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".MyVpnService" android:exported="true"
            android:permission="android.permission.BIND_VPN_SERVICE">
            <intent-filter>
                <action android:name="android.net.VpnService" />
            </intent-filter>
        </service>
    </application>

</manifest>

MainActivity.kt主活动.kt

class MainActivity : AppCompatActivity() {
    private val requestVpn =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
            if (it.resultCode == RESULT_OK)
                startService(Intent(this, MyVpnService::class.java))
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val vpnIntent = VpnService.prepare(this@MainActivity)
        if (vpnIntent != null)
            requestVpn.launch(vpnIntent)
        else
            startService(Intent(this, MyVpnService::class.java))
    }
}

MyVpnService.kt MyVpnService.kt

class MyVpnService : VpnService() {
    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        val builder = Builder()
        builder.setSession("MyVPNService")
            .addAddress("192.168.0.1", 24)
            .addDnsServer("8.8.8.8")
            .addRoute("0.0.0.0", 0)
            .addDisallowedApplication("com.android.chrome")
            .establish()
        return START_STICKY
    }
}

Another alternative I've found requires root, and can be done even in a batch file:我发现的另一种选择需要 root,甚至可以在批处理文件中完成:

set package_name="com.android.browser"
for /f "delims=" %%A in ('adb shell dumpsys package %package_name% ^| findstr "userId="') do (
  for /f "tokens=2 delims== " %%B in ("%%A") do (
    echo Extracted UID: %%B
    adb shell "su -c 'iptables -A OUTPUT -m owner --uid-owner %%B -j DROP'"
  )
)

For un-blocking, replace the "-A OUTPUT" with "-D OUTPUT".要取消阻塞,请将“-A OUTPUT”替换为“-D OUTPUT”。

To check the status, you can use this:要检查状态,您可以使用:

set package_name="com.android.browser"
for /f "delims=" %%A in ('adb shell dumpsys package %package_name% ^| findstr "userId="') do (
  for /f "tokens=2 delims== " %%B in ("%%A") do (
    set uid=%%B
    echo Extracted UID: %%B
    adb shell "su -c 'iptables -L OUTPUT -v -n --line-numbers | grep \"owner UID match %%B\"'"
  )
)

pause

This works well, but I want to know how it's done in apps that don't require root.这很好用,但我想知道它在不需要 root 的应用程序中是如何完成的。

The questions问题

  1. Is this the right way to create and maintain a VPN service?这是创建和维护 VPN 服务的正确方法吗?
  2. The current code doesn't really block apps.当前代码并没有真正阻止应用程序。 What would it take to block other apps?阻止其他应用程序需要什么? It seems I need to do something with the builder's generated instance, but I couldn't find what.似乎我需要对构建器生成的实例做些什么,但我找不到什么。
  3. How would I be able to set the type of communication to block: Wi-Fi and/or mobile-data, just like on other firewall apps?我如何才能设置要阻止的通信类型:Wi-Fi 和/或移动数据,就像其他防火墙应用程序一样?

You can review the source code for the the given app, https://github.com/M66B/NetGuard .您可以查看给定应用程序的源代码, https://github.com/M66B/NetGuard This app does not require a rooted device, also what you are trying to achieve is a complicated topic, you will need to learn proper.networking concepts along with how android communicates with the.network in order to block them.这个应用程序不需要有根设备,而且你想要实现的是一个复杂的主题,你需要学习适当的网络概念以及 android 如何与网络通信以阻止它们。 The source code may give you some insights on how to achieve the functionality.源代码可能会给您一些关于如何实现功能的见解。

import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.os.Build
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

private lateinit var connectivityManager: ConnectivityManager

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

    // Block other apps from network access
    blockNetworkAccess()
}

private fun blockNetworkAccess() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        // Get the currently active network
        val activeNetwork = connectivityManager.activeNetwork

        // Create a NetworkRequest and set the necessary capabilities
        val networkRequest = NetworkCapabilities.Builder()
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            .build()

        // Register a network callback to monitor the active network
        connectivityManager.registerNetworkCallback(
            networkRequest,
            object : ConnectivityManager.NetworkCallback() {
                override fun onCapabilitiesChanged(
                    network: Network,
                    networkCapabilities: NetworkCapabilities
                ) {
                    // Block network access for the active network
                    if (network == activeNetwork) {
                        if (!networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
                            // App blocked from network access
                            // Perform necessary actions
                        }
                    }
                }
            }
        )
    }
}
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM