Skip to content

Commit 9c55ee0

Browse files
committed
SimpleTunnel: Customized Networking Using the NetworkExtension Framework: Version 1.3, 2016-10-04
Updated to Swift 3 The Network Extension framework exposes APIs that give you the ability to customize the networking features of iOS and OS X. This sample project demonstrates how to: - Use the NEPacketTunnelProvider class to implement a custom VPN tunneling protocol. - Use the NETunnelProviderManager class to create and manage VPN configurations that use the custom VPN tunneling protocol. - Use the NEAppProxyProvider class to implement a custom transparent network proxy protocol. - Use the NEAppProxyProviderManager class to manage VPN configurations that use the transparent network proxy protocol. - Use the NEFilterControlProvider and NEFilterDataProvider classes to implement a custom on-device content filtering service. - Use the NEFilterManager class to configure the custom filtering service. Signed-off-by: Liu Lantao <[email protected]>
1 parent 7da81ad commit 9c55ee0

32 files changed

+796
-813
lines changed

SimpleTunnel/AppProxy/AppProxyClientTunnel.swift

-27
This file was deleted.

SimpleTunnel/AppProxy/AppProxyProvider.swift

+14-14
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ class AppProxyProvider: NEAppProxyProvider, TunnelDelegate {
1818
var tunnel: ClientTunnel?
1919

2020
/// The completion handler to call when the tunnel is fully established.
21-
var pendingStartCompletion: (NSError? -> Void)?
21+
var pendingStartCompletion: ((NSError?) -> Void)?
2222

2323
/// The completion handler to call when the tunnel is fully disconnected.
24-
var pendingStopCompletion: (Void -> Void)?
24+
var pendingStopCompletion: ((Void) -> Void)?
2525

2626
// MARK: NEAppProxyProvider
2727

2828
/// Begin the process of establishing the tunnel.
29-
override func startProxyWithOptions(options: [String : AnyObject]?, completionHandler: (NSError?) -> Void) {
29+
override func startProxy(options: [String : Any]?, completionHandler: @escaping (Error?) -> Void) {
3030

3131
let newTunnel = ClientTunnel()
3232
newTunnel.delegate = self
@@ -41,7 +41,7 @@ class AppProxyProvider: NEAppProxyProvider, TunnelDelegate {
4141
}
4242

4343
/// Begin the process of stopping the tunnel.
44-
override func stopProxyWithReason(reason: NEProviderStopReason, completionHandler: () -> Void) {
44+
override func stopProxy(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
4545

4646
// Clear out any pending start completion handler.
4747
pendingStartCompletion = nil
@@ -51,7 +51,7 @@ class AppProxyProvider: NEAppProxyProvider, TunnelDelegate {
5151
}
5252

5353
/// Handle a new flow of network data created by an application.
54-
override func handleNewFlow(flow: (NEAppProxyFlow?)) -> Bool {
54+
override func handleNewFlow(_ flow: (NEAppProxyFlow?)) -> Bool {
5555
var newConnection: ClientAppProxyConnection?
5656

5757
guard let clientTunnel = tunnel else { return false }
@@ -73,9 +73,9 @@ class AppProxyProvider: NEAppProxyProvider, TunnelDelegate {
7373
// MARK: TunnelDelegate
7474

7575
/// Handle the event of the tunnel being fully established.
76-
func tunnelDidOpen(targetTunnel: Tunnel) {
76+
func tunnelDidOpen(_ targetTunnel: Tunnel) {
7777
guard let clientTunnel = targetTunnel as? ClientTunnel else {
78-
pendingStartCompletion?(SimpleTunnelError.InternalError as NSError)
78+
pendingStartCompletion?(SimpleTunnelError.internalError as NSError)
7979
pendingStartCompletion = nil
8080
return
8181
}
@@ -84,7 +84,7 @@ class AppProxyProvider: NEAppProxyProvider, TunnelDelegate {
8484
}
8585

8686
/// Handle the event of the tunnel being fully disconnected.
87-
func tunnelDidClose(targetTunnel: Tunnel) {
87+
func tunnelDidClose(_ targetTunnel: Tunnel) {
8888

8989
// Call the appropriate completion handler depending on the current pending tunnel operation.
9090
if pendingStartCompletion != nil {
@@ -103,34 +103,34 @@ class AppProxyProvider: NEAppProxyProvider, TunnelDelegate {
103103
}
104104

105105
/// Handle the server sending a configuration.
106-
func tunnelDidSendConfiguration(targetTunnel: Tunnel, configuration: [String : AnyObject]) {
106+
func tunnelDidSendConfiguration(_ targetTunnel: Tunnel, configuration: [String : AnyObject]) {
107107
simpleTunnelLog("Server sent configuration: \(configuration)")
108108

109109
guard let tunnelAddress = tunnel?.remoteHost else {
110-
let error = SimpleTunnelError.BadConnection
110+
let error = SimpleTunnelError.badConnection
111111
pendingStartCompletion?(error as NSError)
112112
pendingStartCompletion = nil
113113
return
114114
}
115115

116-
guard let DNSDictionary = configuration[SettingsKey.DNS.rawValue] as? [String: AnyObject], DNSServers = DNSDictionary[SettingsKey.Servers.rawValue] as? [String] else {
116+
guard let DNSDictionary = configuration[SettingsKey.DNS.rawValue] as? [String: AnyObject], let DNSServers = DNSDictionary[SettingsKey.Servers.rawValue] as? [String] else {
117117
self.pendingStartCompletion?(nil)
118118
self.pendingStartCompletion = nil
119119
return
120120
}
121121

122122
let newSettings = NETunnelNetworkSettings(tunnelRemoteAddress: tunnelAddress)
123123

124-
newSettings.DNSSettings = NEDNSSettings(servers: DNSServers)
124+
newSettings.dnsSettings = NEDNSSettings(servers: DNSServers)
125125
if let DNSSearchDomains = DNSDictionary[SettingsKey.SearchDomains.rawValue] as? [String] {
126-
newSettings.DNSSettings?.searchDomains = DNSSearchDomains
126+
newSettings.dnsSettings?.searchDomains = DNSSearchDomains
127127
}
128128

129129
simpleTunnelLog("Calling setTunnelNetworkSettings")
130130

131131
self.setTunnelNetworkSettings(newSettings) { error in
132132
if error != nil {
133-
let startError = SimpleTunnelError.BadConfiguration
133+
let startError = SimpleTunnelError.badConfiguration
134134
self.pendingStartCompletion?(startError as NSError)
135135
self.pendingStartCompletion = nil
136136
}

SimpleTunnel/AppProxy/ClientAppProxyConnection.swift

+52-52
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class ClientAppProxyConnection : Connection {
1919
let appProxyFlow: NEAppProxyFlow
2020

2121
/// A dispatch queue used to regulate the sending of the connection's data through the tunnel connection.
22-
lazy var queue: dispatch_queue_t = dispatch_queue_create("ClientConnection Handle Data queue", nil)
22+
lazy var queue: DispatchQueue = DispatchQueue(label: "ClientConnection Handle Data queue", attributes: [])
2323

2424
// MARK: Initializers
2525

@@ -36,16 +36,16 @@ class ClientAppProxyConnection : Connection {
3636
}
3737

3838
/// Send an "Open" message to the SimpleTunnel server, to begin the process of establishing a flow of data in the SimpleTunnel protocol.
39-
func open(extraProperties: [String: AnyObject]) {
39+
func open(_ extraProperties: [String: AnyObject]) {
4040
guard let clientTunnel = tunnel as? ClientTunnel else {
4141
// Close the NEAppProxyFlow.
42-
let error: SimpleTunnelError = .BadConnection
42+
let error: SimpleTunnelError = .badConnection
4343
appProxyFlow.closeReadWithError(error as NSError)
4444
appProxyFlow.closeWriteWithError(error as NSError)
4545
return
4646
}
4747

48-
let properties = createMessagePropertiesForConnection(identifier, commandType:.Open, extraProperties:extraProperties)
48+
let properties = createMessagePropertiesForConnection(identifier, commandType:.open, extraProperties:extraProperties)
4949

5050
clientTunnel.sendMessage(properties) { error in
5151
if let error = error {
@@ -57,37 +57,37 @@ class ClientAppProxyConnection : Connection {
5757
}
5858

5959
/// Handle the result of sending a data message to the SimpleTunnel server.
60-
func handleSendResult(error: NSError?) {
60+
func handleSendResult(_ error: NSError?) {
6161
}
6262

6363
/// Handle errors that occur on the connection.
64-
func handleErrorCondition(flowError: NEAppProxyFlowError? = nil, notifyServer: Bool = true) {
64+
func handleErrorCondition(_ flowError: NEAppProxyErrorDomain? = nil, notifyServer: Bool = true) {
6565

6666
guard !isClosedCompletely else { return }
6767

68-
tunnel?.sendCloseType(.All, forConnection: identifier)
68+
tunnel?.sendCloseType(.all, forConnection: identifier)
6969

70-
closeConnection(.All)
70+
closeConnection(.all)
7171
}
7272

7373
/// Send a "Data" message to the SimpleTunnel server.
74-
func sendDataMessage(data: NSData, extraProperties: [String: AnyObject] = [:]) {
75-
dispatch_async(queue) {
74+
func sendDataMessage(_ data: Data, extraProperties: [String: AnyObject] = [:]) {
75+
queue.async {
7676

7777
guard let clientTunnel = self.tunnel as? ClientTunnel else { return }
7878

7979
// Suspend further writes to the tunnel until this write operation is completed.
80-
dispatch_suspend(self.queue)
80+
self.queue.suspend()
8181

8282
var dataProperties = extraProperties
83-
dataProperties[TunnelMessageKey.Data.rawValue] = data
83+
dataProperties[TunnelMessageKey.Data.rawValue] = data as AnyObject?
8484

85-
let properties = createMessagePropertiesForConnection(self.identifier, commandType: .Data, extraProperties:dataProperties)
85+
let properties = createMessagePropertiesForConnection(self.identifier, commandType: .data, extraProperties:dataProperties)
8686

8787
clientTunnel.sendMessage(properties) { error in
8888

8989
// Resume the queue to allow subsequent writes.
90-
dispatch_resume(self.queue)
90+
self.queue.resume()
9191

9292
// This will schedule another read operation on the NEAppProxyFlow.
9393
self.handleSendResult(error)
@@ -98,30 +98,30 @@ class ClientAppProxyConnection : Connection {
9898
// MARK: Connection
9999

100100
/// Handle the "Open Completed" message received from the SimpleTunnel server for this connection.
101-
override func handleOpenCompleted(resultCode: TunnelConnectionOpenResult, properties: [NSObject: AnyObject]) {
102-
guard resultCode == .Success else {
101+
override func handleOpenCompleted(_ resultCode: TunnelConnectionOpenResult, properties: [NSObject: AnyObject]) {
102+
guard resultCode == .success else {
103103
simpleTunnelLog("Failed to open \(identifier), result = \(resultCode)")
104-
handleErrorCondition(.PeerReset, notifyServer: false)
104+
handleErrorCondition(.peerReset, notifyServer: false)
105105
return
106106
}
107107

108108
guard let localAddress = (tunnel as? ClientTunnel)?.connection!.localAddress as? NWHostEndpoint else {
109109
simpleTunnelLog("Failed to get localAddress.")
110-
handleErrorCondition(.Internal)
110+
handleErrorCondition(.internal)
111111
return
112112
}
113113

114114
// Now that the SimpleTunnel connection is open, indicate that we are ready to handle data on the NEAppProxyFlow.
115-
appProxyFlow.openWithLocalEndpoint(localAddress) { error in
116-
self.handleSendResult(error)
115+
appProxyFlow.open(withLocalEndpoint: localAddress) { error in
116+
self.handleSendResult(error as NSError?)
117117
}
118118
}
119119

120-
override func closeConnection(direction: TunnelConnectionCloseDirection) {
120+
override func closeConnection(_ direction: TunnelConnectionCloseDirection) {
121121
self.closeConnection(direction, flowError: nil)
122122
}
123123

124-
func closeConnection(direction: TunnelConnectionCloseDirection, flowError: NEAppProxyFlowError?) {
124+
func closeConnection(_ direction: TunnelConnectionCloseDirection, flowError: NEAppProxyErrorDomain?) {
125125
super.closeConnection(direction)
126126

127127
var error: NSError?
@@ -159,32 +159,32 @@ class ClientAppProxyTCPConnection : ClientAppProxyConnection {
159159
/// Send an "Open" message to the SimpleTunnel server, to begin the process of establishing a flow of data in the SimpleTunnel protocol.
160160
override func open() {
161161
open([
162-
TunnelMessageKey.TunnelType.rawValue: TunnelLayer.App.rawValue,
163-
TunnelMessageKey.Host.rawValue: (TCPFlow.remoteEndpoint as! NWHostEndpoint).hostname,
164-
TunnelMessageKey.Port.rawValue: Int((TCPFlow.remoteEndpoint as! NWHostEndpoint).port)!,
165-
TunnelMessageKey.AppProxyFlowType.rawValue: AppProxyFlowKind.TCP.rawValue
162+
TunnelMessageKey.TunnelType.rawValue: TunnelLayer.app.rawValue as AnyObject,
163+
TunnelMessageKey.Host.rawValue: (TCPFlow.remoteEndpoint as! NWHostEndpoint).hostname as AnyObject,
164+
TunnelMessageKey.Port.rawValue: Int((TCPFlow.remoteEndpoint as! NWHostEndpoint).port)! as AnyObject,
165+
TunnelMessageKey.AppProxyFlowType.rawValue: AppProxyFlowKind.tcp.rawValue as AnyObject
166166
])
167167
}
168168

169169
/// Handle the result of sending a "Data" message to the SimpleTunnel server.
170-
override func handleSendResult(error: NSError?) {
170+
override func handleSendResult(_ error: NSError?) {
171171
if let sendError = error {
172172
simpleTunnelLog("Failed to send Data Message to the Tunnel Server. error = \(sendError)")
173-
handleErrorCondition(.HostUnreachable)
173+
handleErrorCondition(.hostUnreachable)
174174
return
175175
}
176176

177177
// Read another chunk of data from the source application.
178-
TCPFlow.readDataWithCompletionHandler { data, readError in
179-
guard let readData = data where readError == nil else {
178+
TCPFlow.readData { data, readError in
179+
guard let readData = data , readError == nil else {
180180
simpleTunnelLog("Failed to read data from the TCP flow. error = \(readError)")
181-
self.handleErrorCondition(.PeerReset)
181+
self.handleErrorCondition(.peerReset)
182182
return
183183
}
184184

185-
guard readData.length > 0 else {
185+
guard readData.count > 0 else {
186186
simpleTunnelLog("\(self.identifier): received EOF on the TCP flow. Closing the flow...")
187-
self.tunnel?.sendCloseType(.Write, forConnection: self.identifier)
187+
self.tunnel?.sendCloseType(.write, forConnection: self.identifier)
188188
self.TCPFlow.closeReadWithError(nil)
189189
return
190190
}
@@ -194,11 +194,11 @@ class ClientAppProxyTCPConnection : ClientAppProxyConnection {
194194
}
195195

196196
/// Send data received from the SimpleTunnel server to the destination application, using the NEAppProxyTCPFlow object.
197-
override func sendData(data: NSData) {
198-
TCPFlow.writeData(data) { error in
197+
override func sendData(_ data: Data) {
198+
TCPFlow.write(data) { error in
199199
if let writeError = error {
200200
simpleTunnelLog("Failed to write data to the TCP flow. error = \(writeError)")
201-
self.tunnel?.sendCloseType(.Read, forConnection: self.identifier)
201+
self.tunnel?.sendCloseType(.read, forConnection: self.identifier)
202202
self.TCPFlow.closeWriteWithError(nil)
203203
}
204204
}
@@ -229,17 +229,17 @@ class ClientAppProxyUDPConnection : ClientAppProxyConnection {
229229
/// Send an "Open" message to the SimpleTunnel server, to begin the process of establishing a flow of data in the SimpleTunnel protocol.
230230
override func open() {
231231
open([
232-
TunnelMessageKey.TunnelType.rawValue: TunnelLayer.App.rawValue,
233-
TunnelMessageKey.AppProxyFlowType.rawValue: AppProxyFlowKind.UDP.rawValue
232+
TunnelMessageKey.TunnelType.rawValue: TunnelLayer.app.rawValue as AnyObject,
233+
TunnelMessageKey.AppProxyFlowType.rawValue: AppProxyFlowKind.udp.rawValue as AnyObject
234234
])
235235
}
236236

237237
/// Handle the result of sending a "Data" message to the SimpleTunnel server.
238-
override func handleSendResult(error: NSError?) {
238+
override func handleSendResult(_ error: NSError?) {
239239

240240
if let sendError = error {
241241
simpleTunnelLog("Failed to send message to Tunnel Server. error = \(sendError)")
242-
handleErrorCondition(.HostUnreachable)
242+
handleErrorCondition(.hostUnreachable)
243243
return
244244
}
245245

@@ -251,50 +251,50 @@ class ClientAppProxyUDPConnection : ClientAppProxyConnection {
251251
guard datagramsOutstanding == 0 else { return }
252252

253253
// Read a new set of datagrams from the source application.
254-
UDPFlow.readDatagramsWithCompletionHandler { datagrams, remoteEndPoints, readError in
254+
UDPFlow.readDatagrams { datagrams, remoteEndPoints, readError in
255255

256256
guard let readDatagrams = datagrams,
257-
readEndpoints = remoteEndPoints
258-
where readError == nil else
257+
let readEndpoints = remoteEndPoints
258+
, readError == nil else
259259
{
260260
simpleTunnelLog("Failed to read data from the UDP flow. error = \(readError)")
261-
self.handleErrorCondition(.PeerReset)
261+
self.handleErrorCondition(.peerReset)
262262
return
263263
}
264264

265265
guard !readDatagrams.isEmpty && readEndpoints.count == readDatagrams.count else {
266266
simpleTunnelLog("\(self.identifier): Received EOF on the UDP flow. Closing the flow...")
267-
self.tunnel?.sendCloseType(.Write, forConnection: self.identifier)
267+
self.tunnel?.sendCloseType(.write, forConnection: self.identifier)
268268
self.UDPFlow.closeReadWithError(nil)
269269
return
270270
}
271271

272272
self.datagramsOutstanding = readDatagrams.count
273273

274-
for (index, datagram) in readDatagrams.enumerate() {
274+
for (index, datagram) in readDatagrams.enumerated() {
275275
guard let endpoint = readEndpoints[index] as? NWHostEndpoint else { continue }
276276

277-
simpleTunnelLog("(\(self.identifier)): Sending a \(datagram.length)-byte datagram to \(endpoint.hostname):\(endpoint.port)")
277+
simpleTunnelLog("(\(self.identifier)): Sending a \(datagram.count)-byte datagram to \(endpoint.hostname):\(endpoint.port)")
278278

279279
// Send a data message to the SimpleTunnel server.
280280
self.sendDataMessage(datagram, extraProperties:[
281-
TunnelMessageKey.Host.rawValue: endpoint.hostname,
282-
TunnelMessageKey.Port.rawValue: Int(endpoint.port)!
281+
TunnelMessageKey.Host.rawValue: endpoint.hostname as AnyObject,
282+
TunnelMessageKey.Port.rawValue: Int(endpoint.port)! as AnyObject
283283
])
284284
}
285285
}
286286
}
287287

288288
/// Send a datagram received from the SimpleTunnel server to the destination application.
289-
override func sendDataWithEndPoint(data: NSData, host: String, port: Int) {
289+
override func sendDataWithEndPoint(_ data: Data, host: String, port: Int) {
290290
let datagrams = [ data ]
291291
let endpoints = [ NWHostEndpoint(hostname: host, port: String(port)) ]
292292

293293
// Send the datagram to the destination application.
294-
UDPFlow.writeDatagrams(datagrams, sentByEndpoints: endpoints) { error in
294+
UDPFlow.writeDatagrams(datagrams, sentBy: endpoints) { error in
295295
if let error = error {
296296
simpleTunnelLog("Failed to write datagrams to the UDP Flow: \(error)")
297-
self.tunnel?.sendCloseType(.Read, forConnection: self.identifier)
297+
self.tunnel?.sendCloseType(.read, forConnection: self.identifier)
298298
self.UDPFlow.closeWriteWithError(nil)
299299
}
300300
}

0 commit comments

Comments
 (0)