You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

非Root环境下基于VPN实现APP网络拦截的开发技术咨询

非Root环境下Android防火墙应用开发疑问

背景

Play商店中有多款防火墙应用支持用户选择允许哪些APP使用Wi-Fi或移动网络,这类应用通过VPN技术实现网络管控。

已尝试内容

  1. VPN服务实现尝试
    我参考了ToyVpn示例但觉得过于复杂,于是从零编写代码搭建了一个VPN服务,选择Google Chrome作为测试拦截对象,但无法实现拦截效果。相关代码如下:

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

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

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
    }
}
  1. Root权限下的iptables实现
    找到了一种需要Root权限的实现方式,通过批处理文件完成APP网络拦截:
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'"
  )
)

取消拦截时,将-A OUTPUT替换为-D OUTPUT;查看拦截状态可使用:

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

该方式有效,但我需要非Root环境下的实现方案。

技术疑问

  • 当前创建和维护VPN服务的方式是否正确?
  • 当前代码无法实现APP网络拦截,需进行哪些修改才能达成目标?
  • 如何像主流防火墙应用一样,设置拦截Wi-Fi或移动数据的网络类型?

内容的提问来源于stack exchange,提问作者android developer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 19:37:03