├── .gitignore ├── IKEv2_Demo.xcodeproj └── project.pbxproj ├── IKEv2_Demo ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── IKEv2_Demo.entitlements ├── Info.plist ├── LoginViewController.h ├── LoginViewController.m └── main.m ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/osx,xcode,objective-c 3 | 4 | ### OSX ### 5 | .DS_Store 6 | .AppleDouble 7 | .LSOverride 8 | 9 | # Icon must end with two \r 10 | Icon 11 | 12 | 13 | # Thumbnails 14 | ._* 15 | 16 | # Files that might appear in the root of a volume 17 | .DocumentRevisions-V100 18 | .fseventsd 19 | .Spotlight-V100 20 | .TemporaryItems 21 | .Trashes 22 | .VolumeIcon.icns 23 | 24 | # Directories potentially created on remote AFP share 25 | .AppleDB 26 | .AppleDesktop 27 | Network Trash Folder 28 | Temporary Items 29 | .apdisk 30 | 31 | 32 | ### Xcode ### 33 | # Xcode 34 | # 35 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 36 | 37 | ## Build generated 38 | build/ 39 | DerivedData/ 40 | 41 | ## Various settings 42 | *.pbxuser 43 | !default.pbxuser 44 | *.mode1v3 45 | !default.mode1v3 46 | *.mode2v3 47 | !default.mode2v3 48 | *.perspectivev3 49 | !default.perspectivev3 50 | xcuserdata/ 51 | 52 | ## Other 53 | *.moved-aside 54 | *.xccheckout 55 | *.xcscmblueprint 56 | 57 | 58 | ### Objective-C ### 59 | # Xcode 60 | # 61 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 62 | 63 | ## Build generated 64 | build/ 65 | DerivedData/ 66 | 67 | ## Various settings 68 | *.pbxuser 69 | !default.pbxuser 70 | *.mode1v3 71 | !default.mode1v3 72 | *.mode2v3 73 | !default.mode2v3 74 | *.perspectivev3 75 | !default.perspectivev3 76 | xcuserdata/ 77 | 78 | ## Other 79 | *.moved-aside 80 | *.xcuserstate 81 | 82 | ## Obj-C/Swift specific 83 | *.hmap 84 | *.ipa 85 | 86 | # CocoaPods 87 | # 88 | # We recommend against adding the Pods directory to your .gitignore. However 89 | # you should judge for yourself, the pros and cons are mentioned at: 90 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 91 | # 92 | # Pods/ 93 | 94 | # Carthage 95 | # 96 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 97 | # Carthage/Checkouts 98 | 99 | Carthage/Build 100 | 101 | # fastlane 102 | # 103 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 104 | # screenshots whenever they are needed. 105 | # For more information about the recommended setup visit: 106 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md 107 | 108 | fastlane/report.xml 109 | fastlane/screenshots 110 | 111 | ### Objective-C Patch ### 112 | *.xcscmblueprint 113 | 114 | -------------------------------------------------------------------------------- /IKEv2_Demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | F2532BFF1C992A2E002D3E16 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F2532BFE1C992A2E002D3E16 /* main.m */; }; 11 | F2532C021C992A2E002D3E16 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F2532C011C992A2E002D3E16 /* AppDelegate.m */; }; 12 | F2532C0B1C992A2E002D3E16 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F2532C091C992A2E002D3E16 /* Main.storyboard */; }; 13 | F2532C0D1C992A2E002D3E16 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F2532C0C1C992A2E002D3E16 /* Assets.xcassets */; }; 14 | F2532C101C992A2E002D3E16 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F2532C0E1C992A2E002D3E16 /* LaunchScreen.storyboard */; }; 15 | F2532C341C992A7F002D3E16 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F2532C331C992A7F002D3E16 /* NetworkExtension.framework */; }; 16 | F2532C3B1C992D2B002D3E16 /* LoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F2532C3A1C992D2B002D3E16 /* LoginViewController.m */; }; 17 | F2532C3D1C992E3F002D3E16 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F2532C3C1C992E3F002D3E16 /* Security.framework */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | F2532BFA1C992A2E002D3E16 /* IKEv2_Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IKEv2_Demo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | F2532BFE1C992A2E002D3E16 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 23 | F2532C001C992A2E002D3E16 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 24 | F2532C011C992A2E002D3E16 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 25 | F2532C0A1C992A2E002D3E16 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 26 | F2532C0C1C992A2E002D3E16 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 27 | F2532C0F1C992A2E002D3E16 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 28 | F2532C111C992A2E002D3E16 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 29 | F2532C331C992A7F002D3E16 /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = System/Library/Frameworks/NetworkExtension.framework; sourceTree = SDKROOT; }; 30 | F2532C351C992A7F002D3E16 /* IKEv2_Demo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = IKEv2_Demo.entitlements; sourceTree = ""; }; 31 | F2532C391C992D2B002D3E16 /* LoginViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoginViewController.h; sourceTree = ""; }; 32 | F2532C3A1C992D2B002D3E16 /* LoginViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LoginViewController.m; sourceTree = ""; }; 33 | F2532C3C1C992E3F002D3E16 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | F2532BF71C992A2E002D3E16 /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | F2532C3D1C992E3F002D3E16 /* Security.framework in Frameworks */, 42 | F2532C341C992A7F002D3E16 /* NetworkExtension.framework in Frameworks */, 43 | ); 44 | runOnlyForDeploymentPostprocessing = 0; 45 | }; 46 | /* End PBXFrameworksBuildPhase section */ 47 | 48 | /* Begin PBXGroup section */ 49 | F2532BF11C992A2E002D3E16 = { 50 | isa = PBXGroup; 51 | children = ( 52 | F2532C3C1C992E3F002D3E16 /* Security.framework */, 53 | F2532C331C992A7F002D3E16 /* NetworkExtension.framework */, 54 | F2532BFC1C992A2E002D3E16 /* IKEv2_Demo */, 55 | F2532BFB1C992A2E002D3E16 /* Products */, 56 | ); 57 | sourceTree = ""; 58 | }; 59 | F2532BFB1C992A2E002D3E16 /* Products */ = { 60 | isa = PBXGroup; 61 | children = ( 62 | F2532BFA1C992A2E002D3E16 /* IKEv2_Demo.app */, 63 | ); 64 | name = Products; 65 | sourceTree = ""; 66 | }; 67 | F2532BFC1C992A2E002D3E16 /* IKEv2_Demo */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | F2532C351C992A7F002D3E16 /* IKEv2_Demo.entitlements */, 71 | F2532C001C992A2E002D3E16 /* AppDelegate.h */, 72 | F2532C011C992A2E002D3E16 /* AppDelegate.m */, 73 | F2532C391C992D2B002D3E16 /* LoginViewController.h */, 74 | F2532C3A1C992D2B002D3E16 /* LoginViewController.m */, 75 | F2532C091C992A2E002D3E16 /* Main.storyboard */, 76 | F2532C0C1C992A2E002D3E16 /* Assets.xcassets */, 77 | F2532C0E1C992A2E002D3E16 /* LaunchScreen.storyboard */, 78 | F2532C111C992A2E002D3E16 /* Info.plist */, 79 | F2532BFD1C992A2E002D3E16 /* Supporting Files */, 80 | ); 81 | path = IKEv2_Demo; 82 | sourceTree = ""; 83 | }; 84 | F2532BFD1C992A2E002D3E16 /* Supporting Files */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | F2532BFE1C992A2E002D3E16 /* main.m */, 88 | ); 89 | name = "Supporting Files"; 90 | sourceTree = ""; 91 | }; 92 | /* End PBXGroup section */ 93 | 94 | /* Begin PBXNativeTarget section */ 95 | F2532BF91C992A2E002D3E16 /* IKEv2_Demo */ = { 96 | isa = PBXNativeTarget; 97 | buildConfigurationList = F2532C2A1C992A2F002D3E16 /* Build configuration list for PBXNativeTarget "IKEv2_Demo" */; 98 | buildPhases = ( 99 | F2532BF61C992A2E002D3E16 /* Sources */, 100 | F2532BF71C992A2E002D3E16 /* Frameworks */, 101 | F2532BF81C992A2E002D3E16 /* Resources */, 102 | ); 103 | buildRules = ( 104 | ); 105 | dependencies = ( 106 | ); 107 | name = IKEv2_Demo; 108 | productName = IKEv2_Demo; 109 | productReference = F2532BFA1C992A2E002D3E16 /* IKEv2_Demo.app */; 110 | productType = "com.apple.product-type.application"; 111 | }; 112 | /* End PBXNativeTarget section */ 113 | 114 | /* Begin PBXProject section */ 115 | F2532BF21C992A2E002D3E16 /* Project object */ = { 116 | isa = PBXProject; 117 | attributes = { 118 | LastUpgradeCheck = 0720; 119 | ORGANIZATIONNAME = zorro; 120 | TargetAttributes = { 121 | F2532BF91C992A2E002D3E16 = { 122 | CreatedOnToolsVersion = 7.2.1; 123 | SystemCapabilities = { 124 | com.apple.VPNLite = { 125 | enabled = 1; 126 | }; 127 | }; 128 | }; 129 | }; 130 | }; 131 | buildConfigurationList = F2532BF51C992A2E002D3E16 /* Build configuration list for PBXProject "IKEv2_Demo" */; 132 | compatibilityVersion = "Xcode 3.2"; 133 | developmentRegion = English; 134 | hasScannedForEncodings = 0; 135 | knownRegions = ( 136 | en, 137 | Base, 138 | ); 139 | mainGroup = F2532BF11C992A2E002D3E16; 140 | productRefGroup = F2532BFB1C992A2E002D3E16 /* Products */; 141 | projectDirPath = ""; 142 | projectRoot = ""; 143 | targets = ( 144 | F2532BF91C992A2E002D3E16 /* IKEv2_Demo */, 145 | ); 146 | }; 147 | /* End PBXProject section */ 148 | 149 | /* Begin PBXResourcesBuildPhase section */ 150 | F2532BF81C992A2E002D3E16 /* Resources */ = { 151 | isa = PBXResourcesBuildPhase; 152 | buildActionMask = 2147483647; 153 | files = ( 154 | F2532C101C992A2E002D3E16 /* LaunchScreen.storyboard in Resources */, 155 | F2532C0D1C992A2E002D3E16 /* Assets.xcassets in Resources */, 156 | F2532C0B1C992A2E002D3E16 /* Main.storyboard in Resources */, 157 | ); 158 | runOnlyForDeploymentPostprocessing = 0; 159 | }; 160 | /* End PBXResourcesBuildPhase section */ 161 | 162 | /* Begin PBXSourcesBuildPhase section */ 163 | F2532BF61C992A2E002D3E16 /* Sources */ = { 164 | isa = PBXSourcesBuildPhase; 165 | buildActionMask = 2147483647; 166 | files = ( 167 | F2532C021C992A2E002D3E16 /* AppDelegate.m in Sources */, 168 | F2532BFF1C992A2E002D3E16 /* main.m in Sources */, 169 | F2532C3B1C992D2B002D3E16 /* LoginViewController.m in Sources */, 170 | ); 171 | runOnlyForDeploymentPostprocessing = 0; 172 | }; 173 | /* End PBXSourcesBuildPhase section */ 174 | 175 | /* Begin PBXVariantGroup section */ 176 | F2532C091C992A2E002D3E16 /* Main.storyboard */ = { 177 | isa = PBXVariantGroup; 178 | children = ( 179 | F2532C0A1C992A2E002D3E16 /* Base */, 180 | ); 181 | name = Main.storyboard; 182 | sourceTree = ""; 183 | }; 184 | F2532C0E1C992A2E002D3E16 /* LaunchScreen.storyboard */ = { 185 | isa = PBXVariantGroup; 186 | children = ( 187 | F2532C0F1C992A2E002D3E16 /* Base */, 188 | ); 189 | name = LaunchScreen.storyboard; 190 | sourceTree = ""; 191 | }; 192 | /* End PBXVariantGroup section */ 193 | 194 | /* Begin XCBuildConfiguration section */ 195 | F2532C281C992A2F002D3E16 /* Debug */ = { 196 | isa = XCBuildConfiguration; 197 | buildSettings = { 198 | ALWAYS_SEARCH_USER_PATHS = NO; 199 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 200 | CLANG_CXX_LIBRARY = "libc++"; 201 | CLANG_ENABLE_MODULES = YES; 202 | CLANG_ENABLE_OBJC_ARC = YES; 203 | CLANG_WARN_BOOL_CONVERSION = YES; 204 | CLANG_WARN_CONSTANT_CONVERSION = YES; 205 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 206 | CLANG_WARN_EMPTY_BODY = YES; 207 | CLANG_WARN_ENUM_CONVERSION = YES; 208 | CLANG_WARN_INT_CONVERSION = YES; 209 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 210 | CLANG_WARN_UNREACHABLE_CODE = YES; 211 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 212 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 213 | COPY_PHASE_STRIP = NO; 214 | DEBUG_INFORMATION_FORMAT = dwarf; 215 | ENABLE_STRICT_OBJC_MSGSEND = YES; 216 | ENABLE_TESTABILITY = YES; 217 | GCC_C_LANGUAGE_STANDARD = gnu99; 218 | GCC_DYNAMIC_NO_PIC = NO; 219 | GCC_NO_COMMON_BLOCKS = YES; 220 | GCC_OPTIMIZATION_LEVEL = 0; 221 | GCC_PREPROCESSOR_DEFINITIONS = ( 222 | "DEBUG=1", 223 | "$(inherited)", 224 | ); 225 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 226 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 227 | GCC_WARN_UNDECLARED_SELECTOR = YES; 228 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 229 | GCC_WARN_UNUSED_FUNCTION = YES; 230 | GCC_WARN_UNUSED_VARIABLE = YES; 231 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 232 | MTL_ENABLE_DEBUG_INFO = YES; 233 | ONLY_ACTIVE_ARCH = YES; 234 | SDKROOT = iphoneos; 235 | }; 236 | name = Debug; 237 | }; 238 | F2532C291C992A2F002D3E16 /* Release */ = { 239 | isa = XCBuildConfiguration; 240 | buildSettings = { 241 | ALWAYS_SEARCH_USER_PATHS = NO; 242 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 243 | CLANG_CXX_LIBRARY = "libc++"; 244 | CLANG_ENABLE_MODULES = YES; 245 | CLANG_ENABLE_OBJC_ARC = YES; 246 | CLANG_WARN_BOOL_CONVERSION = YES; 247 | CLANG_WARN_CONSTANT_CONVERSION = YES; 248 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 249 | CLANG_WARN_EMPTY_BODY = YES; 250 | CLANG_WARN_ENUM_CONVERSION = YES; 251 | CLANG_WARN_INT_CONVERSION = YES; 252 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 253 | CLANG_WARN_UNREACHABLE_CODE = YES; 254 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 255 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 256 | COPY_PHASE_STRIP = NO; 257 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 258 | ENABLE_NS_ASSERTIONS = NO; 259 | ENABLE_STRICT_OBJC_MSGSEND = YES; 260 | GCC_C_LANGUAGE_STANDARD = gnu99; 261 | GCC_NO_COMMON_BLOCKS = YES; 262 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 263 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 264 | GCC_WARN_UNDECLARED_SELECTOR = YES; 265 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 266 | GCC_WARN_UNUSED_FUNCTION = YES; 267 | GCC_WARN_UNUSED_VARIABLE = YES; 268 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 269 | MTL_ENABLE_DEBUG_INFO = NO; 270 | SDKROOT = iphoneos; 271 | VALIDATE_PRODUCT = YES; 272 | }; 273 | name = Release; 274 | }; 275 | F2532C2B1C992A2F002D3E16 /* Debug */ = { 276 | isa = XCBuildConfiguration; 277 | buildSettings = { 278 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 279 | CODE_SIGN_ENTITLEMENTS = IKEv2_Demo/IKEv2_Demo.entitlements; 280 | CODE_SIGN_IDENTITY = "iPhone Developer"; 281 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 282 | INFOPLIST_FILE = IKEv2_Demo/Info.plist; 283 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 284 | PRODUCT_BUNDLE_IDENTIFIER = "im.zorro.IKEv2-Demo"; 285 | PRODUCT_NAME = "$(TARGET_NAME)"; 286 | PROVISIONING_PROFILE = ""; 287 | }; 288 | name = Debug; 289 | }; 290 | F2532C2C1C992A2F002D3E16 /* Release */ = { 291 | isa = XCBuildConfiguration; 292 | buildSettings = { 293 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 294 | CODE_SIGN_ENTITLEMENTS = IKEv2_Demo/IKEv2_Demo.entitlements; 295 | CODE_SIGN_IDENTITY = "iPhone Developer"; 296 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 297 | INFOPLIST_FILE = IKEv2_Demo/Info.plist; 298 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 299 | PRODUCT_BUNDLE_IDENTIFIER = "im.zorro.IKEv2-Demo"; 300 | PRODUCT_NAME = "$(TARGET_NAME)"; 301 | PROVISIONING_PROFILE = ""; 302 | }; 303 | name = Release; 304 | }; 305 | /* End XCBuildConfiguration section */ 306 | 307 | /* Begin XCConfigurationList section */ 308 | F2532BF51C992A2E002D3E16 /* Build configuration list for PBXProject "IKEv2_Demo" */ = { 309 | isa = XCConfigurationList; 310 | buildConfigurations = ( 311 | F2532C281C992A2F002D3E16 /* Debug */, 312 | F2532C291C992A2F002D3E16 /* Release */, 313 | ); 314 | defaultConfigurationIsVisible = 0; 315 | defaultConfigurationName = Release; 316 | }; 317 | F2532C2A1C992A2F002D3E16 /* Build configuration list for PBXNativeTarget "IKEv2_Demo" */ = { 318 | isa = XCConfigurationList; 319 | buildConfigurations = ( 320 | F2532C2B1C992A2F002D3E16 /* Debug */, 321 | F2532C2C1C992A2F002D3E16 /* Release */, 322 | ); 323 | defaultConfigurationIsVisible = 0; 324 | defaultConfigurationName = Release; 325 | }; 326 | /* End XCConfigurationList section */ 327 | }; 328 | rootObject = F2532BF21C992A2E002D3E16 /* Project object */; 329 | } 330 | -------------------------------------------------------------------------------- /IKEv2_Demo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // IKEv2_Demo 4 | // 5 | // Created by zqqf16 on 16/3/16. 6 | // Copyright © 2016年 zqqf16. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /IKEv2_Demo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // IKEv2_Demo 4 | // 5 | // Created by zqqf16 on 16/3/16. 6 | // Copyright © 2016年 zqqf16. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /IKEv2_Demo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /IKEv2_Demo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /IKEv2_Demo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 124 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /IKEv2_Demo/IKEv2_Demo.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.networking.vpn.api 6 | 7 | allow-vpn 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /IKEv2_Demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UIStatusBarTintParameters 34 | 35 | UINavigationBar 36 | 37 | Style 38 | UIBarStyleDefault 39 | Translucent 40 | 41 | 42 | 43 | UISupportedInterfaceOrientations 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /IKEv2_Demo/LoginViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LoginViewController.h 3 | // IKEv2_Demo 4 | // 5 | // Created by zqqf16 on 16/3/16. 6 | // Copyright © 2016年 zqqf16. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LoginViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /IKEv2_Demo/LoginViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LoginViewController.m 3 | // IKEv2_Demo 4 | // 5 | // Created by zqqf16 on 16/3/16. 6 | // Copyright © 2016年 zqqf16. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | 13 | #import "LoginViewController.h" 14 | 15 | @interface LoginViewController () 16 | 17 | @property (weak, nonatomic) IBOutlet UITextField *server; 18 | @property (weak, nonatomic) IBOutlet UITextField *username; 19 | @property (weak, nonatomic) IBOutlet UITextField *password; 20 | @property (weak, nonatomic) IBOutlet UITextField *presharedKey; 21 | @property (weak, nonatomic) IBOutlet UITextField *remoteIdentifier; 22 | @property (weak, nonatomic) IBOutlet UITextField *localIdentifier; 23 | 24 | @property (weak, nonatomic) IBOutlet UIButton *actionButton; 25 | @property (weak, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator; 26 | 27 | @property (strong, nonatomic) NEVPNManager *vpnManager; 28 | 29 | @end 30 | 31 | @implementation LoginViewController 32 | 33 | - (void)viewDidLoad { 34 | [super viewDidLoad]; 35 | 36 | self.vpnManager = [NEVPNManager sharedManager]; 37 | 38 | NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 39 | [nc addObserver:self 40 | selector:@selector(vpnStatusDidChanged:) 41 | name:NEVPNStatusDidChangeNotification 42 | object:nil]; 43 | } 44 | 45 | - (void)didReceiveMemoryWarning { 46 | [super didReceiveMemoryWarning]; 47 | } 48 | 49 | #pragma mark - UITextField Delegate 50 | 51 | - (BOOL)textFieldShouldReturn:(UITextField *)textField 52 | { 53 | NSArray *textFieldList = @[_server, _username, _password, _presharedKey, _remoteIdentifier, _localIdentifier]; 54 | NSUInteger index = [textFieldList indexOfObject:textField]; 55 | 56 | [textField resignFirstResponder]; 57 | 58 | if (index < textFieldList.count - 1) { 59 | [(UITextField *)[textFieldList objectAtIndex:index+1] becomeFirstResponder]; 60 | } 61 | 62 | return YES; 63 | } 64 | 65 | #pragma mark - VPN Control 66 | 67 | - (void)installProfile { 68 | NSString *server = _server.text; 69 | NSString *username = _username.text; 70 | NSString *remoteIdentifier = _remoteIdentifier.text; 71 | NSString *localIdnetifier = _localIdentifier.text; 72 | 73 | // Save password & psk 74 | [self createKeychainValue:_password.text forIdentifier:@"VPN_PASSWORD"]; 75 | [self createKeychainValue:_presharedKey.text forIdentifier:@"PSK"]; 76 | 77 | // Load config from perference 78 | [_vpnManager loadFromPreferencesWithCompletionHandler:^(NSError *error) { 79 | 80 | if (error) { 81 | NSLog(@"Load config failed [%@]", error.localizedDescription); 82 | return; 83 | } 84 | 85 | NEVPNProtocolIKEv2 *p = (NEVPNProtocolIKEv2 *)_vpnManager.protocolConfiguration; 86 | 87 | if (p) { 88 | // Protocol exists. 89 | // If you don't want to edit it, just return here. 90 | } else { 91 | // create a new one. 92 | p = [[NEVPNProtocolIKEv2 alloc] init]; 93 | } 94 | 95 | // config IPSec protocol 96 | p.username = username; 97 | p.serverAddress = server; 98 | 99 | // Get password persistent reference from keychain 100 | // If password doesn't exist in keychain, should create it beforehand. 101 | // [self createKeychainValue:@"your_password" forIdentifier:@"VPN_PASSWORD"]; 102 | p.passwordReference = [self searchKeychainCopyMatching:@"VPN_PASSWORD"]; 103 | 104 | // PSK 105 | p.authenticationMethod = NEVPNIKEAuthenticationMethodSharedSecret; 106 | // [self createKeychainValue:@"your_psk" forIdentifier:@"PSK"]; 107 | p.sharedSecretReference = [self searchKeychainCopyMatching:@"PSK"]; 108 | 109 | /* 110 | // certificate 111 | p.identityData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"]]; 112 | p.identityDataPassword = @"[Your certificate import password]"; 113 | */ 114 | 115 | p.localIdentifier = localIdnetifier; 116 | p.remoteIdentifier = remoteIdentifier; 117 | 118 | p.useExtendedAuthentication = YES; 119 | p.disconnectOnSleep = NO; 120 | 121 | _vpnManager.protocolConfiguration = p; 122 | _vpnManager.localizedDescription = @"IPSec IKEv2 Demo"; 123 | _vpnManager.enabled = YES; 124 | 125 | [_vpnManager saveToPreferencesWithCompletionHandler:^(NSError *error) { 126 | if (error) { 127 | NSLog(@"Save config failed [%@]", error.localizedDescription); 128 | } 129 | }]; 130 | }]; 131 | } 132 | 133 | - (IBAction)changeVPNStatus:(id)sender 134 | { 135 | NEVPNStatus status = _vpnManager.connection.status; 136 | if (status == NEVPNStatusConnected 137 | || status == NEVPNStatusConnecting 138 | || status == NEVPNStatusReasserting) { 139 | [self disconnect]; 140 | } else { 141 | [self connect]; 142 | } 143 | } 144 | 145 | - (void)connect { 146 | // Install profile 147 | [self installProfile]; 148 | 149 | NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 150 | [nc addObserver:self 151 | selector:@selector(vpnConfigDidChanged:) 152 | name:NEVPNConfigurationChangeNotification 153 | object:nil]; 154 | 155 | } 156 | 157 | - (void)disconnect 158 | { 159 | [_vpnManager.connection stopVPNTunnel]; 160 | } 161 | 162 | - (void)vpnConfigDidChanged:(NSNotification *)notification 163 | { 164 | // TODO: Save configuration failed 165 | [self startConnecting]; 166 | [[NSNotificationCenter defaultCenter] removeObserver:self 167 | name:NEVPNConfigurationChangeNotification 168 | object:nil]; 169 | } 170 | 171 | - (void)startConnecting 172 | { 173 | NSError *startError; 174 | [_vpnManager.connection startVPNTunnelAndReturnError:&startError]; 175 | if (startError) { 176 | NSLog(@"Start VPN failed: [%@]", startError.localizedDescription); 177 | } 178 | } 179 | 180 | - (void)vpnStatusDidChanged:(NSNotification *)notification 181 | { 182 | NEVPNStatus status = _vpnManager.connection.status; 183 | switch (status) { 184 | case NEVPNStatusConnected: 185 | _actionButton.enabled = YES; 186 | [_actionButton setTitle:@"Disconnect" forState:UIControlStateNormal]; 187 | _activityIndicator.hidden = YES; 188 | break; 189 | case NEVPNStatusInvalid: 190 | case NEVPNStatusDisconnected: 191 | _actionButton.enabled = YES; 192 | [_actionButton setTitle:@"Connect" forState:UIControlStateNormal]; 193 | _activityIndicator.hidden = YES; 194 | break; 195 | case NEVPNStatusConnecting: 196 | case NEVPNStatusReasserting: 197 | _actionButton.enabled = YES; 198 | [_actionButton setTitle:@"Connecting..." forState:UIControlStateNormal]; 199 | _activityIndicator.hidden = NO; 200 | [_activityIndicator startAnimating]; 201 | break; 202 | case NEVPNStatusDisconnecting: 203 | _actionButton.enabled = NO; 204 | [_actionButton setTitle:@"Disconnecting..." forState:UIControlStateDisabled]; 205 | _activityIndicator.hidden = NO; 206 | [_activityIndicator startAnimating]; 207 | break; 208 | default: 209 | break; 210 | } 211 | } 212 | 213 | #pragma mark - KeyChain 214 | 215 | static NSString * const serviceName = @"im.zorro.ipsec_demo.vpn_config"; 216 | 217 | - (NSMutableDictionary *)newSearchDictionary:(NSString *)identifier { 218 | NSMutableDictionary *searchDictionary = [[NSMutableDictionary alloc] init]; 219 | 220 | [searchDictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; 221 | 222 | NSData *encodedIdentifier = [identifier dataUsingEncoding:NSUTF8StringEncoding]; 223 | [searchDictionary setObject:encodedIdentifier forKey:(__bridge id)kSecAttrGeneric]; 224 | [searchDictionary setObject:encodedIdentifier forKey:(__bridge id)kSecAttrAccount]; 225 | [searchDictionary setObject:serviceName forKey:(__bridge id)kSecAttrService]; 226 | 227 | return searchDictionary; 228 | } 229 | 230 | - (NSData *)searchKeychainCopyMatching:(NSString *)identifier { 231 | NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier]; 232 | 233 | // Add search attributes 234 | [searchDictionary setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; 235 | 236 | // Add search return types 237 | // Must be persistent ref !!!! 238 | [searchDictionary setObject:@YES forKey:(__bridge id)kSecReturnPersistentRef]; 239 | 240 | CFTypeRef result = NULL; 241 | SecItemCopyMatching((__bridge CFDictionaryRef)searchDictionary, &result); 242 | 243 | return (__bridge_transfer NSData *)result; 244 | } 245 | 246 | - (BOOL)createKeychainValue:(NSString *)password forIdentifier:(NSString *)identifier { 247 | NSMutableDictionary *dictionary = [self newSearchDictionary:identifier]; 248 | 249 | OSStatus status = SecItemDelete((__bridge CFDictionaryRef)dictionary); 250 | 251 | NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; 252 | [dictionary setObject:passwordData forKey:(__bridge id)kSecValueData]; 253 | 254 | status = SecItemAdd((__bridge CFDictionaryRef)dictionary, NULL); 255 | 256 | if (status == errSecSuccess) { 257 | return YES; 258 | } 259 | return NO; 260 | } 261 | 262 | @end 263 | -------------------------------------------------------------------------------- /IKEv2_Demo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // IKEv2_Demo 4 | // 5 | // Created by zqqf16 on 16/3/16. 6 | // Copyright © 2016年 zqqf16. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 上山打老虎 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IKEv2_Demo 2 | 3 | Configure and establish IKEv2 VPN connection programmatically in iOS 8+ 4 | 5 | 在 iOS 8+ 上通过 Network Extension 配置/控制 IKEv2 VPN。 6 | 7 | 8 | 有关 Network Extension 的具体使用,请参考 [谈谈 iOS8 中的 Network Extension](https://blog.zorro.im/posts/2014-10-14-ios8-network-extension.html) 9 | 10 | 11 | 有关 IKEv2 服务端的配置,请参考 [用 strongSwan 搭建免证书的 IKEv2 VPN](https://blog.zorro.im/posts/2015-10-14-strongswan-ikev2-for-ios-without-certificate.html) 12 | --------------------------------------------------------------------------------