Skip to content

Commit 0fdb944

Browse files
authored
[client] Create NRPT rules separately per domain (#4329)
1 parent ccbabd9 commit 0fdb944

File tree

3 files changed

+60
-24
lines changed

3 files changed

+60
-24
lines changed

client/internal/dns/file_parser_unix_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,4 +176,3 @@ nameserver 192.168.0.1
176176
t.Errorf("unexpected resolv.conf content: %v", cfg)
177177
}
178178
}
179-

client/internal/dns/host_windows.go

Lines changed: 54 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,10 @@ const (
6464
)
6565

6666
type registryConfigurator struct {
67-
guid string
68-
routingAll bool
69-
gpo bool
67+
guid string
68+
routingAll bool
69+
gpo bool
70+
nrptEntryCount int
7071
}
7172

7273
func newHostManager(wgInterface WGIface) (*registryConfigurator, error) {
@@ -177,7 +178,11 @@ func (r *registryConfigurator) applyDNSConfig(config HostDNSConfig, stateManager
177178
log.Infof("removed %s as main DNS forwarder for this peer", config.ServerIP)
178179
}
179180

180-
if err := stateManager.UpdateState(&ShutdownState{Guid: r.guid, GPO: r.gpo}); err != nil {
181+
if err := stateManager.UpdateState(&ShutdownState{
182+
Guid: r.guid,
183+
GPO: r.gpo,
184+
NRPTEntryCount: r.nrptEntryCount,
185+
}); err != nil {
181186
log.Errorf("failed to update shutdown state: %s", err)
182187
}
183188

@@ -193,13 +198,24 @@ func (r *registryConfigurator) applyDNSConfig(config HostDNSConfig, stateManager
193198
}
194199

195200
if len(matchDomains) != 0 {
196-
if err := r.addDNSMatchPolicy(matchDomains, config.ServerIP); err != nil {
201+
count, err := r.addDNSMatchPolicy(matchDomains, config.ServerIP)
202+
if err != nil {
197203
return fmt.Errorf("add dns match policy: %w", err)
198204
}
205+
r.nrptEntryCount = count
199206
} else {
200207
if err := r.removeDNSMatchPolicies(); err != nil {
201208
return fmt.Errorf("remove dns match policies: %w", err)
202209
}
210+
r.nrptEntryCount = 0
211+
}
212+
213+
if err := stateManager.UpdateState(&ShutdownState{
214+
Guid: r.guid,
215+
GPO: r.gpo,
216+
NRPTEntryCount: r.nrptEntryCount,
217+
}); err != nil {
218+
log.Errorf("failed to update shutdown state: %s", err)
203219
}
204220

205221
if err := r.updateSearchDomains(searchDomains); err != nil {
@@ -220,28 +236,34 @@ func (r *registryConfigurator) addDNSSetupForAll(ip netip.Addr) error {
220236
return nil
221237
}
222238

223-
func (r *registryConfigurator) addDNSMatchPolicy(domains []string, ip netip.Addr) error {
239+
func (r *registryConfigurator) addDNSMatchPolicy(domains []string, ip netip.Addr) (int, error) {
224240
// if the gpo key is present, we need to put our DNS settings there, otherwise our config might be ignored
225241
// see https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-gpnrpt/8cc31cb9-20cb-4140-9e85-3e08703b4745
226-
if r.gpo {
227-
if err := r.configureDNSPolicy(gpoDnsPolicyConfigMatchPath, domains, ip); err != nil {
228-
return fmt.Errorf("configure GPO DNS policy: %w", err)
242+
for i, domain := range domains {
243+
policyPath := fmt.Sprintf("%s-%d", dnsPolicyConfigMatchPath, i)
244+
if r.gpo {
245+
policyPath = fmt.Sprintf("%s-%d", gpoDnsPolicyConfigMatchPath, i)
229246
}
230247

248+
singleDomain := []string{domain}
249+
250+
if err := r.configureDNSPolicy(policyPath, singleDomain, ip); err != nil {
251+
return i, fmt.Errorf("configure DNS policy for domain %s: %w", domain, err)
252+
}
253+
254+
log.Debugf("added NRPT entry for domain: %s", domain)
255+
}
256+
257+
if r.gpo {
231258
if err := refreshGroupPolicy(); err != nil {
232259
log.Warnf("failed to refresh group policy: %v", err)
233260
}
234-
} else {
235-
if err := r.configureDNSPolicy(dnsPolicyConfigMatchPath, domains, ip); err != nil {
236-
return fmt.Errorf("configure local DNS policy: %w", err)
237-
}
238261
}
239262

240-
log.Infof("added %d match domains. Domain list: %s", len(domains), domains)
241-
return nil
263+
log.Infof("added %d separate NRPT entries. Domain list: %s", len(domains), domains)
264+
return len(domains), nil
242265
}
243266

244-
// configureDNSPolicy handles the actual configuration of a DNS policy at the specified path
245267
func (r *registryConfigurator) configureDNSPolicy(policyPath string, domains []string, ip netip.Addr) error {
246268
if err := removeRegistryKeyFromDNSPolicyConfig(policyPath); err != nil {
247269
return fmt.Errorf("remove existing dns policy: %w", err)
@@ -374,12 +396,25 @@ func (r *registryConfigurator) restoreHostDNS() error {
374396

375397
func (r *registryConfigurator) removeDNSMatchPolicies() error {
376398
var merr *multierror.Error
399+
400+
// Try to remove the base entries (for backward compatibility)
377401
if err := removeRegistryKeyFromDNSPolicyConfig(dnsPolicyConfigMatchPath); err != nil {
378-
merr = multierror.Append(merr, fmt.Errorf("remove local registry key: %w", err))
402+
merr = multierror.Append(merr, fmt.Errorf("remove local base entry: %w", err))
379403
}
380-
381404
if err := removeRegistryKeyFromDNSPolicyConfig(gpoDnsPolicyConfigMatchPath); err != nil {
382-
merr = multierror.Append(merr, fmt.Errorf("remove GPO registry key: %w", err))
405+
merr = multierror.Append(merr, fmt.Errorf("remove GPO base entry: %w", err))
406+
}
407+
408+
for i := 0; i < r.nrptEntryCount; i++ {
409+
localPath := fmt.Sprintf("%s-%d", dnsPolicyConfigMatchPath, i)
410+
gpoPath := fmt.Sprintf("%s-%d", gpoDnsPolicyConfigMatchPath, i)
411+
412+
if err := removeRegistryKeyFromDNSPolicyConfig(localPath); err != nil {
413+
merr = multierror.Append(merr, fmt.Errorf("remove local entry %d: %w", i, err))
414+
}
415+
if err := removeRegistryKeyFromDNSPolicyConfig(gpoPath); err != nil {
416+
merr = multierror.Append(merr, fmt.Errorf("remove GPO entry %d: %w", i, err))
417+
}
383418
}
384419

385420
if err := refreshGroupPolicy(); err != nil {

client/internal/dns/unclean_shutdown_windows.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import (
55
)
66

77
type ShutdownState struct {
8-
Guid string
9-
GPO bool
8+
Guid string
9+
GPO bool
10+
NRPTEntryCount int
1011
}
1112

1213
func (s *ShutdownState) Name() string {
@@ -15,8 +16,9 @@ func (s *ShutdownState) Name() string {
1516

1617
func (s *ShutdownState) Cleanup() error {
1718
manager := &registryConfigurator{
18-
guid: s.Guid,
19-
gpo: s.GPO,
19+
guid: s.Guid,
20+
gpo: s.GPO,
21+
nrptEntryCount: s.NRPTEntryCount,
2022
}
2123

2224
if err := manager.restoreUncleanShutdownDNS(); err != nil {

0 commit comments

Comments
 (0)