Android如何利用VpnService来抓包

概要

首先需要说明一下Android的VpnService是个什么东西。按照google官方的文档来说就是:

Android 包含一个内置的(PPTP 和 L2TP/IPSec)VPN 客户端,有时称为旧版 VPN。Android 4.0(API 级别 14)引入了 API,以便应用开发者可以提供自己的 VPN 解决方案。

并且有一张图片可以清晰地描述整体架构:

vpn-app-arch.jpg

通过这张图可以看出在未使用VpnService的情况下,App会走系统网络来进行各种网络通信。而在使用VpnService的情况下,IP层网络通信传输的包将经由本地的虚拟通道交由VpnService来处理,这样一来我们便可以捕获这些数据从而达到抓包的目的。

一些比较重要的API

addAddress(InetAddress address, int prefixLength)

至今还没有完全理解这个API的意义。按照google的文档来说就是:

Add a network address to the VPN interface. Both IPv4 and IPv6 addresses are supported. At least one address must be set before calling establish(). Adding an address implicitly allows traffic from that address family (i.e., IPv4 or IPv6) to be routed over the VPN.

看起来像是添加一个虚拟IP地址的意思,然而按照教程中的描述则为:

添加至少一个 IPv4 或 IPv6 地址以及系统指定为本地 TUN 接口地址的子网掩码。您的应用通常会在握手过程中收到来自 VPN 网关的 IP 地址和子网掩码。

参数变成了子网掩码,但是按照实际的使用来看更偏向于第一种。

addRoute(InetAddress address, int prefixLength)

添加路由来过滤发送特定IP地址的流量,如果不进行任何过滤则需要设置为0.0.0.0/0或::/0

addDnsServer(InetAddress address)

添加DNS服务器的地址,如果不添加的话将使用手机默认的DNS服务器。

addDisallowedApplication(String packageName)

添加白名单,白名单中的app的流量将不会经过vpn虚拟通道而直接走系统网络。

setBlocking(boolean blocking)

设置是否为阻塞模式,默认为非阻塞。个人感觉很重要的API,github上的很多项目没有设置为阻塞导致具体实现的时候用的都是线程轮询的方式,这一样一来大大提升了系统的开销。设置为阻塞模式后将大大减少进程上下文的切换。

setMtu(int mtu)

设置虚拟通道的最大传输字节数,需要根据具体情况具体分析。在抓包的场景下最好尽可能得设置大一些。

allowBypass()

简单来说是否允许一些app在使用一些非主流的方式访问网络的情况下不走虚拟通道。个人觉得最好允许。

大概思路

VpnService启动后创建Builder进行各种初始化,结束后调用establish()获得本地虚拟通道的文件描述符(mFD)。通过输入流读取需要发送IP数据包后解析包的解析(网上有各种第三方的库可供选择)。首先判断是版本是IPV4还是IPV6,之后根据不同的版本来判断使用的是什么协议。
实际抓包的时候可以看到很多协议种类,当然主要的还是UDP与TCP。

UDP的情况

可以创建一个稀疏数组,key为源端口,value为Datagram通道,通过Datagram通道向外发送UDP数据,从而减少系统开销。最终通过Datagram通道拿到UDP响应数据后写入mFD的输出流。

TCP的情况

TCP的情况比较麻烦,涉及到三次握手以及四次分手,在github上看到个人感觉比较好的做法是,本地建立一个代理服务器来模拟这个过程。这个还需要深入研究。

一些补充

套接字在发送之前一定要调用protect来防止循环链接,否则发出去的包又回回到mFD的输入流造成死循环。

boolean protect (int socket)

另外mFD如果不关闭的话是没办法停止VpnService的。

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
img
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓(文末还有ChatGPT机器人小福利哦,大家千万不要错过)

PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题

图片

  • 22
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现 SSTP VPN 可以使用 Android 中的 VPNService 类。以下是实现步骤: 1. 首先,需要在 AndroidManifest.xml 文件中声明 VPNService 的服务。 ``` <service android:name=".SstpVpnService" android:permission="android.permission.BIND_VPN_SERVICE" android:exported="false"> </service> ``` 2. 创建 SstpVpnService 类并继承 VPNService 类,实现必要的方法。 ``` public class SstpVpnService extends VpnService { // 实现必要的方法 } ``` 3. 在 onCreate() 方法中,创建一个 Builder 对象并设置 VPN 的配置。 ``` @Override public void onCreate() { super.onCreate(); Builder builder = new Builder(); builder.setSession("SSTP VPN"); builder.setMtu(1400); builder.addAddress("10.0.0.2", 24); builder.addRoute("0.0.0.0", 0); builder.addDnsServer("8.8.8.8"); builder.setBlocking(true); builder.setUnderlyingNetworks(null); builder.setConfigureIntent(null); try { mInterface = builder.establish(); } catch (Exception e) { e.printStackTrace(); } } ``` 4. 实现 onRevoke() 方法,在 VPN 被撤销时进行清理工作。 ``` @Override public void onRevoke() { super.onRevoke(); if (mInterface != null) { try { mInterface.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` 5. 在 onStartCommand() 方法中,启动 VPN。 ``` @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; } ``` 6. 最后,在应用程序中启动 SSTP VPN 服务。 ``` Intent vpnIntent = VpnService.prepare(this); if (vpnIntent != null) { startActivityForResult(vpnIntent, VPN_REQUEST_CODE); } else { startVpnService(); } ``` 这样,就可以在 Android 应用程序中实现 SSTP VPN 服务。需要注意的是,SSTP VPN 协议是基于 SSL/TLS 的,需要使用 SSL/TLS 协议进行加密。在实现过程中,需要配置 SSL/TLS 相关的参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值