From 9231c03513e480a0a6f7ed2aa86f69e47d078774 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 15 Dec 2020 13:49:21 +0100 Subject: [PATCH] global: support DNS search domains This has been supported by Windows and Linux for quite some time. Add support here for iOS and macOS. Signed-off-by: Jason A. Donenfeld --- .../Model/TunnelConfiguration+WgQuickConfig.swift | 15 ++++++++++----- .../Tunnel/TunnelConfiguration+UapiConfig.swift | 1 + Sources/WireGuardApp/UI/TunnelViewModel.swift | 11 +++++++---- Sources/WireGuardApp/UI/macOS/View/highlighter.c | 12 ++++++------ Sources/WireGuardKit/InterfaceConfiguration.swift | 4 +++- .../PacketTunnelSettingsGenerator.swift | 1 + 6 files changed, 28 insertions(+), 16 deletions(-) diff --git a/Sources/Shared/Model/TunnelConfiguration+WgQuickConfig.swift b/Sources/Shared/Model/TunnelConfiguration+WgQuickConfig.swift index eb60a52..0cc1803 100644 --- a/Sources/Shared/Model/TunnelConfiguration+WgQuickConfig.swift +++ b/Sources/Shared/Model/TunnelConfiguration+WgQuickConfig.swift @@ -133,8 +133,10 @@ extension TunnelConfiguration { let addressString = interface.addresses.map { $0.stringRepresentation }.joined(separator: ", ") output.append("Address = \(addressString)\n") } - if !interface.dns.isEmpty { - let dnsString = interface.dns.map { $0.stringRepresentation }.joined(separator: ", ") + if !interface.dns.isEmpty || !interface.dnsSearch.isEmpty { + var dnsLine = interface.dns.map { $0.stringRepresentation } + dnsLine.append(contentsOf: interface.dnsSearch) + let dnsString = dnsLine.joined(separator: ", ") output.append("DNS = \(dnsString)\n") } if let mtu = interface.mtu { @@ -188,13 +190,16 @@ extension TunnelConfiguration { } if let dnsString = attributes["dns"] { var dnsServers = [DNSServer]() + var dnsSearch = [String]() for dnsServerString in dnsString.splitToArray(trimmingCharacters: .whitespacesAndNewlines) { - guard let dnsServer = DNSServer(from: dnsServerString) else { - throw ParseError.interfaceHasInvalidDNS(dnsServerString) + if let dnsServer = DNSServer(from: dnsServerString) { + dnsServers.append(dnsServer) + } else { + dnsSearch.append(dnsServerString) } - dnsServers.append(dnsServer) } interface.dns = dnsServers + interface.dnsSearch = dnsSearch } if let mtuString = attributes["mtu"] { guard let mtu = UInt16(mtuString) else { diff --git a/Sources/WireGuardApp/Tunnel/TunnelConfiguration+UapiConfig.swift b/Sources/WireGuardApp/Tunnel/TunnelConfiguration+UapiConfig.swift index 1874b05..e8aa8a9 100644 --- a/Sources/WireGuardApp/Tunnel/TunnelConfiguration+UapiConfig.swift +++ b/Sources/WireGuardApp/Tunnel/TunnelConfiguration+UapiConfig.swift @@ -74,6 +74,7 @@ extension TunnelConfiguration { interfaceConfiguration?.addresses = base?.interface.addresses ?? [] interfaceConfiguration?.dns = base?.interface.dns ?? [] + interfaceConfiguration?.dnsSearch = base?.interface.dnsSearch ?? [] interfaceConfiguration?.mtu = base?.interface.mtu if let interfaceConfiguration = interfaceConfiguration { diff --git a/Sources/WireGuardApp/UI/TunnelViewModel.swift b/Sources/WireGuardApp/UI/TunnelViewModel.swift index 60aa5c3..6d0471e 100644 --- a/Sources/WireGuardApp/UI/TunnelViewModel.swift +++ b/Sources/WireGuardApp/UI/TunnelViewModel.swift @@ -139,8 +139,10 @@ class TunnelViewModel { if let mtu = config.mtu { scratchpad[.mtu] = String(mtu) } - if !config.dns.isEmpty { - scratchpad[.dns] = config.dns.map { $0.stringRepresentation }.joined(separator: ", ") + if !config.dns.isEmpty || !config.dnsSearch.isEmpty { + var dns = config.dns.map { $0.stringRepresentation } + dns.append(contentsOf: config.dnsSearch) + scratchpad[.dns] = dns.joined(separator: ", ") } return scratchpad } @@ -194,15 +196,16 @@ class TunnelViewModel { } if let dnsString = scratchpad[.dns] { var dnsServers = [DNSServer]() + var dnsSearch = [String]() for dnsServerString in dnsString.splitToArray(trimmingCharacters: .whitespacesAndNewlines) { if let dnsServer = DNSServer(from: dnsServerString) { dnsServers.append(dnsServer) } else { - fieldsWithError.insert(.dns) - errorMessages.append(tr("alertInvalidInterfaceMessageDNSInvalid")) + dnsSearch.append(dnsServerString) } } config.dns = dnsServers + config.dnsSearch = dnsSearch } guard errorMessages.isEmpty else { return .error(errorMessages.first!) } diff --git a/Sources/WireGuardApp/UI/macOS/View/highlighter.c b/Sources/WireGuardApp/UI/macOS/View/highlighter.c index e0d4e04..d89feda 100644 --- a/Sources/WireGuardApp/UI/macOS/View/highlighter.c +++ b/Sources/WireGuardApp/UI/macOS/View/highlighter.c @@ -337,11 +337,6 @@ static bool is_valid_network(string_span_t s) return is_valid_ipv4(s) || is_valid_ipv6(s); } -static bool is_valid_dns(string_span_t s) -{ - return is_valid_ipv4(s) || is_valid_ipv6(s); -} - enum field { InterfaceSection, PrivateKey, @@ -451,7 +446,12 @@ static void highlight_multivalue_value(struct highlight_span_array *ret, const s { switch (section) { case DNS: - append_highlight_span(ret, parent.s, s, is_valid_dns(s) ? HighlightIP : HighlightError); + if (is_valid_ipv4(s) || is_valid_ipv6(s)) + append_highlight_span(ret, parent.s, s, HighlightIP); + else if (is_valid_hostname(s)) + append_highlight_span(ret, parent.s, s, HighlightHost); + else + append_highlight_span(ret, parent.s, s, HighlightError); break; case Address: case AllowedIPs: { diff --git a/Sources/WireGuardKit/InterfaceConfiguration.swift b/Sources/WireGuardKit/InterfaceConfiguration.swift index 2d104d2..02bed98 100644 --- a/Sources/WireGuardKit/InterfaceConfiguration.swift +++ b/Sources/WireGuardKit/InterfaceConfiguration.swift @@ -10,6 +10,7 @@ public struct InterfaceConfiguration { public var listenPort: UInt16? public var mtu: UInt16? public var dns = [DNSServer]() + public var dnsSearch = [String]() public init(privateKey: PrivateKey) { self.privateKey = privateKey @@ -25,6 +26,7 @@ extension InterfaceConfiguration: Equatable { lhsAddresses == rhsAddresses && lhs.listenPort == rhs.listenPort && lhs.mtu == rhs.mtu && - lhs.dns == rhs.dns + lhs.dns == rhs.dns && + lhs.dnsSearch == rhs.dnsSearch } } diff --git a/Sources/WireGuardKit/PacketTunnelSettingsGenerator.swift b/Sources/WireGuardKit/PacketTunnelSettingsGenerator.swift index 0ddc1b7..034ecaf 100644 --- a/Sources/WireGuardKit/PacketTunnelSettingsGenerator.swift +++ b/Sources/WireGuardKit/PacketTunnelSettingsGenerator.swift @@ -85,6 +85,7 @@ class PacketTunnelSettingsGenerator { let dnsServerStrings = tunnelConfiguration.interface.dns.map { $0.stringRepresentation } let dnsSettings = NEDNSSettings(servers: dnsServerStrings) + dnsSettings.searchDomains = tunnelConfiguration.interface.dnsSearch dnsSettings.matchDomains = [""] // All DNS queries must first go through the tunnel's DNS networkSettings.dnsSettings = dnsSettings