// // ViewController.m // VPNOCDemo // // Created by 程俊铭 on 2022/6/8. // #import "ViewController.h" #import #import @interface ViewController () @property (nonatomic, strong)NETunnelProviderManager *providerManagers; @property (nonatomic, strong) UIButton *connectBtn; @property (nonatomic, strong) UILabel *stutusLb; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onVpnStateChange:) name:NEVPNStatusDidChangeNotification object:nil]; [self.connectBtn addTarget:self action:@selector(connect) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:self.connectBtn]; [self.view addSubview:self.stutusLb]; [self.connectBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.center.equalTo(self.view); }]; [self.stutusLb mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.equalTo(self.view); make.top.equalTo(self.connectBtn.mas_bottom).offset(40); }]; NSURL *url = [[NSBundle mainBundle] URLForResource:@"FlyTestVPN" withExtension:@"ovpn"]; NSData *data = [[NSData alloc] initWithContentsOfURL:url]; [self saveVpn:data]; } /// 保存vpn相关的数据 /// @param data 数据 -(void)saveVpn:(NSData *)data { //加载与调用应用程序关联的所有应用程序代理配置,这些配置以前已保存到网络扩展首选项中。 [NETunnelProviderManager loadAllFromPreferencesWithCompletionHandler:^(NSArray * _Nullable managers, NSError * _Nullable error) { if (error) { NSLog(@"Load Error: %@", error.description); } NETunnelProviderManager *manager; if (managers.count > 0) { manager = managers[0]; }else { manager = [[NETunnelProviderManager alloc] init]; manager.protocolConfiguration = [[NETunnelProviderProtocol alloc] init]; } NETunnelProviderProtocol *tunel = [[NETunnelProviderProtocol alloc]init]; // 获取文件内容 tunel.providerConfiguration = @{@"ovpn": data}; // 项目的Identifier tunel.providerBundleIdentifier = @"com.chuancheng.zy.vpn.master.PacketTunnelProvider"; // serverAddress:即在手机设置的vpn中显示的vpn地址(服务器显示) tunel.serverAddress = @"Fly VPN"; // tunel.username = @"username"; // tunel.identityDataPassword = @"password"; // 设备进入睡眠,vpn断开连接 tunel.disconnectOnSleep = NO; // 是否可以编辑 [manager setEnabled:YES]; // 协议配置 [manager setProtocolConfiguration:tunel]; // 包含vpn描述的字符串(类型显示) manager.localizedDescription = @"Fly-加速器"; // 保存信息 // SSLWeakSelf(self); [manager saveToPreferencesWithCompletionHandler:^(NSError *error) { if(error) { NSLog(@"Save error: %@", error); }else { self.providerManagers = manager; NSLog(@"add success"); //加载与调用应用程序关联的所有应用程序代理配置,这些配置以前已保存到网络扩展首选项中。 [manager loadFromPreferencesWithCompletionHandler:^(NSError * _Nullable error) { NSLog(@"loadFromPreferences!"); }]; } }]; }]; } -(void)connect { // 连接 [self.providerManagers loadFromPreferencesWithCompletionHandler:^(NSError * _Nullable error) { if(!error){ [self.providerManagers saveToPreferencesWithCompletionHandler:^(NSError * _Nullable error) { if (error) { NSLog(@"保存失败"); }else { NSError *error = nil; [self.providerManagers.connection startVPNTunnelWithOptions:nil andReturnError:&error]; if(error) { NSLog(@"Start error: %@", error.localizedDescription); }else{ NSLog(@"Connection established!"); } } }]; } }]; } -(void)disconnectAction { // 断开连接 [self.providerManagers loadFromPreferencesWithCompletionHandler:^(NSError * _Nullable error) { [self.providerManagers.connection stopVPNTunnel]; }]; } -(void)onVpnStateChange:(NSNotification *)Notification { NEVPNStatus status = self.providerManagers.connection.status; switch (status) { case NEVPNStatusInvalid: { NSLog(@"连接无效"); self.stutusLb.text = @"连接无效"; } break; case NEVPNStatusDisconnected: { NSLog(@"未连接"); self.stutusLb.text = @"未连接"; } break; case NEVPNStatusConnecting: { NSLog(@"正在连接"); self.stutusLb.text = @"正在连接"; } break; case NEVPNStatusConnected: { NSLog(@"已连接"); self.stutusLb.text = @"已连接"; } break; case NEVPNStatusDisconnecting: { NSLog(@"断开连接中..."); self.stutusLb.text = @"断开连接中..."; } break; case NEVPNStatusReasserting: { NSLog(@"重新连接..."); self.stutusLb.text = @"重新连接..."; } break; default: break; } } //@property (nonatomic, strong) UIButton *connectBtn; //@property (nonatomic, strong) UILabel *stutusLb; - (UIButton *)connectBtn { if (_connectBtn == nil) { _connectBtn = [[UIButton alloc]init]; [_connectBtn setTitle:@"连接" forState:UIControlStateNormal]; [_connectBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; } return _connectBtn; } - (UILabel *)stutusLb { if (_stutusLb == nil) { _stutusLb = [[UILabel alloc]init]; _stutusLb.text = @"状态"; _stutusLb.textColor = [UIColor redColor]; } return _stutusLb; } @end