Skip to content

Add DNSMatchDomains property to Interface (split DNS) #11

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
@@ -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
@@ -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 {
@@ -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")
}
@@ -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)
1 change: 1 addition & 0 deletions Sources/WireGuardApp/Base.lproj/Localizable.strings
Original file line number Diff line number Diff line change
@@ -82,6 +82,7 @@
"tunnelInterfaceListenPort" = "Listen port";
"tunnelInterfaceMTU" = "MTU";
"tunnelInterfaceDNS" = "DNS servers";
"tunnelInterfaceDNSMatchDomains" = "DNS match domains";
"tunnelInterfaceStatus" = "Status";

"tunnelSectionTitlePeer" = "Peer";
Original file line number Diff line number Diff line change
@@ -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 {
8 changes: 8 additions & 0 deletions Sources/WireGuardApp/UI/TunnelViewModel.swift
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@ class TunnelViewModel {
case listenPort
case mtu
case dns
case dnsMatchDomains
case status
case toggleStatus

@@ -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 ""
}
@@ -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
}

@@ -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!) }

Original file line number Diff line number Diff line change
@@ -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] = [
Original file line number Diff line number Diff line change
@@ -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] = [
@@ -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
9 changes: 9 additions & 0 deletions Sources/WireGuardApp/UI/macOS/View/highlighter.c
Original file line number Diff line number Diff line change
@@ -343,6 +343,7 @@ enum field {
ListenPort,
Address,
DNS,
DNSMatchDomains,
MTU,
#ifndef MOBILE_WGQUICK_SUBSET
FwMark,
@@ -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);
@@ -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;
@@ -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;
Original file line number Diff line number Diff line change
@@ -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] = [
4 changes: 3 additions & 1 deletion Sources/WireGuardKit/InterfaceConfiguration.swift
Original file line number Diff line number Diff line change
@@ -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
@@ -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
@@ -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,
// 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
}