Skip to content

Commit 279a2db

Browse files
committed
chore: add a dns.OSConfigurator implementation that uses the CoderVPN protocol
1 parent 040e5cf commit 279a2db

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

tailnet/conn.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"tailscale.com/envknob"
2323
"tailscale.com/ipn/ipnstate"
2424
"tailscale.com/net/connstats"
25+
"tailscale.com/net/dns"
2526
"tailscale.com/net/netmon"
2627
"tailscale.com/net/netns"
2728
"tailscale.com/net/tsdial"
@@ -106,6 +107,9 @@ type Options struct {
106107
ClientType proto.TelemetryEvent_ClientType
107108
// TelemetrySink is optional.
108109
TelemetrySink TelemetrySink
110+
// DNSConfigurator is optional, and is passed to the underlying wireguard
111+
// engine.
112+
DNSConfigurator dns.OSConfigurator
109113
}
110114

111115
// TelemetrySink allows tailnet.Conn to send network telemetry to the Coder
@@ -178,6 +182,7 @@ func NewConn(options *Options) (conn *Conn, err error) {
178182
Dialer: dialer,
179183
ListenPort: options.ListenPort,
180184
SetSubsystem: sys.Set,
185+
DNS: options.DNSConfigurator,
181186
})
182187
if err != nil {
183188
return nil, xerrors.Errorf("create wgengine: %w", err)

vpn/dns.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package vpn
2+
3+
import "tailscale.com/net/dns"
4+
5+
func NewVPNManager(t *Tunnel) dns.OSConfigurator {
6+
return &vpnDNSManager{tunnel: t}
7+
}
8+
9+
type vpnDNSManager struct {
10+
tunnel *Tunnel
11+
}
12+
13+
func (v *vpnDNSManager) SetDNS(cfg dns.OSConfig) error {
14+
servers := make([]string, 0, len(cfg.Nameservers))
15+
for _, ns := range cfg.Nameservers {
16+
servers = append(servers, ns.String())
17+
}
18+
searchDomains := make([]string, 0, len(cfg.SearchDomains))
19+
for _, domain := range cfg.SearchDomains {
20+
searchDomains = append(searchDomains, domain.WithoutTrailingDot())
21+
}
22+
matchDomains := make([]string, 0, len(cfg.MatchDomains))
23+
for _, domain := range cfg.MatchDomains {
24+
matchDomains = append(matchDomains, domain.WithoutTrailingDot())
25+
}
26+
return v.tunnel.ApplyNetworkSettings(v.tunnel.ctx, &NetworkSettingsRequest{
27+
DnsSettings: &NetworkSettingsRequest_DNSSettings{
28+
Servers: servers,
29+
SearchDomains: searchDomains,
30+
DomainName: "coder",
31+
MatchDomains: matchDomains,
32+
MatchDomainsNoSearch: false,
33+
},
34+
})
35+
}
36+
37+
func (vpnDNSManager) GetBaseConfig() (dns.OSConfig, error) {
38+
// Tailscale calls this function to blend the OS's DNS configuration with
39+
// it's own, so this is only called if `SupportsSplitDNS` returns false.
40+
return dns.OSConfig{}, dns.ErrGetBaseConfigNotSupported
41+
}
42+
43+
func (*vpnDNSManager) SupportsSplitDNS() bool {
44+
// macOS & Windows 10+ support split DNS, so we'll assume all CoderVPN
45+
// clients do too.
46+
return true
47+
}
48+
49+
// Close implements dns.OSConfigurator.
50+
func (*vpnDNSManager) Close() error {
51+
// There's no cleanup that we need to initiate from within the dylib.
52+
return nil
53+
}
54+
55+
var _ dns.OSConfigurator = (*vpnDNSManager)(nil)

0 commit comments

Comments
 (0)