Move logic to extension: Refactor PacketTunnelOptionsGenerator into a PacketTunnelSettingsGenerator

Signed-off-by: Roopesh Chander <roop@roopc.net>
This commit is contained in:
Roopesh Chander
2018-11-08 15:44:13 +05:30
parent 2f7e437202
commit af58bfcb00
2 changed files with 67 additions and 42 deletions
@@ -3,29 +3,30 @@
import Foundation
import Network
import NetworkExtension
class PacketTunnelOptionsGenerator {
static func generateOptions(from tc: TunnelConfiguration,
withResolvedEndpoints resolvedEndpoints: [Endpoint?]) -> [String: NSObject] {
var options: [String: NSObject] = [:]
class PacketTunnelSettingsGenerator {
// Interface name
let tunnelConfiguration: TunnelConfiguration
let resolvedEndpoints: [Endpoint?]
options[.interfaceName] = tc.interface.name as NSObject
// WireGuard settings
init(tunnelConfiguration: TunnelConfiguration, resolvedEndpoints: [Endpoint?]) {
self.tunnelConfiguration = tunnelConfiguration
self.resolvedEndpoints = resolvedEndpoints
}
func generateWireGuardSettings() -> String {
var wgSettings = ""
let privateKey = tc.interface.privateKey.hexEncodedString()
let privateKey = tunnelConfiguration.interface.privateKey.hexEncodedString()
wgSettings.append("private_key=\(privateKey)\n")
if let listenPort = tc.interface.listenPort {
if let listenPort = tunnelConfiguration.interface.listenPort {
wgSettings.append("listen_port=\(listenPort)\n")
}
if (tc.peers.count > 0) {
if (tunnelConfiguration.peers.count > 0) {
wgSettings.append("replace_peers=true\n")
}
assert(tc.peers.count == resolvedEndpoints.count)
for (i, peer) in tc.peers.enumerated() {
assert(tunnelConfiguration.peers.count == resolvedEndpoints.count)
for (i, peer) in tunnelConfiguration.peers.enumerated() {
wgSettings.append("public_key=\(peer.publicKey.hexEncodedString())\n")
if let preSharedKey = peer.preSharedKey {
wgSettings.append("preshared_key=\(preSharedKey.hexEncodedString())\n")
@@ -43,8 +44,10 @@ class PacketTunnelOptionsGenerator {
}
}
}
return wgSettings
}
options[.wireguardSettings] = wgSettings as NSObject
func generateNetworkSettings() -> NEPacketTunnelNetworkSettings {
// Remote address
@@ -67,15 +70,22 @@ class PacketTunnelOptionsGenerator {
}
}
options[.remoteAddress] = remoteAddress as NSObject
let networkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: remoteAddress)
// DNS
options[.dnsServers] = tc.interface.dns.map { $0.stringRepresentation() } as NSObject
let dnsServerStrings = tunnelConfiguration.interface.dns.map { $0.stringRepresentation() }
networkSettings.dnsSettings = NEDNSSettings(servers: dnsServerStrings)
// MTU
options[.mtu] = NSNumber(value: tc.interface.mtu ?? 0) // 0 implies auto-MTU
let mtu = tunnelConfiguration.interface.mtu ?? 0
if (mtu == 0) {
// 0 imples automatic MTU, where we set overhead as 80 bytes, which is the worst case for WireGuard
networkSettings.tunnelOverheadBytes = 80
} else {
networkSettings.mtu = NSNumber(value: mtu)
}
// Addresses from interface addresses
@@ -85,22 +95,16 @@ class PacketTunnelOptionsGenerator {
var ipv6Addresses: [String] = []
var ipv6NetworkPrefixLengths: [NSNumber] = []
for addressRange in tc.interface.addresses {
for addressRange in tunnelConfiguration.interface.addresses {
if (addressRange.address is IPv4Address) {
ipv4Addresses.append("\(addressRange.address)")
ipv4SubnetMasks.append(ipv4SubnetMaskString(of: addressRange))
ipv4SubnetMasks.append(PacketTunnelSettingsGenerator.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] = []
@@ -109,11 +113,11 @@ class PacketTunnelOptionsGenerator {
var ipv6IncludedRouteAddresses: [String] = []
var ipv6IncludedRouteNetworkPrefixLengths: [NSNumber] = []
for peer in tc.peers {
for peer in tunnelConfiguration.peers {
for addressRange in peer.allowedIPs {
if (addressRange.address is IPv4Address) {
ipv4IncludedRouteAddresses.append("\(addressRange.address)")
ipv4IncludedRouteSubnetMasks.append(ipv4SubnetMaskString(of: addressRange))
ipv4IncludedRouteSubnetMasks.append(PacketTunnelSettingsGenerator.ipv4SubnetMaskString(of: addressRange))
} else if (addressRange.address is IPv6Address) {
ipv6IncludedRouteAddresses.append("\(addressRange.address)")
ipv6IncludedRouteNetworkPrefixLengths.append(NSNumber(value: addressRange.networkPrefixLength))
@@ -121,12 +125,6 @@ class PacketTunnelOptionsGenerator {
}
}
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] = []
@@ -149,13 +147,40 @@ class PacketTunnelOptionsGenerator {
}
}
options[.ipv4ExcludedRouteAddresses] = ipv4ExcludedRouteAddresses as NSObject
options[.ipv4ExcludedRouteSubnetMasks] = ipv4ExcludedRouteSubnetMasks as NSObject
// Apply IPv4 settings
options[.ipv6ExcludedRouteAddresses] = ipv6ExcludedRouteAddresses as NSObject
options[.ipv6ExcludedRouteNetworkPrefixLengths] = ipv6ExcludedRouteNetworkPrefixLengths as NSObject
let ipv4Settings = NEIPv4Settings(addresses: ipv4Addresses, subnetMasks: ipv4SubnetMasks)
assert(ipv4IncludedRouteAddresses.count == ipv4IncludedRouteSubnetMasks.count)
ipv4Settings.includedRoutes = zip(ipv4IncludedRouteAddresses, ipv4IncludedRouteSubnetMasks).map {
NEIPv4Route(destinationAddress: $0.0, subnetMask: $0.1)
}
assert(ipv4ExcludedRouteAddresses.count == ipv4ExcludedRouteSubnetMasks.count)
ipv4Settings.excludedRoutes = zip(ipv4ExcludedRouteAddresses, ipv4ExcludedRouteSubnetMasks).map {
NEIPv4Route(destinationAddress: $0.0, subnetMask: $0.1)
}
networkSettings.ipv4Settings = ipv4Settings
return options
// Apply IPv6 settings
/* Big fat ugly hack for broken iOS networking stack: the smallest prefix that will have
* any effect on iOS is a /120, so we clamp everything above to /120. This is potentially
* very bad, if various network parameters were actually relying on that subnet being
* intentionally small. TODO: talk about this with upstream iOS devs.
*/
let ipv6Settings = NEIPv6Settings(addresses: ipv6Addresses, networkPrefixLengths: ipv6NetworkPrefixLengths.map { NSNumber(value: min(120, $0.intValue)) })
assert(ipv6IncludedRouteAddresses.count == ipv6IncludedRouteNetworkPrefixLengths.count)
ipv6Settings.includedRoutes = zip(ipv6IncludedRouteAddresses, ipv6IncludedRouteNetworkPrefixLengths).map {
NEIPv6Route(destinationAddress: $0.0, networkPrefixLength: $0.1)
}
assert(ipv6ExcludedRouteAddresses.count == ipv6ExcludedRouteNetworkPrefixLengths.count)
ipv6Settings.excludedRoutes = zip(ipv6ExcludedRouteAddresses, ipv6ExcludedRouteNetworkPrefixLengths).map {
NEIPv6Route(destinationAddress: $0.0, networkPrefixLength: $0.1)
}
networkSettings.ipv6Settings = ipv6Settings
// Done
return networkSettings
}
static func ipv4SubnetMaskString(of addressRange: IPAddressRange) -> String {