diff --git a/.gitignore b/.gitignore index 74364af..d203206 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,6 @@ fastlane/screenshots fastlane/test_output Preview.html output + +# Wireguard specific +WireGuard/WireGuard/Config/Developer.xcconfig diff --git a/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift b/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift index 11d8ebc..1a51573 100644 --- a/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift +++ b/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift @@ -1,8 +1,9 @@ // SPDX-License-Identifier: MIT // Copyright © 2018 WireGuard LLC. All Rights Reserved. -import NetworkExtension import Foundation +import Network +import NetworkExtension import os.log enum PacketTunnelProviderError: Error { @@ -20,9 +21,15 @@ class PacketTunnelProvider: NEPacketTunnelProvider { // MARK: Properties private var wgHandle: Int32? + + private var networkMonitor: NWPathMonitor? // MARK: NEPacketTunnelProvider + deinit { + networkMonitor?.cancel() + } + /// Begin the process of establishing the tunnel. override func startTunnel(options: [String: NSObject]?, completionHandler startTunnelCompletionHandler: @escaping (Error?) -> Void) { @@ -106,10 +113,27 @@ class PacketTunnelProvider: NEPacketTunnelProvider { startTunnelCompletionHandler(nil /* No errors */) } } + + networkMonitor = NWPathMonitor() + networkMonitor?.pathUpdateHandler = { path in + if path.status == .satisfied { + let endpointString = packetTunnelSettingsGenerator.endpointFromSettings() + + let endpointGoString = endpointString.withCString { + gostring_t(p: $0, n: endpointString.utf8.count) + } + + wgSetConfig(handle, endpointGoString) + } + } + networkMonitor?.start(queue: DispatchQueue(label: "NetworkMonitor")) } /// Begin the process of stopping the tunnel. override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { + networkMonitor?.cancel() + networkMonitor = nil + wg_log(.info, staticMessage: "Stopping tunnel") if let handle = wgHandle { wgTurnOff(handle) diff --git a/WireGuard/WireGuardNetworkExtension/PacketTunnelSettingsGenerator.swift b/WireGuard/WireGuardNetworkExtension/PacketTunnelSettingsGenerator.swift index 4007196..906aea9 100644 --- a/WireGuard/WireGuardNetworkExtension/PacketTunnelSettingsGenerator.swift +++ b/WireGuard/WireGuardNetworkExtension/PacketTunnelSettingsGenerator.swift @@ -15,6 +15,20 @@ class PacketTunnelSettingsGenerator { self.resolvedEndpoints = resolvedEndpoints } + func endpointFromSettings() -> String { + var wgSettings = "listen_port=\(tunnelConfiguration.interface.listenPort ?? 0)\n" + + for (i, peer) in tunnelConfiguration.peers.enumerated() { + wgSettings.append("public_key=\(peer.publicKey.hexEncodedString())\n") + if let endpoint = resolvedEndpoints[i] { + if case .name(_, _) = endpoint.host { assert(false, "Endpoint is not resolved") } + wgSettings.append("endpoint=\(endpoint.stringRepresentation())\n") + } + } + + return wgSettings + } + func generateWireGuardSettings() -> String { var wgSettings = "" let privateKey = tunnelConfiguration.interface.privateKey.hexEncodedString()