Android系统自带的VPN服务框架实例详解
Android系统自带的VPN服务框架
Android从4.0开始(API LEVEL 15),自己带了一个帮助在设备上建立VPN连接的解决方案,且不需要root权限,本文将对其做一个简单的介绍。
一、基本原理
在介绍如何使用这些新增的API之前,先来说说其基本的原理。
android设备上,如果已经使用了VpnService框架,建立起了一条从设备到远端的VPN链接,那么数据包在设备上大致经历了如下四个过程的转换:
VpnService.prepare函数的目的,主要是用来检查当前系统中是不是已经存在一个VPN连接了,如果有了的话,是不是就是本程序创建的。
如果当前系统中没有VPN连接,或者存在的VPN连接不是本程序建立的,则VpnService.prepare函数会返回一个intent。这个intent就是用来触发确认对话框的,程序会接着调用startActivityForResult将对话框弹出来等用户确认。如果用户确认了,则会关闭前面已经建立的VPN连接,并重置虚拟端口。该对话框返回的时候,会调用onActivityResult函数,并告之用户的选择。
如果当前系统中有VPN连接,并且这个连接就是本程序建立的,则函数会返回null,就不需要用户再确认了。因为用户在本程序第一次建立VPN连接的时候已经确认过了,就不要再重复确认了,直接手动调用onActivityResult函数就行了。
在onActivityResult函数中,处理相对简单:
protected void onActivityResult(int request,int result,Intent data) { if (result == RESULT_OK) { Intent intent = new Intent(this,MyVpnService.class); ... startService(intent); } }
如果返回结果是OK的,也就是用户同意建立VPN连接,则将你写的,继承自VpnService类的服务启动起来就行了。
当然,你也可以通过intent传递一些别的参数。
服务程序实现
服务程序必须要继承自android.NET.VpnService类:
public class MyVpnService extends VpnService ...
VpnService类封装了建立VPN连接所必须的所有函数,后面会逐步用到。
建立链接的第一步是要用合适的参数,创建并初始化好tun0虚拟网络端口,这可以通过在VpnService类中的一个内部类Builder来做到:
Builder builder = new Builder(); builder.setMtu(...); builder.addAddress(...); builder.addRoute(...); builder.addDnsServer(...); builder.addSearchDomain(...); builder.setSession(...); builder.setConfigureIntent(...); ParcelFileDescriptor interface = builder.establish();
可以看到,这里使用了标准的Builder设计模式。在正式建立(establish)虚拟网络接口之前,需要设置好几个参数,分别是:
1)MTU(Maximun Transmission Unit),即表示虚拟网络端口的最大传输单元,如果发送的包长度超过这个数字,则会被分包;
2)Address,即这个虚拟网络端口的IP地址;
3)Route,只有匹配上的IP包,才会被路由到虚拟端口上去。如果是0.0.0.0/0的话,则会将所有的IP包都路由到虚拟端口上去;
4)DNS Server,就是该端口的DNS服务器地址;
5)Search Domain,就是添加DNS域名的自动补齐。DNS服务器必须通过全域名进行搜索,但每次查找都输入全域名太麻烦了,可以通过配置域名的自动补齐规则予以简化;
6)Session,就是你要建立的VPN连接的名字,它将会在系统管理的与VPN连接相关的通知栏和对话框中显示出来;
微信公众号搜索 “ 程序精选 ” ,选择关注!
精选程序员所需精品干货内容!