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连接相关的通知栏和对话框中显示出来;

微信公众号搜索 “ 程序精选 ” ,选择关注!
精选程序员所需精品干货内容!