From fb6a7f6007ef55668b42297abdb4d6adb9127de5 Mon Sep 17 00:00:00 2001 From: Roopesh Chander Date: Thu, 8 Nov 2018 14:16:30 +0530 Subject: Move logic to extension: Move PacketTunnelOptionsGenerator to the extension Signed-off-by: Roopesh Chander --- WireGuard/WireGuard.xcodeproj/project.pbxproj | 6 +- .../VPN/PacketTunnelOptionsGenerator.swift | 178 --------------------- .../PacketTunnelOptionsGenerator.swift | 178 +++++++++++++++++++++ 3 files changed, 181 insertions(+), 181 deletions(-) delete mode 100644 WireGuard/WireGuard/VPN/PacketTunnelOptionsGenerator.swift create mode 100644 WireGuard/WireGuardNetworkExtension/PacketTunnelOptionsGenerator.swift (limited to 'WireGuard') diff --git a/WireGuard/WireGuard.xcodeproj/project.pbxproj b/WireGuard/WireGuard.xcodeproj/project.pbxproj index 6ca6160..8ff5898 100644 --- a/WireGuard/WireGuard.xcodeproj/project.pbxproj +++ b/WireGuard/WireGuard.xcodeproj/project.pbxproj @@ -14,7 +14,6 @@ 6F5D0C22218352EF000F85AD /* WireGuardNetworkExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 6F5D0C1A218352EF000F85AD /* WireGuardNetworkExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 6F5D0C452183BCDA000F85AD /* PacketTunnelOptionKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F5D0C442183BCDA000F85AD /* PacketTunnelOptionKey.swift */; }; 6F5D0C462183C0B4000F85AD /* PacketTunnelOptionKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F5D0C442183BCDA000F85AD /* PacketTunnelOptionKey.swift */; }; - 6F5D0C482183C6A3000F85AD /* PacketTunnelOptionsGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F5D0C472183C6A3000F85AD /* PacketTunnelOptionsGenerator.swift */; }; 6F628C3D217F09E9003482A3 /* TunnelViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C3C217F09E9003482A3 /* TunnelViewModel.swift */; }; 6F628C3F217F3413003482A3 /* DNSServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C3E217F3413003482A3 /* DNSServer.swift */; }; 6F628C41217F47DB003482A3 /* TunnelDetailTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C40217F47DB003482A3 /* TunnelDetailTableViewController.swift */; }; @@ -44,6 +43,7 @@ 6FDEF8082187442100D8FBF6 /* WgQuickConfigFileWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FDEF8072187442100D8FBF6 /* WgQuickConfigFileWriter.swift */; }; 6FF4AC1F211EC472002C96EB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6FF4AC1E211EC472002C96EB /* Assets.xcassets */; }; 6FF4AC22211EC472002C96EB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6FF4AC20211EC472002C96EB /* LaunchScreen.storyboard */; }; + 6FFA5D8921942F320001E2F7 /* PacketTunnelOptionsGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F5D0C472183C6A3000F85AD /* PacketTunnelOptionsGenerator.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -152,6 +152,7 @@ isa = PBXGroup; children = ( 6F5D0C1C218352EF000F85AD /* PacketTunnelProvider.swift */, + 6F5D0C472183C6A3000F85AD /* PacketTunnelOptionsGenerator.swift */, 6F5D0C1E218352EF000F85AD /* Info.plist */, 6F5D0C1F218352EF000F85AD /* WireGuardNetworkExtension.entitlements */, 6F5D0C3421839E37000F85AD /* WireGuardNetworkExtension-Bridging-Header.h */, @@ -229,7 +230,6 @@ children = ( 6F7774EE21722D97006A79B3 /* TunnelsManager.swift */, 6F5D0C1421832391000F85AD /* DNSResolver.swift */, - 6F5D0C472183C6A3000F85AD /* PacketTunnelOptionsGenerator.swift */, ); path = VPN; sourceTree = ""; @@ -488,6 +488,7 @@ buildActionMask = 2147483647; files = ( 6F5D0C462183C0B4000F85AD /* PacketTunnelOptionKey.swift in Sources */, + 6FFA5D8921942F320001E2F7 /* PacketTunnelOptionsGenerator.swift in Sources */, 6F5D0C1D218352EF000F85AD /* PacketTunnelProvider.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -500,7 +501,6 @@ 6F7774E421718281006A79B3 /* TunnelsListTableViewController.swift in Sources */, 6F7774EF21722D97006A79B3 /* TunnelsManager.swift in Sources */, 6F5D0C1521832391000F85AD /* DNSResolver.swift in Sources */, - 6F5D0C482183C6A3000F85AD /* PacketTunnelOptionsGenerator.swift in Sources */, 6BB8400421892C920003598F /* CopyableLabelTableViewCell.swift in Sources */, 6F693A562179E556008551C1 /* Endpoint.swift in Sources */, 6F0068572191AFD200419BE9 /* ScrollableLabel.swift in Sources */, diff --git a/WireGuard/WireGuard/VPN/PacketTunnelOptionsGenerator.swift b/WireGuard/WireGuard/VPN/PacketTunnelOptionsGenerator.swift deleted file mode 100644 index 3eabde7..0000000 --- a/WireGuard/WireGuard/VPN/PacketTunnelOptionsGenerator.swift +++ /dev/null @@ -1,178 +0,0 @@ -// SPDX-License-Identifier: MIT -// Copyright © 2018 WireGuard LLC. All Rights Reserved. - -import Foundation -import Network - -class PacketTunnelOptionsGenerator { - static func generateOptions(from tc: TunnelConfiguration, - withResolvedEndpoints resolvedEndpoints: [Endpoint?]) -> [String: NSObject] { - var options: [String: NSObject] = [:] - - // Interface name - - options[.interfaceName] = tc.interface.name as NSObject - - // WireGuard settings - - var wgSettings = "" - let privateKey = tc.interface.privateKey.hexEncodedString() - wgSettings.append("private_key=\(privateKey)\n") - if let listenPort = tc.interface.listenPort { - wgSettings.append("listen_port=\(listenPort)\n") - } - if (tc.peers.count > 0) { - wgSettings.append("replace_peers=true\n") - } - assert(tc.peers.count == resolvedEndpoints.count) - for (i, peer) in tc.peers.enumerated() { - wgSettings.append("public_key=\(peer.publicKey.hexEncodedString())\n") - if let preSharedKey = peer.preSharedKey { - wgSettings.append("preshared_key=\(preSharedKey.hexEncodedString())\n") - } - if let endpoint = resolvedEndpoints[i] { - if case .name(_, _) = endpoint.host { assert(false, "Endpoint is not resolved") } - wgSettings.append("endpoint=\(endpoint.stringRepresentation())\n") - } - let persistentKeepAlive = peer.persistentKeepAlive ?? 0 - wgSettings.append("persistent_keepalive_interval=\(persistentKeepAlive)\n") - if (!peer.allowedIPs.isEmpty) { - wgSettings.append("replace_allowed_ips=true\n") - for ip in peer.allowedIPs { - wgSettings.append("allowed_ip=\(ip.stringRepresentation())\n") - } - } - } - - options[.wireguardSettings] = wgSettings as NSObject - - // Remote address - - /* iOS requires a tunnel endpoint, whereas in WireGuard it's valid for - * a tunnel to have no endpoint, or for there to be many endpoints, in - * which case, displaying a single one in settings doesn't really - * make sense. So, we fill it in with this placeholder, which is not - * a valid IP address that will actually route over the Internet. - */ - var remoteAddress: String = "0.0.0.0" - let endpointsCompact = resolvedEndpoints.compactMap({ $0 }) - if endpointsCompact.count == 1 { - switch (endpointsCompact.first!.host) { - case .ipv4(let address): - remoteAddress = "\(address)" - case .ipv6(let address): - remoteAddress = "\(address)" - default: - break - } - } - - options[.remoteAddress] = remoteAddress as NSObject - - // DNS - - options[.dnsServers] = tc.interface.dns.map { $0.stringRepresentation() } as NSObject - - // MTU - - options[.mtu] = NSNumber(value: tc.interface.mtu ?? 0) // 0 implies auto-MTU - - // Addresses from interface addresses - - var ipv4Addresses: [String] = [] - var ipv4SubnetMasks: [String] = [] - - var ipv6Addresses: [String] = [] - var ipv6NetworkPrefixLengths: [NSNumber] = [] - - for addressRange in tc.interface.addresses { - if (addressRange.address is IPv4Address) { - ipv4Addresses.append("\(addressRange.address)") - ipv4SubnetMasks.append(ipv4SubnetMaskString(of: addressRange)) - } else if (addressRange.address is IPv6Address) { - ipv6Addresses.append("\(addressRange.address)") - ipv6NetworkPrefixLengths.append(NSNumber(value: addressRange.networkPrefixLength)) - } - } - - options[.ipv4Addresses] = ipv4Addresses as NSObject - options[.ipv4SubnetMasks] = ipv4SubnetMasks as NSObject - - options[.ipv6Addresses] = ipv6Addresses as NSObject - options[.ipv6NetworkPrefixLengths] = ipv6NetworkPrefixLengths as NSObject - - // Included routes from AllowedIPs - - var ipv4IncludedRouteAddresses: [String] = [] - var ipv4IncludedRouteSubnetMasks: [String] = [] - - var ipv6IncludedRouteAddresses: [String] = [] - var ipv6IncludedRouteNetworkPrefixLengths: [NSNumber] = [] - - for peer in tc.peers { - for addressRange in peer.allowedIPs { - if (addressRange.address is IPv4Address) { - ipv4IncludedRouteAddresses.append("\(addressRange.address)") - ipv4IncludedRouteSubnetMasks.append(ipv4SubnetMaskString(of: addressRange)) - } else if (addressRange.address is IPv6Address) { - ipv6IncludedRouteAddresses.append("\(addressRange.address)") - ipv6IncludedRouteNetworkPrefixLengths.append(NSNumber(value: addressRange.networkPrefixLength)) - } - } - } - - options[.ipv4IncludedRouteAddresses] = ipv4IncludedRouteAddresses as NSObject - options[.ipv4IncludedRouteSubnetMasks] = ipv4IncludedRouteSubnetMasks as NSObject - - options[.ipv6IncludedRouteAddresses] = ipv6IncludedRouteAddresses as NSObject - options[.ipv6IncludedRouteNetworkPrefixLengths] = ipv6IncludedRouteNetworkPrefixLengths as NSObject - - // Excluded routes from endpoints - - var ipv4ExcludedRouteAddresses: [String] = [] - var ipv4ExcludedRouteSubnetMasks: [String] = [] - - var ipv6ExcludedRouteAddresses: [String] = [] - var ipv6ExcludedRouteNetworkPrefixLengths: [NSNumber] = [] - - for endpoint in resolvedEndpoints { - guard let endpoint = endpoint else { continue } - switch (endpoint.host) { - case .ipv4(let address): - ipv4ExcludedRouteAddresses.append("\(address)") - ipv4ExcludedRouteSubnetMasks.append("255.255.255.255") // A single IPv4 address - case .ipv6(let address): - ipv6ExcludedRouteAddresses.append("\(address)") - ipv6ExcludedRouteNetworkPrefixLengths.append(NSNumber(value: UInt8(128))) // A single IPv6 address - default: - fatalError() - } - } - - options[.ipv4ExcludedRouteAddresses] = ipv4ExcludedRouteAddresses as NSObject - options[.ipv4ExcludedRouteSubnetMasks] = ipv4ExcludedRouteSubnetMasks as NSObject - - options[.ipv6ExcludedRouteAddresses] = ipv6ExcludedRouteAddresses as NSObject - options[.ipv6ExcludedRouteNetworkPrefixLengths] = ipv6ExcludedRouteNetworkPrefixLengths as NSObject - - return options - } - - static func ipv4SubnetMaskString(of addressRange: IPAddressRange) -> String { - let n: UInt8 = addressRange.networkPrefixLength - assert(n <= 32) - var octets: [UInt8] = [0, 0, 0, 0] - let subnetMask: UInt32 = n > 0 ? ~UInt32(0) << (32 - n) : UInt32(0) - octets[0] = UInt8(truncatingIfNeeded: subnetMask >> 24) - octets[1] = UInt8(truncatingIfNeeded: subnetMask >> 16) - octets[2] = UInt8(truncatingIfNeeded: subnetMask >> 8) - octets[3] = UInt8(truncatingIfNeeded: subnetMask) - return octets.map { String($0) }.joined(separator: ".") - } -} - -private extension Data { - func hexEncodedString() -> String { - return self.map { String(format: "%02x", $0) }.joined() - } -} diff --git a/WireGuard/WireGuardNetworkExtension/PacketTunnelOptionsGenerator.swift b/WireGuard/WireGuardNetworkExtension/PacketTunnelOptionsGenerator.swift new file mode 100644 index 0000000..3eabde7 --- /dev/null +++ b/WireGuard/WireGuardNetworkExtension/PacketTunnelOptionsGenerator.swift @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: MIT +// Copyright © 2018 WireGuard LLC. All Rights Reserved. + +import Foundation +import Network + +class PacketTunnelOptionsGenerator { + static func generateOptions(from tc: TunnelConfiguration, + withResolvedEndpoints resolvedEndpoints: [Endpoint?]) -> [String: NSObject] { + var options: [String: NSObject] = [:] + + // Interface name + + options[.interfaceName] = tc.interface.name as NSObject + + // WireGuard settings + + var wgSettings = "" + let privateKey = tc.interface.privateKey.hexEncodedString() + wgSettings.append("private_key=\(privateKey)\n") + if let listenPort = tc.interface.listenPort { + wgSettings.append("listen_port=\(listenPort)\n") + } + if (tc.peers.count > 0) { + wgSettings.append("replace_peers=true\n") + } + assert(tc.peers.count == resolvedEndpoints.count) + for (i, peer) in tc.peers.enumerated() { + wgSettings.append("public_key=\(peer.publicKey.hexEncodedString())\n") + if let preSharedKey = peer.preSharedKey { + wgSettings.append("preshared_key=\(preSharedKey.hexEncodedString())\n") + } + if let endpoint = resolvedEndpoints[i] { + if case .name(_, _) = endpoint.host { assert(false, "Endpoint is not resolved") } + wgSettings.append("endpoint=\(endpoint.stringRepresentation())\n") + } + let persistentKeepAlive = peer.persistentKeepAlive ?? 0 + wgSettings.append("persistent_keepalive_interval=\(persistentKeepAlive)\n") + if (!peer.allowedIPs.isEmpty) { + wgSettings.append("replace_allowed_ips=true\n") + for ip in peer.allowedIPs { + wgSettings.append("allowed_ip=\(ip.stringRepresentation())\n") + } + } + } + + options[.wireguardSettings] = wgSettings as NSObject + + // Remote address + + /* iOS requires a tunnel endpoint, whereas in WireGuard it's valid for + * a tunnel to have no endpoint, or for there to be many endpoints, in + * which case, displaying a single one in settings doesn't really + * make sense. So, we fill it in with this placeholder, which is not + * a valid IP address that will actually route over the Internet. + */ + var remoteAddress: String = "0.0.0.0" + let endpointsCompact = resolvedEndpoints.compactMap({ $0 }) + if endpointsCompact.count == 1 { + switch (endpointsCompact.first!.host) { + case .ipv4(let address): + remoteAddress = "\(address)" + case .ipv6(let address): + remoteAddress = "\(address)" + default: + break + } + } + + options[.remoteAddress] = remoteAddress as NSObject + + // DNS + + options[.dnsServers] = tc.interface.dns.map { $0.stringRepresentation() } as NSObject + + // MTU + + options[.mtu] = NSNumber(value: tc.interface.mtu ?? 0) // 0 implies auto-MTU + + // Addresses from interface addresses + + var ipv4Addresses: [String] = [] + var ipv4SubnetMasks: [String] = [] + + var ipv6Addresses: [String] = [] + var ipv6NetworkPrefixLengths: [NSNumber] = [] + + for addressRange in tc.interface.addresses { + if (addressRange.address is IPv4Address) { + ipv4Addresses.append("\(addressRange.address)") + ipv4SubnetMasks.append(ipv4SubnetMaskString(of: addressRange)) + } else if (addressRange.address is IPv6Address) { + ipv6Addresses.append("\(addressRange.address)") + ipv6NetworkPrefixLengths.append(NSNumber(value: addressRange.networkPrefixLength)) + } + } + + options[.ipv4Addresses] = ipv4Addresses as NSObject + options[.ipv4SubnetMasks] = ipv4SubnetMasks as NSObject + + options[.ipv6Addresses] = ipv6Addresses as NSObject + options[.ipv6NetworkPrefixLengths] = ipv6NetworkPrefixLengths as NSObject + + // Included routes from AllowedIPs + + var ipv4IncludedRouteAddresses: [String] = [] + var ipv4IncludedRouteSubnetMasks: [String] = [] + + var ipv6IncludedRouteAddresses: [String] = [] + var ipv6IncludedRouteNetworkPrefixLengths: [NSNumber] = [] + + for peer in tc.peers { + for addressRange in peer.allowedIPs { + if (addressRange.address is IPv4Address) { + ipv4IncludedRouteAddresses.append("\(addressRange.address)") + ipv4IncludedRouteSubnetMasks.append(ipv4SubnetMaskString(of: addressRange)) + } else if (addressRange.address is IPv6Address) { + ipv6IncludedRouteAddresses.append("\(addressRange.address)") + ipv6IncludedRouteNetworkPrefixLengths.append(NSNumber(value: addressRange.networkPrefixLength)) + } + } + } + + options[.ipv4IncludedRouteAddresses] = ipv4IncludedRouteAddresses as NSObject + options[.ipv4IncludedRouteSubnetMasks] = ipv4IncludedRouteSubnetMasks as NSObject + + options[.ipv6IncludedRouteAddresses] = ipv6IncludedRouteAddresses as NSObject + options[.ipv6IncludedRouteNetworkPrefixLengths] = ipv6IncludedRouteNetworkPrefixLengths as NSObject + + // Excluded routes from endpoints + + var ipv4ExcludedRouteAddresses: [String] = [] + var ipv4ExcludedRouteSubnetMasks: [String] = [] + + var ipv6ExcludedRouteAddresses: [String] = [] + var ipv6ExcludedRouteNetworkPrefixLengths: [NSNumber] = [] + + for endpoint in resolvedEndpoints { + guard let endpoint = endpoint else { continue } + switch (endpoint.host) { + case .ipv4(let address): + ipv4ExcludedRouteAddresses.append("\(address)") + ipv4ExcludedRouteSubnetMasks.append("255.255.255.255") // A single IPv4 address + case .ipv6(let address): + ipv6ExcludedRouteAddresses.append("\(address)") + ipv6ExcludedRouteNetworkPrefixLengths.append(NSNumber(value: UInt8(128))) // A single IPv6 address + default: + fatalError() + } + } + + options[.ipv4ExcludedRouteAddresses] = ipv4ExcludedRouteAddresses as NSObject + options[.ipv4ExcludedRouteSubnetMasks] = ipv4ExcludedRouteSubnetMasks as NSObject + + options[.ipv6ExcludedRouteAddresses] = ipv6ExcludedRouteAddresses as NSObject + options[.ipv6ExcludedRouteNetworkPrefixLengths] = ipv6ExcludedRouteNetworkPrefixLengths as NSObject + + return options + } + + static func ipv4SubnetMaskString(of addressRange: IPAddressRange) -> String { + let n: UInt8 = addressRange.networkPrefixLength + assert(n <= 32) + var octets: [UInt8] = [0, 0, 0, 0] + let subnetMask: UInt32 = n > 0 ? ~UInt32(0) << (32 - n) : UInt32(0) + octets[0] = UInt8(truncatingIfNeeded: subnetMask >> 24) + octets[1] = UInt8(truncatingIfNeeded: subnetMask >> 16) + octets[2] = UInt8(truncatingIfNeeded: subnetMask >> 8) + octets[3] = UInt8(truncatingIfNeeded: subnetMask) + return octets.map { String($0) }.joined(separator: ".") + } +} + +private extension Data { + func hexEncodedString() -> String { + return self.map { String(format: "%02x", $0) }.joined() + } +} -- cgit v1.2.3-59-g8ed1b