Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5d853fc

Browse files
chore: support adding dns hosts totailnet.Conn (#15419)
Relates to#14718.The remaining changes (regarding the Tailscale DNS service) will need tobe made on `coder/tailscale`.
1 parente5661c2 commit5d853fc

File tree

3 files changed

+223
-6
lines changed

3 files changed

+223
-6
lines changed

‎tailnet/configmaps.go

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import (
55
"encoding/json"
66
"errors"
77
"fmt"
8+
"maps"
89
"net/netip"
10+
"slices"
911
"sync"
1012
"time"
1113

@@ -14,9 +16,11 @@ import (
1416
"tailscale.com/ipn/ipnstate"
1517
"tailscale.com/net/dns"
1618
"tailscale.com/tailcfg"
19+
"tailscale.com/types/dnstype"
1720
"tailscale.com/types/ipproto"
1821
"tailscale.com/types/key"
1922
"tailscale.com/types/netmap"
23+
"tailscale.com/util/dnsname"
2024
"tailscale.com/wgengine"
2125
"tailscale.com/wgengine/filter"
2226
"tailscale.com/wgengine/router"
@@ -30,6 +34,10 @@ import (
3034

3135
constlostTimeout=15*time.Minute
3236

37+
// CoderDNSSuffix is the default DNS suffix that we append to Coder DNS
38+
// records.
39+
constCoderDNSSuffix="coder."
40+
3341
// engineConfigurable is the subset of wgengine.Engine that we use for configuration.
3442
//
3543
// This allows us to test configuration code without faking the whole interface.
@@ -63,6 +71,7 @@ type configMaps struct {
6371

6472
engineengineConfigurable
6573
static netmap.NetworkMap
74+
hostsmap[dnsname.FQDN][]netip.Addr
6675
peersmap[uuid.UUID]*peerLifecycle
6776
addresses []netip.Prefix
6877
derpMap*tailcfg.DERPMap
@@ -79,6 +88,7 @@ func newConfigMaps(logger slog.Logger, engine engineConfigurable, nodeID tailcfg
7988
phased:phased{Cond:*(sync.NewCond(&sync.Mutex{}))},
8089
logger:logger,
8190
engine:engine,
91+
hosts:make(map[dnsname.FQDN][]netip.Addr),
8292
static: netmap.NetworkMap{
8393
SelfNode:&tailcfg.Node{
8494
ID:nodeID,
@@ -153,10 +163,11 @@ func (c *configMaps) configLoop() {
153163
}
154164
ifc.netmapDirty {
155165
nm:=c.netMapLocked()
166+
hosts:=c.hostsLocked()
156167
actions=append(actions,func() {
157168
c.logger.Debug(context.Background(),"updating engine network map",slog.F("network_map",nm))
158169
c.engine.SetNetworkMap(nm)
159-
c.reconfig(nm)
170+
c.reconfig(nm,hosts)
160171
})
161172
}
162173
ifc.filterDirty {
@@ -212,6 +223,11 @@ func (c *configMaps) netMapLocked() *netmap.NetworkMap {
212223
returnnm
213224
}
214225

226+
// hostsLocked returns the current DNS hosts mapping. c.L must be held.
227+
func (c*configMaps)hostsLocked()map[dnsname.FQDN][]netip.Addr {
228+
returnmaps.Clone(c.hosts)
229+
}
230+
215231
// peerConfigLocked returns the set of peer nodes we have. c.L must be held.
216232
func (c*configMaps)peerConfigLocked() []*tailcfg.Node {
217233
out:=make([]*tailcfg.Node,0,len(c.peers))
@@ -261,6 +277,37 @@ func (c *configMaps) setAddresses(ips []netip.Prefix) {
261277
c.Broadcast()
262278
}
263279

280+
func (c*configMaps)addHosts(hostsmap[dnsname.FQDN][]netip.Addr) {
281+
c.L.Lock()
282+
deferc.L.Unlock()
283+
forname,addrs:=rangehosts {
284+
c.hosts[name]=slices.Clone(addrs)
285+
}
286+
c.netmapDirty=true
287+
c.Broadcast()
288+
}
289+
290+
func (c*configMaps)setHosts(hostsmap[dnsname.FQDN][]netip.Addr) {
291+
c.L.Lock()
292+
deferc.L.Unlock()
293+
c.hosts=make(map[dnsname.FQDN][]netip.Addr)
294+
forname,addrs:=rangehosts {
295+
c.hosts[name]=slices.Clone(addrs)
296+
}
297+
c.netmapDirty=true
298+
c.Broadcast()
299+
}
300+
301+
func (c*configMaps)removeHosts(names []dnsname.FQDN) {
302+
c.L.Lock()
303+
deferc.L.Unlock()
304+
for_,name:=rangenames {
305+
delete(c.hosts,name)
306+
}
307+
c.netmapDirty=true
308+
c.Broadcast()
309+
}
310+
264311
// setBlockEndpoints sets whether we should block configuring endpoints we learn
265312
// from peers. It triggers a configuration of the engine if the value changes.
266313
// nolint: revive
@@ -305,7 +352,15 @@ func (c *configMaps) derpMapLocked() *tailcfg.DERPMap {
305352
// reconfig computes the correct wireguard config and calls the engine.Reconfig
306353
// with the config we have. It is not intended for this to be called outside of
307354
// the updateLoop()
308-
func (c*configMaps)reconfig(nm*netmap.NetworkMap) {
355+
func (c*configMaps)reconfig(nm*netmap.NetworkMap,hostsmap[dnsname.FQDN][]netip.Addr) {
356+
dnsCfg:=&dns.Config{}
357+
iflen(hosts)>0 {
358+
dnsCfg.Hosts=hosts
359+
dnsCfg.OnlyIPv6=true
360+
dnsCfg.Routes=map[dnsname.FQDN][]*dnstype.Resolver{
361+
CoderDNSSuffix:nil,
362+
}
363+
}
309364
cfg,err:=nmcfg.WGCfg(nm,Logger(c.logger.Named("net.wgconfig")),netmap.AllowSingleHosts,"")
310365
iferr!=nil {
311366
// WGCfg never returns an error at the time this code was written. If it starts, returning
@@ -314,8 +369,11 @@ func (c *configMaps) reconfig(nm *netmap.NetworkMap) {
314369
return
315370
}
316371

317-
rc:=&router.Config{LocalAddrs:nm.Addresses}
318-
err=c.engine.Reconfig(cfg,rc,&dns.Config{},&tailcfg.Debug{})
372+
rc:=&router.Config{
373+
LocalAddrs:nm.Addresses,
374+
Routes: []netip.Prefix{CoderServicePrefix.AsNetip()},
375+
}
376+
err=c.engine.Reconfig(cfg,rc,dnsCfg,&tailcfg.Debug{})
319377
iferr!=nil {
320378
iferrors.Is(err,wgengine.ErrNoChanges) {
321379
return

‎tailnet/configmaps_internal_test.go

Lines changed: 127 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@ import (
1010
"github.com/google/uuid"
1111
"github.com/stretchr/testify/assert"
1212
"github.com/stretchr/testify/require"
13+
"golang.org/x/exp/maps"
1314
"tailscale.com/ipn/ipnstate"
1415
"tailscale.com/net/dns"
1516
"tailscale.com/tailcfg"
17+
"tailscale.com/types/dnstype"
1618
"tailscale.com/types/key"
1719
"tailscale.com/types/netmap"
20+
"tailscale.com/util/dnsname"
1821
"tailscale.com/wgengine/filter"
1922
"tailscale.com/wgengine/router"
2023
"tailscale.com/wgengine/wgcfg"
@@ -1157,6 +1160,127 @@ func TestConfigMaps_updatePeers_nonexist(t *testing.T) {
11571160
}
11581161
}
11591162

1163+
funcTestConfigMaps_addRemoveHosts(t*testing.T) {
1164+
t.Parallel()
1165+
1166+
ctx:=testutil.Context(t,testutil.WaitShort)
1167+
logger:=slogtest.Make(t,nil).Leveled(slog.LevelDebug)
1168+
fEng:=newFakeEngineConfigurable()
1169+
nodePrivateKey:=key.NewNode()
1170+
nodeID:=tailcfg.NodeID(5)
1171+
discoKey:=key.NewDisco()
1172+
uut:=newConfigMaps(logger,fEng,nodeID,nodePrivateKey,discoKey.Public())
1173+
deferuut.close()
1174+
1175+
addr1:=CoderServicePrefix.AddrFromUUID(uuid.New())
1176+
addr2:=CoderServicePrefix.AddrFromUUID(uuid.New())
1177+
addr3:=CoderServicePrefix.AddrFromUUID(uuid.New())
1178+
addr4:=CoderServicePrefix.AddrFromUUID(uuid.New())
1179+
1180+
// WHEN: we add two hosts
1181+
uut.addHosts(map[dnsname.FQDN][]netip.Addr{
1182+
"agent.myws.me.coder.": {
1183+
addr1,
1184+
},
1185+
"dev.main.me.coder.": {
1186+
addr2,
1187+
addr3,
1188+
},
1189+
})
1190+
1191+
// THEN: the engine is reconfigured with those same hosts
1192+
_=testutil.RequireRecvCtx(ctx,t,fEng.setNetworkMap)
1193+
req:=testutil.RequireRecvCtx(ctx,t,fEng.reconfig)
1194+
require.Equal(t,req.dnsCfg,&dns.Config{
1195+
Routes:map[dnsname.FQDN][]*dnstype.Resolver{
1196+
CoderDNSSuffix:nil,
1197+
},
1198+
Hosts:map[dnsname.FQDN][]netip.Addr{
1199+
"agent.myws.me.coder.": {
1200+
addr1,
1201+
},
1202+
"dev.main.me.coder.": {
1203+
addr2,
1204+
addr3,
1205+
},
1206+
},
1207+
OnlyIPv6:true,
1208+
})
1209+
1210+
// WHEN: we add a new host
1211+
newHost:=map[dnsname.FQDN][]netip.Addr{
1212+
"agent2.myws.me.coder.": {
1213+
addr4,
1214+
},
1215+
}
1216+
uut.addHosts(newHost)
1217+
1218+
// THEN: the engine is reconfigured with both the old and new hosts
1219+
_=testutil.RequireRecvCtx(ctx,t,fEng.setNetworkMap)
1220+
req=testutil.RequireRecvCtx(ctx,t,fEng.reconfig)
1221+
require.Equal(t,req.dnsCfg,&dns.Config{
1222+
Routes:map[dnsname.FQDN][]*dnstype.Resolver{
1223+
CoderDNSSuffix:nil,
1224+
},
1225+
Hosts:map[dnsname.FQDN][]netip.Addr{
1226+
"agent.myws.me.coder.": {
1227+
addr1,
1228+
},
1229+
"dev.main.me.coder.": {
1230+
addr2,
1231+
addr3,
1232+
},
1233+
"agent2.myws.me.coder.": {
1234+
addr4,
1235+
},
1236+
},
1237+
OnlyIPv6:true,
1238+
})
1239+
1240+
// WHEN: We replace the hosts with a new set
1241+
uut.setHosts(map[dnsname.FQDN][]netip.Addr{
1242+
"newagent.myws.me.coder.": {
1243+
addr4,
1244+
},
1245+
"newagent2.main.me.coder.": {
1246+
addr1,
1247+
},
1248+
})
1249+
1250+
// THEN: The engine is reconfigured with only the new hosts
1251+
_=testutil.RequireRecvCtx(ctx,t,fEng.setNetworkMap)
1252+
req=testutil.RequireRecvCtx(ctx,t,fEng.reconfig)
1253+
require.Equal(t,req.dnsCfg,&dns.Config{
1254+
Routes:map[dnsname.FQDN][]*dnstype.Resolver{
1255+
CoderDNSSuffix:nil,
1256+
},
1257+
Hosts:map[dnsname.FQDN][]netip.Addr{
1258+
"newagent.myws.me.coder.": {
1259+
addr4,
1260+
},
1261+
"newagent2.main.me.coder.": {
1262+
addr1,
1263+
},
1264+
},
1265+
OnlyIPv6:true,
1266+
})
1267+
1268+
// WHEN: we remove all the hosts, and a bad host
1269+
uut.removeHosts(append(maps.Keys(req.dnsCfg.Hosts),"badhostname"))
1270+
_=testutil.RequireRecvCtx(ctx,t,fEng.setNetworkMap)
1271+
req=testutil.RequireRecvCtx(ctx,t,fEng.reconfig)
1272+
1273+
// THEN: the engine is reconfigured with an empty config
1274+
require.Equal(t,req.dnsCfg,&dns.Config{})
1275+
1276+
done:=make(chanstruct{})
1277+
gofunc() {
1278+
deferclose(done)
1279+
uut.close()
1280+
}()
1281+
_=testutil.RequireRecvCtx(ctx,t,done)
1282+
}
1283+
11601284
funcnewTestNode(idint)*Node {
11611285
return&Node{
11621286
ID:tailcfg.NodeID(id),
@@ -1199,6 +1323,7 @@ func requireNeverConfigures(ctx context.Context, t *testing.T, uut *phased) {
11991323
typereconfigCallstruct {
12001324
wg*wgcfg.Config
12011325
router*router.Config
1326+
dnsCfg*dns.Config
12021327
}
12031328

12041329
var_engineConfigurable=&fakeEngineConfigurable{}
@@ -1235,8 +1360,8 @@ func (f fakeEngineConfigurable) SetNetworkMap(networkMap *netmap.NetworkMap) {
12351360
f.setNetworkMap<-networkMap
12361361
}
12371362

1238-
func (ffakeEngineConfigurable)Reconfig(wg*wgcfg.Config,r*router.Config,_*dns.Config,_*tailcfg.Debug)error {
1239-
f.reconfig<-reconfigCall{wg:wg,router:r}
1363+
func (ffakeEngineConfigurable)Reconfig(wg*wgcfg.Config,r*router.Config,dnsCfg*dns.Config,_*tailcfg.Debug)error {
1364+
f.reconfig<-reconfigCall{wg:wg,router:r,dnsCfg:dnsCfg}
12401365
returnnil
12411366
}
12421367

‎tailnet/conn.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
tslogger"tailscale.com/types/logger"
3434
"tailscale.com/types/netlogtype"
3535
"tailscale.com/types/netmap"
36+
"tailscale.com/util/dnsname"
3637
"tailscale.com/wgengine"
3738
"tailscale.com/wgengine/capture"
3839
"tailscale.com/wgengine/magicsock"
@@ -290,6 +291,7 @@ func NewConn(options *Options) (conn *Conn, err error) {
290291
configMaps:cfgMaps,
291292
nodeUpdater:nodeUp,
292293
telemetrySink:options.TelemetrySink,
294+
dnsConfigurator:options.DNSConfigurator,
293295
telemetryStore:telemetryStore,
294296
createdAt:time.Now(),
295297
watchCtx:ctx,
@@ -379,6 +381,12 @@ func (p ServicePrefix) RandomPrefix() netip.Prefix {
379381
returnnetip.PrefixFrom(p.RandomAddr(),128)
380382
}
381383

384+
func (pServicePrefix)AsNetip() netip.Prefix {
385+
out:= [16]byte{}
386+
copy(out[:],p[:])
387+
returnnetip.PrefixFrom(netip.AddrFrom16(out),48)
388+
}
389+
382390
// Conn is an actively listening Wireguard connection.
383391
typeConnstruct {
384392
// Unique ID used for telemetry.
@@ -396,6 +404,7 @@ type Conn struct {
396404
wireguardMonitor*netmon.Monitor
397405
wireguardRouter*router.Config
398406
wireguardEngine wgengine.Engine
407+
dnsConfigurator dns.OSConfigurator
399408
listenersmap[listenKey]*listener
400409
clientType proto.TelemetryEvent_ClientType
401410
createdAt time.Time
@@ -442,6 +451,31 @@ func (c *Conn) SetAddresses(ips []netip.Prefix) error {
442451
returnnil
443452
}
444453

454+
func (c*Conn)AddDNSHosts(hostsmap[dnsname.FQDN][]netip.Addr)error {
455+
ifc.dnsConfigurator==nil {
456+
returnxerrors.New("no DNSConfigurator set")
457+
}
458+
c.configMaps.addHosts(hosts)
459+
returnnil
460+
}
461+
462+
func (c*Conn)RemoveDNSHosts(names []dnsname.FQDN)error {
463+
ifc.dnsConfigurator==nil {
464+
returnxerrors.New("no DNSConfigurator set")
465+
}
466+
c.configMaps.removeHosts(names)
467+
returnnil
468+
}
469+
470+
// SetDNSHosts replaces the map of DNS hosts for the connection.
471+
func (c*Conn)SetDNSHosts(hostsmap[dnsname.FQDN][]netip.Addr)error {
472+
ifc.dnsConfigurator==nil {
473+
returnxerrors.New("no DNSConfigurator set")
474+
}
475+
c.configMaps.setHosts(hosts)
476+
returnnil
477+
}
478+
445479
func (c*Conn)SetNodeCallback(callbackfunc(node*Node)) {
446480
c.nodeUpdater.setCallback(callback)
447481
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp