Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DNSMatchDomains property to Interface (split DNS) #11

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions Sources/Shared/Model/TunnelConfiguration+WgQuickConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ extension TunnelConfiguration {
let keyWithCase = trimmedLine[..<equalsIndex].trimmingCharacters(in: .whitespacesAndNewlines)
let key = keyWithCase.lowercased()
let value = trimmedLine[trimmedLine.index(equalsIndex, offsetBy: 1)...].trimmingCharacters(in: .whitespacesAndNewlines)
let keysWithMultipleEntriesAllowed: Set<String> = ["address", "allowedips", "dns"]
let keysWithMultipleEntriesAllowed: Set<String> = ["address", "allowedips", "dns", "dnsmatchdomains"]
if let presentValue = attributes[key] {
if keysWithMultipleEntriesAllowed.contains(key) {
attributes[key] = presentValue + "," + value
Expand All @@ -71,7 +71,7 @@ extension TunnelConfiguration {
} else {
attributes[key] = value
}
let interfaceSectionKeys: Set<String> = ["privatekey", "listenport", "address", "dns", "mtu"]
let interfaceSectionKeys: Set<String> = ["privatekey", "listenport", "address", "dns", "dnsmatchdomains", "mtu"]
let peerSectionKeys: Set<String> = ["publickey", "presharedkey", "allowedips", "endpoint", "persistentkeepalive"]
if parserState == .inInterfaceSection {
guard interfaceSectionKeys.contains(key) else {
Expand Down Expand Up @@ -139,6 +139,10 @@ extension TunnelConfiguration {
let dnsString = dnsLine.joined(separator: ", ")
output.append("DNS = \(dnsString)\n")
}
if !interface.dnsMatchDomains.isEmpty {
let dnsMatchString = interface.dnsMatchDomains.joined(separator: ", ")
output.append("DNSMatchDomains = \(dnsMatchString)\n")
}
if let mtu = interface.mtu {
output.append("MTU = \(mtu)\n")
}
Expand Down Expand Up @@ -201,6 +205,9 @@ extension TunnelConfiguration {
interface.dns = dnsServers
interface.dnsSearch = dnsSearch
}
if let dnsMatchString = attributes["dnsmatchdomains"] {
interface.dnsMatchDomains = dnsMatchString.splitToArray(trimmingCharacters: .whitespacesAndNewlines)
}
if let mtuString = attributes["mtu"] {
guard let mtu = UInt16(mtuString) else {
throw ParseError.interfaceHasInvalidMTU(mtuString)
Expand Down
1 change: 1 addition & 0 deletions Sources/WireGuardApp/Base.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"tunnelInterfaceListenPort" = "Listen port";
"tunnelInterfaceMTU" = "MTU";
"tunnelInterfaceDNS" = "DNS servers";
"tunnelInterfaceDNSMatchDomains" = "DNS match domains";
"tunnelInterfaceStatus" = "Status";

"tunnelSectionTitlePeer" = "Peer";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ extension TunnelConfiguration {
interfaceConfiguration?.addresses = base?.interface.addresses ?? []
interfaceConfiguration?.dns = base?.interface.dns ?? []
interfaceConfiguration?.dnsSearch = base?.interface.dnsSearch ?? []
interfaceConfiguration?.dnsMatchDomains = base?.interface.dnsMatchDomains ?? []
interfaceConfiguration?.mtu = base?.interface.mtu

if let interfaceConfiguration = interfaceConfiguration {
Expand Down
8 changes: 8 additions & 0 deletions Sources/WireGuardApp/UI/TunnelViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class TunnelViewModel {
case listenPort
case mtu
case dns
case dnsMatchDomains
case status
case toggleStatus

Expand All @@ -27,6 +28,7 @@ class TunnelViewModel {
case .listenPort: return tr("tunnelInterfaceListenPort")
case .mtu: return tr("tunnelInterfaceMTU")
case .dns: return tr("tunnelInterfaceDNS")
case .dnsMatchDomains: return tr("tunnelInterfaceDNSMatchDomains")
case .status: return tr("tunnelInterfaceStatus")
case .toggleStatus: return ""
}
Expand Down Expand Up @@ -144,6 +146,9 @@ class TunnelViewModel {
dns.append(contentsOf: config.dnsSearch)
scratchpad[.dns] = dns.joined(separator: ", ")
}
if !config.dnsMatchDomains.isEmpty {
scratchpad[.dnsMatchDomains] = config.dnsMatchDomains.joined(separator: ", ")
}
return scratchpad
}

Expand Down Expand Up @@ -207,6 +212,9 @@ class TunnelViewModel {
config.dns = dnsServers
config.dnsSearch = dnsSearch
}
if let dnsMatchString = scratchpad[.dnsMatchDomains] {
config.dnsMatchDomains = dnsMatchString.splitToArray(trimmingCharacters: .whitespacesAndNewlines)
}

guard errorMessages.isEmpty else { return .error(errorMessages.first!) }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class TunnelDetailTableViewController: UITableViewController {

static let interfaceFields: [TunnelViewModel.InterfaceField] = [
.name, .publicKey, .addresses,
.listenPort, .mtu, .dns
.listenPort, .mtu, .dns, .dnsMatchDomains
]

static let peerFields: [TunnelViewModel.PeerField] = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class TunnelEditTableViewController: UITableViewController {
let interfaceFieldsBySection: [[TunnelViewModel.InterfaceField]] = [
[.name],
[.privateKey, .publicKey, .generateKeyPair],
[.addresses, .listenPort, .mtu, .dns]
[.addresses, .listenPort, .mtu, .dns, .dnsMatchDomains]
]

let peerFields: [TunnelViewModel.PeerField] = [
Expand Down Expand Up @@ -246,6 +246,9 @@ extension TunnelEditTableViewController {
case .dns:
cell.placeholderText = tunnelViewModel.peersData.contains(where: { $0.shouldStronglyRecommendDNS }) ? tr("tunnelEditPlaceholderTextStronglyRecommended") : tr("tunnelEditPlaceholderTextOptional")
cell.keyboardType = .numbersAndPunctuation
case .dnsMatchDomains:
cell.placeholderText = tr("tunnelEditPlaceholderTextOptional")
cell.keyboardType = .numbersAndPunctuation
case .listenPort, .mtu:
cell.placeholderText = tr("tunnelEditPlaceholderTextAutomatic")
cell.keyboardType = .numberPad
Expand Down
9 changes: 9 additions & 0 deletions Sources/WireGuardApp/UI/macOS/View/highlighter.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ enum field {
ListenPort,
Address,
DNS,
DNSMatchDomains,
MTU,
#ifndef MOBILE_WGQUICK_SUBSET
FwMark,
Expand Down Expand Up @@ -377,6 +378,7 @@ static enum field get_field(string_span_t s)
check_enum(ListenPort);
check_enum(Address);
check_enum(DNS);
check_enum(DNSMatchDomains);
check_enum(MTU);
check_enum(PublicKey);
check_enum(PresharedKey);
Expand Down Expand Up @@ -453,6 +455,12 @@ static void highlight_multivalue_value(struct highlight_span_array *ret, const s
else
append_highlight_span(ret, parent.s, s, HighlightError);
break;
case DNSMatchDomains:
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: {
size_t slash;
Expand Down Expand Up @@ -563,6 +571,7 @@ static void highlight_value(struct highlight_span_array *ret, const string_span_
}
case Address:
case DNS:
case DNSMatchDomains:
case AllowedIPs:
highlight_multivalue(ret, parent, s, section);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class TunnelDetailTableViewController: NSViewController {

static let interfaceFields: [TunnelViewModel.InterfaceField] = [
.name, .status, .publicKey, .addresses,
.listenPort, .mtu, .dns, .toggleStatus
.listenPort, .mtu, .dns, .dnsMatchDomains, .toggleStatus
]

static let peerFields: [TunnelViewModel.PeerField] = [
Expand Down
4 changes: 3 additions & 1 deletion Sources/WireGuardKit/InterfaceConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public struct InterfaceConfiguration {
public var mtu: UInt16?
public var dns = [DNSServer]()
public var dnsSearch = [String]()
public var dnsMatchDomains = [String]()

public init(privateKey: PrivateKey) {
self.privateKey = privateKey
Expand All @@ -27,6 +28,7 @@ extension InterfaceConfiguration: Equatable {
lhs.listenPort == rhs.listenPort &&
lhs.mtu == rhs.mtu &&
lhs.dns == rhs.dns &&
lhs.dnsSearch == rhs.dnsSearch
lhs.dnsSearch == rhs.dnsSearch &&
lhs.dnsMatchDomains == rhs.dnsMatchDomains
}
}
21 changes: 20 additions & 1 deletion Sources/WireGuardKit/PacketTunnelSettingsGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,28 @@ class PacketTunnelSettingsGenerator {
let dnsServerStrings = tunnelConfiguration.interface.dns.map { $0.stringRepresentation }
let dnsSettings = NEDNSSettings(servers: dnsServerStrings)
dnsSettings.searchDomains = tunnelConfiguration.interface.dnsSearch

if !tunnelConfiguration.interface.dns.isEmpty {
dnsSettings.matchDomains = [""] // All DNS queries must first go through the tunnel's DNS
dnsSettings.matchDomainsNoSearch = true
if tunnelConfiguration.interface.dnsMatchDomains.isEmpty {
// Add "" so that all DNS queries must first go through the tunnel's DNS.
// NEDNSSettings.searchDomains does not work so we add the searches to matchDomains,
fhriley marked this conversation as resolved.
Show resolved Hide resolved
// which does work.
dnsSettings.matchDomains = [""] + tunnelConfiguration.interface.dnsSearch
dnsSettings.matchDomainsNoSearch = false
} else {
// Don't add dnsSearch here because that would cause domains that aren't
// in dnsMatchDomains to be matched.
dnsSettings.matchDomains = tunnelConfiguration.interface.dnsMatchDomains
for domain in tunnelConfiguration.interface.dnsMatchDomains {
if tunnelConfiguration.interface.dnsSearch.contains(domain) {
dnsSettings.matchDomainsNoSearch = false
break
}
}
}
}

networkSettings.dnsSettings = dnsSettings
}

Expand Down