diff --git a/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift b/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift index 33c755f..6e7c160 100644 --- a/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift +++ b/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift @@ -67,6 +67,7 @@ extension TunnelKitProvider { keepAliveInterval: nil, renegotiatesAfter: nil, dnsServers: nil, + searchDomain: nil, randomizeEndpoint: false, usesPIAPatches: nil ), @@ -189,10 +190,11 @@ extension TunnelKitProvider { } sessionConfigurationBuilder.keepAliveInterval = providerConfiguration[S.keepAlive] as? TimeInterval ?? ConfigurationBuilder.defaults.sessionConfiguration.keepAliveInterval sessionConfigurationBuilder.renegotiatesAfter = providerConfiguration[S.renegotiatesAfter] as? TimeInterval ?? ConfigurationBuilder.defaults.sessionConfiguration.renegotiatesAfter - sessionConfigurationBuilder.usesPIAPatches = providerConfiguration[S.usesPIAPatches] as? Bool ?? ConfigurationBuilder.defaults.sessionConfiguration.usesPIAPatches sessionConfigurationBuilder.checksEKU = providerConfiguration[S.checksEKU] as? Bool ?? ConfigurationBuilder.defaults.sessionConfiguration.checksEKU sessionConfigurationBuilder.dnsServers = providerConfiguration[S.dnsServers] as? [String] + sessionConfigurationBuilder.searchDomain = providerConfiguration[S.searchDomain] as? String sessionConfigurationBuilder.randomizeEndpoint = providerConfiguration[S.randomizeEndpoint] as? Bool ?? ConfigurationBuilder.defaults.sessionConfiguration.randomizeEndpoint + sessionConfigurationBuilder.usesPIAPatches = providerConfiguration[S.usesPIAPatches] as? Bool ?? ConfigurationBuilder.defaults.sessionConfiguration.usesPIAPatches sessionConfiguration = sessionConfigurationBuilder.build() shouldDebug = providerConfiguration[S.debug] as? Bool ?? ConfigurationBuilder.defaults.shouldDebug @@ -260,14 +262,16 @@ extension TunnelKitProvider { static let renegotiatesAfter = "RenegotiatesAfter" - static let usesPIAPatches = "UsesPIAPatches" - static let checksEKU = "ChecksEKU" static let dnsServers = "DNSServers" + static let searchDomain = "SearchDomain" + static let randomizeEndpoint = "RandomizeEndpoint" + static let usesPIAPatches = "UsesPIAPatches" + // MARK: Debugging static let debug = "Debug" @@ -445,18 +449,21 @@ extension TunnelKitProvider { if let renegotiatesAfterSeconds = sessionConfiguration.renegotiatesAfter { dict[S.renegotiatesAfter] = renegotiatesAfterSeconds } - if let usesPIAPatches = sessionConfiguration.usesPIAPatches { - dict[S.usesPIAPatches] = usesPIAPatches - } if let checksEKU = sessionConfiguration.checksEKU { dict[S.checksEKU] = checksEKU } if let dnsServers = sessionConfiguration.dnsServers { dict[S.dnsServers] = dnsServers } + if let searchDomain = sessionConfiguration.searchDomain { + dict[S.searchDomain] = searchDomain + } if let randomizeEndpoint = sessionConfiguration.randomizeEndpoint { dict[S.randomizeEndpoint] = randomizeEndpoint } + if let usesPIAPatches = sessionConfiguration.usesPIAPatches { + dict[S.usesPIAPatches] = usesPIAPatches + } if let debugLogFormat = debugLogFormat { dict[S.debugLogFormat] = debugLogFormat } @@ -539,6 +546,9 @@ extension TunnelKitProvider { if let dnsServers = sessionConfiguration.dnsServers { log.info("\tCustom DNS servers: \(dnsServers.maskedDescription)") } + if let searchDomain = sessionConfiguration.searchDomain { + log.info("\tCustom search domain: \(searchDomain.maskedDescription)") + } if sessionConfiguration.randomizeEndpoint ?? false { log.info("\tRandomize endpoint: true") } diff --git a/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift b/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift index 47d5405..f4631c0 100644 --- a/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift +++ b/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift @@ -466,6 +466,7 @@ extension TunnelKitProvider: SessionProxyDelegate { log.info("\tIPv4: \(reply.options.ipv4?.description ?? "not configured")") log.info("\tIPv6: \(reply.options.ipv6?.description ?? "not configured")") log.info("\tDNS: \(reply.options.dnsServers.map { $0.maskedDescription })") + log.info("\tDomain: \(reply.options.searchDomain?.maskedDescription ?? "not configured")") bringNetworkUp(remoteAddress: remoteAddress, reply: reply) { (error) in if let error = error { @@ -535,8 +536,14 @@ extension TunnelKitProvider: SessionProxyDelegate { ipv6Settings?.excludedRoutes = [] } - let dnsSettings = NEDNSSettings(servers: cfg.sessionConfiguration.dnsServers ?? reply.options.dnsServers) - + let dnsServers = cfg.sessionConfiguration.dnsServers ?? reply.options.dnsServers + let searchDomain = cfg.sessionConfiguration.searchDomain ?? reply.options.searchDomain + let dnsSettings = NEDNSSettings(servers: dnsServers) + dnsSettings.domainName = searchDomain + if let searchDomain = searchDomain { + dnsSettings.searchDomains = [searchDomain] + } + let newSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: remoteAddress) newSettings.ipv4Settings = ipv4Settings newSettings.ipv6Settings = ipv6Settings diff --git a/TunnelKit/Sources/Core/ConfigurationParser.swift b/TunnelKit/Sources/Core/ConfigurationParser.swift index a012474..bee3e85 100644 --- a/TunnelKit/Sources/Core/ConfigurationParser.swift +++ b/TunnelKit/Sources/Core/ConfigurationParser.swift @@ -115,6 +115,7 @@ public class ConfigurationParser { sessionBuilder.keepAliveInterval = options.keepAliveSeconds sessionBuilder.renegotiatesAfter = options.renegotiateAfterSeconds sessionBuilder.dnsServers = options.dnsServers + sessionBuilder.searchDomain = options.searchDomain sessionBuilder.randomizeEndpoint = options.randomizeEndpoint return ParsingResult( diff --git a/TunnelKit/Sources/Core/OptionsBundle.swift b/TunnelKit/Sources/Core/OptionsBundle.swift index 7e28626..c0bb447 100644 --- a/TunnelKit/Sources/Core/OptionsBundle.swift +++ b/TunnelKit/Sources/Core/OptionsBundle.swift @@ -87,6 +87,8 @@ public struct OptionsBundle { static let dns = NSRegularExpression("^dhcp-option +DNS6? +[\\d\\.a-fA-F:]+") + static let domain = NSRegularExpression("^dhcp-option +DOMAIN +[^ ]+") + // MARK: Unsupported // static let fragment = NSRegularExpression("^fragment +\\d+") @@ -181,6 +183,9 @@ public struct OptionsBundle { /// The DNS servers. public let dnsServers: [String] + /// The search domain. + public let searchDomain: String? + /** Parses options from an array of lines. @@ -225,6 +230,7 @@ public struct OptionsBundle { var optRoutes4: [(String, String, String?)] = [] // address, netmask, gateway var optRoutes6: [(String, UInt8, String?)] = [] // destination, prefix, gateway var optDNSServers: [String] = [] + var optSearchDomain: String? log.verbose("Configuration file:") for line in lines { @@ -495,6 +501,12 @@ public struct OptionsBundle { } optDNSServers.append($0[1]) } + Regex.domain.enumerateArguments(in: line) { + guard $0.count == 2 else { + return + } + optSearchDomain = $0[1] + } // @@ -654,6 +666,7 @@ public struct OptionsBundle { } dnsServers = optDNSServers + searchDomain = optSearchDomain } private static func normalizeEncryptedPEMBlock(block: inout [String]) { diff --git a/TunnelKit/Sources/Core/SessionProxy+Configuration.swift b/TunnelKit/Sources/Core/SessionProxy+Configuration.swift index 0db65ea..bc60478 100644 --- a/TunnelKit/Sources/Core/SessionProxy+Configuration.swift +++ b/TunnelKit/Sources/Core/SessionProxy+Configuration.swift @@ -171,6 +171,9 @@ extension SessionProxy { /// - Seealso: `OptionsBundle.dnsServers` public var dnsServers: [String]? + /// - Seealso: `OptionsBundle.searchDomain` + public var searchDomain: String? + /// - Seealso: `OptionsBundle.randomizeEndpoint` public var randomizeEndpoint: Bool? @@ -191,6 +194,7 @@ extension SessionProxy { keepAliveInterval = nil renegotiatesAfter = nil dnsServers = nil + searchDomain = nil randomizeEndpoint = false usesPIAPatches = false } @@ -214,6 +218,7 @@ extension SessionProxy { keepAliveInterval: keepAliveInterval, renegotiatesAfter: renegotiatesAfter, dnsServers: dnsServers, + searchDomain: searchDomain, randomizeEndpoint: randomizeEndpoint, usesPIAPatches: usesPIAPatches ) @@ -259,6 +264,9 @@ extension SessionProxy { /// - Seealso: `SessionProxy.ConfigurationBuilder.dnsServers` public let dnsServers: [String]? + /// - Seealso: `SessionProxy.ConfigurationBuilder.searchDomain` + public let searchDomain: String? + /// - Seealso: `SessionProxy.ConfigurationBuilder.randomizeEndpoint` public let randomizeEndpoint: Bool? @@ -283,6 +291,7 @@ extension SessionProxy { builder.keepAliveInterval = keepAliveInterval builder.renegotiatesAfter = renegotiatesAfter builder.dnsServers = dnsServers + builder.searchDomain = searchDomain builder.randomizeEndpoint = randomizeEndpoint builder.usesPIAPatches = usesPIAPatches return builder @@ -304,6 +313,7 @@ extension SessionProxy { (lhs.keepAliveInterval == rhs.keepAliveInterval) && (lhs.renegotiatesAfter == rhs.renegotiatesAfter) && (lhs.dnsServers == rhs.dnsServers) && + (lhs.searchDomain == rhs.searchDomain) && (lhs.randomizeEndpoint == rhs.randomizeEndpoint) && (lhs.usesPIAPatches == rhs.usesPIAPatches) } diff --git a/TunnelKitTests/OptionsBundleTests.swift b/TunnelKitTests/OptionsBundleTests.swift index c9852af..66af67d 100644 --- a/TunnelKitTests/OptionsBundleTests.swift +++ b/TunnelKitTests/OptionsBundleTests.swift @@ -51,11 +51,12 @@ class OptionsBundleTests: XCTestCase { } func testDHCPOption() throws { - let lines = base + ["dhcp-option DNS 8.8.8.8", "dhcp-option DNS6 ffff::1"] + let lines = base + ["dhcp-option DNS 8.8.8.8", "dhcp-option DNS6 ffff::1", "dhcp-option DOMAIN example.com"] XCTAssertNoThrow(try OptionsBundle(from: lines)) let parsed = try! OptionsBundle(from: lines) XCTAssertEqual(parsed.dnsServers, ["8.8.8.8", "ffff::1"]) + XCTAssertEqual(parsed.searchDomain, "example.com") } func testConnectionBlock() throws {