Skip to content
返回

安卓开发 VpnService 使用,完成 TCP 和 UDP 协议(抓包)

Published:  at  23:13

一、原理分析

访问百度(https://www.baidu.com)的过程:

  1. 发送 UDP 请求,解析域名 www.baidu.com,获取 IP 地址;
  2. 使用 TCP 协议与该 IP 建立连接,获取网页数据。

在 Android 中通过 VpnService 拦截所有网络数据,分析其 TCP 和 UDP 数据包并实现抓包。

打开Wireshark选择以太网抓包,通过CMD执行下面命令

# 清空dns缓存
ipconfig /flushdns 
# 解析百度域名IP
ping www.baidu.com
# curl请求百度
curl https://www.baidu.com

dns tcp

数据包结构概览

在网络传输中:

VpnService 拿到的数据是 从 IP 层开始,没有以太网帧,因此我们只需解析 IP 数据包即可。

工作流程简述

从虚拟网卡读取数据:


二、TCP 协议要点

TCP 是面向连接、可靠、有序的协议,基于字节流。其主要过程:

三次握手

  1. 客户端发送 SYN
  2. 服务端回复 SYN + ACK
  3. 客户端回复 ACK,连接建立完成。

四次挥手

  1. 客户端发送 FIN
  2. 服务端回复 ACK
  3. 服务端发送 FIN
  4. 客户端回复 ACK,连接关闭。

我们需要处理的:


三、UDP 协议要点

UDP 是无连接、不可靠的协议:


四、VpnService 使用

VpnService 是 Android 提供的类,用于创建一个虚拟的网络接口。

官方文档

1. 权限与 Service 注册

AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

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

2. 启动/停止 VPN

MyVpnService.java 核心实现:

public class MyVpnService extends VpnService {
    private ParcelFileDescriptor descriptor;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        switch (intent.getStringExtra("status")) {
            case "start": setupVpn(); break;
            case "stop": stopVpn(); break;
        }
        return START_STICKY;
    }

    private synchronized void stopVpn() {
        try {
            if (descriptor != null) descriptor.close();
        } catch (IOException ignored) {}
        finally {
            descriptor = null;
            sendStatusUpdate("stop");
            stopSelf();
        }
    }

    private synchronized void setupVpn() {
        if (descriptor != null) return;
        try {
            descriptor = new Builder()
                .addAddress("10.0.0.1", 32)
                .addRoute("0.0.0.0", 0)
                .addDnsServer("114.114.114.114")
                .addAllowedApplication(getPackageName())
                .addAllowedApplication("com.android.browser")
                .establish();
            sendStatusUpdate("start");
        } catch (Exception e) {
            throw new RuntimeException("VPN setup failed", e);
        }
    }

    private void sendStatusUpdate(String status) {
        LocalBroadcastManager.getInstance(this)
            .sendBroadcast(new Intent("com.example.UPDATE_TEXT")
                .putExtra("status", status));
    }
}

3. 权限请求和 UI 控制

MainActivity.java 核心代码:

private void setupVpnLauncher() {
    vpnLauncher = registerForActivityResult(
        new ActivityResultContracts.StartActivityForResult(),
        result -> {
            if (result.getResultCode() == Activity.RESULT_OK) {
                startVpnService();
            } else {
                ((Switch)findViewById(R.id.vpnSwitch)).setChecked(false);
                appendOutput("VPN权限被拒绝");
            }
        });
}

private void handleVpnToggle(boolean isChecked) {
    Intent intent = VpnService.prepare(this);
    if (isChecked) {
        if (intent != null) vpnLauncher.launch(intent);
        else startVpnService();
    } else {
        stopVpnService();
    }
}

private void startVpnService() {
    vpnIntent = new Intent(this, MyVpnService.class).putExtra("status", "start");
    startService(vpnIntent);
}

private void stopVpnService() {
    if (vpnIntent != null) {
        startService(vpnIntent.putExtra("status", "stop"));
    }
}

五、数据包解析:使用 PCAP4J

1. 添加依赖

libs.versions.toml

[libraries]
pcap4j-core = { group = "org.pcap4j", name = "pcap4j-core", version.ref = "pcap4j" }
pcap4j-packetfactory = { group = "org.pcap4j", name = "pcap4j-packetfactory-static", version.ref = "pcap4j" }

build.gradle.kts

dependencies {
    implementation(libs.pcap4j.core)
    implementation(libs.pcap4j.packetfactory)
}

六、完整示例代码

项目地址:https://github.com/aLavaGolem/vpnservice-learn


七、总结



上一篇
Android 无障碍开发基础配置
下一篇
OpenWrt 安装 Passwall2 详细教程