iOS开发使用NetworkExtension框架编写VPN应用
最近闲来无聊,想自己做个ios平台代理上网的应用,最直接的方式就是通过VPN了,刚好iOS对VPN有很好的支持。于是花点时间查了下iOS的官方开发文档,顺便学习一下这种相关框架(NetworkExtension)的使用,也算是对知识点的查漏补缺了。
苹果是从iOS 8开始,才开放了新的框架 NetworkExtension ,该框架提供了配置和控制VPN支持和wifi热点相关的接口。通过该框架,我们可以很方便的实现VPN以及wifi热点相应的功能。接下来,我将介绍如何使用该框架实现一个简单的VPN功能。
在平常的iOS开发当中,VPN功能作为Capabilities中的一项,需要我们手动去工程的Capabilities中配置且打开。如下图所示:
注:<small>相关的AppID以及开发证书(或者发布证书)需要在苹果开发者中心里面开启该项功能,即在相应的App Id里面 edit id ---> 确保Personal VPN前面的复选框被选中!</small>
屏幕快照 2017-05-02 下午2.52.12.png
下面开始代码实现,关于VPN的种类以及不同种类之间的差异和优缺点,大家请自行谷歌百度之,这里不再作过多的赘述。需要注意的是早在iOS10,苹果就去掉了PPTP的vpn连接方式(而MacOs是在EiCapitain出来之后去掉的)。以下,我仅介绍其中一种VPN连接方式---IKEV2[1]。
首先引入相关框架:
@import NetworkExtension
打开应用需要检测之前安装了VPN描述文件(profile):
NEVPNManager *manager = [NEVPNManager sharedManager];
[manager loadFromPreferencesWithCompletionHandler:^(NSError * _Nullable error) {
if(error) {
NSLog(@"Load error: %@", error);
} else {
// No errors! The rest of your codes goes here..
NEVPNProtocolIKEv2* ikev = [[NEVPNProtocolIKEv2 alloc] init];
ikev.certificateType = NEVPNIKEv2CertificateTypeRSA;
ikev.authenticationMethod = NEVPNIKEAuthenticationMethodCertificate;
ikev.useExtendedAuthentication = YES;
ikev.username = _wzUsername;
ikev.passwordReference = 使用iOS钥匙串(keyChain)存入的密码;
ikev.serverAddress = @"**. **. **. **";
ikev.remoteIdentifier = @"***";
ikev.identityReference = 使用iOS钥匙串(keyChain)存入的identity;
[manager setEnabled:YES];
[manager setProtocol:ikev];
[manager setOnDemandEnabled:NO];
[manager setLocalizedDescription:@"MyVPN"];
[manager saveToPreferencesWithCompletionHandler:^(NSError * _Nullable error) {
if(error) {
NSLog(@"Save error: %@", error);
}
else {
NSLog(@"Saved!");
}
}];
}
}];
NEVPNManager是个VPN的管理单例,在整个VPN的操作中会被频繁使用。首先调用loadFromPrefreferencesWithCompletionHandler函数加载相关配置,如果没有发生错误就使用类NEVPNProtocolIKEV2配置VPN的类型(该例子使用的是IKEV2类型,类似的还可以通过NEVPNProtocolIPSec设置IPSec类型的VPN,配置方式大同小异),关键点在于NEVPNProtocolIKEv2类的各个配置参数:
- 如果authenticationMethod字段采用的是NEVPNIKEAuthenticationMethodCertificate,那么在使用该VPN之前,我们必须引导用户在ios设备安装从我们的服务器导出的证书。
- passwordReference 字段必须使用从KeyChain里面取出的密码,在此之前,我们可以先将VPN的密码提前使用ios的keyChain进行持久化。
- identityReference 则是使用keyChain存储的VPN证书。
- username VPN的账号
- serverAddress VPN的服务器地址,可以是域名或者IP地址
- remoteIdentifier 远程服务器的ID,该参数可以在自己服务器的VPN配置文件查询得到
如果用户尚未安装描述文件,则调用saveToPreferencesWithCompletionHandler会弹出系统提示,提醒用户安装相应的描述文件。
以上任何一个字段填写错误都会导致VPN连接不成功。一切就绪后,使用如下方式发起VPN的连接请求:
NSError *startError;
[[NEVPNManager sharedManager].connection startVPNTunnelAndReturnError:&startError];
一般情况在开始连接之前最好先加载VPN配置,如果没有错误再进行连接,(如果连接成功后,设备顶部状态栏会出现一个VPN图标。)操作如下:
[[NEVPNManager sharedManager] loadFromPreferencesWithCompletionHandler:^(NSError * _Nullable error) {
if(error)
{
NSLog(@"VPN load error->%@", error);
}
else
{
NSError *startError;
[[NEVPNManager sharedManager].connection startVPNTunnelAndReturnError:&startError];
if(startError) {
NSLog(@"Start error: %@", startError.localizedDescription);
} else {
NSLog(@"Connection established!");
}
}
}];
综上,通过苹果的框架去实现一个简单的VPN功能还是相当容易的,如果各位在使用上遇到了什么问题,请留言!。
最后,厚着脸皮安利一下自己最近写的一个APP(水平有限,有需要改进的地方还望高手指出),希望大家多多支持,多多交流,共同进步😂😂
https://itunes.apple.com/us/app/bigvpn/id1225850922?mt=8
-
IKEv2连接在用户自身网络状况经常变化的情况下仍旧能够维持加密连接,而不会出现频繁闪断、断开又重连之类的情况,能大大提高网络连接的稳定性。IKEv2能够拥有比PPTP/L2TP更加高效的网络通讯效率。IKEv2是IKE(v1)的改良版,使用了公钥证书和密码等多重认证,弥补了v1时代的安全性上的不足。比PPTP/L2TP更是可靠许多。同时IKEv2还支持硬件加速,保证了高效的传输效率。(引用自网络) ↩