Skip to content

Commit cd38324

Browse files
committed
ipn/wg: make endpoints & warp cfg update-able
warp/amenzia configuration and peer endpoints may change their endpoints on-the-fly. Make wgconn.go aware of those changes by passing it raw volatile values for warp/amnezia configuration and peer endpoints rather than fixed pointers (which may be later rendered obselete due to wgproxy.update()). wireguard's ipc can handle adding or updating new peers in-place, just fine.
1 parent 2ffc9fa commit cd38324

File tree

2 files changed

+24
-20
lines changed

2 files changed

+24
-20
lines changed

intra/ipn/wg/wgconn.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,9 @@ type connector func(network, to string) (net.PacketConn, error)
100100
type StdNetBind struct {
101101
id string
102102
connect connector
103-
pm *multihost.MHMap // peer ip:port or host => preferred-addrs
103+
pm *core.Volatile[*multihost.MHMap] // peer ip:port or host => preferred-addrs
104104

105-
amnezia *Amnezia
105+
amnezia *core.Volatile[*Amnezia] // may return nil *Amnezia
106106
floodBa *core.Barrier[int, netip.AddrPort]
107107

108108
mu sync.Mutex // protects following fields
@@ -119,7 +119,7 @@ type StdNetBind struct {
119119
}
120120

121121
// TODO: get d, ep, f, rb through an Opts bag?
122-
func NewEndpoint(id string, d connector, pm *multihost.MHMap, f rwobserver, a *Amnezia) *StdNetBind {
122+
func NewEndpoint(id string, d connector, pm *core.Volatile[*multihost.MHMap], f rwobserver, a *core.Volatile[*Amnezia]) *StdNetBind {
123123
s := &StdNetBind{
124124
id: id,
125125
connect: d,
@@ -161,7 +161,7 @@ func (e *StdNetBind) ParseEndpoint(s string) (conn.Endpoint, error) {
161161
// do what tailscale does, and share a preferred endpoint regardless of "s"
162162
// github.com/tailscale/tailscale/blob/3a6d3f1a5b7/wgengine/magicsock/magicsock.go#L2568
163163
// d.Add([]string{host}) // resolves host if needed
164-
d, err := e.pm.Get(s)
164+
d, err := e.pm.Load().Get(s)
165165
if err != nil || d == nil /*nilaway; can't happen*/ {
166166
log.E("wg: bind: %s parse: invalid endpoint in(%s); err: %v", e.id, s, err)
167167
return nil, err
@@ -347,7 +347,7 @@ func (s *StdNetBind) makeReceiveFn(uc net.PacketConn) conn.ReceiveFunc {
347347
extend(uc, wgtimeout)
348348
n, addr, err := uc.ReadFrom(b)
349349
if err == nil {
350-
recvOverwritten = s.amnezia.recv(&b)
350+
recvOverwritten = s.amnezia.Load().recv(&b)
351351
numMsgs++
352352
}
353353

@@ -357,7 +357,7 @@ func (s *StdNetBind) makeReceiveFn(uc net.PacketConn) conn.ReceiveFunc {
357357
}
358358

359359
logeif(err != nil && !timedout(err))("wg: bind: %s recvFrom(%v): %d / ov? %t<=%t / err? %v",
360-
s.id, addr, n, s.amnezia.Set(), recvOverwritten, err)
360+
s.id, addr, n, s.amnezia.Load().Set(), recvOverwritten, err)
361361
return numMsgs, err
362362
}
363363
}
@@ -414,9 +414,9 @@ func (s *StdNetBind) Send(buf [][]byte, peer conn.Endpoint) (err error) {
414414

415415
datalen := len(data) // grab the length before we overwrite it
416416

417-
overwritten = s.amnezia.send(&data)
417+
overwritten = s.amnezia.Load().send(&data)
418418

419-
if !flooded && (experimentalWg || s.amnezia.Set()) {
419+
if !flooded && (experimentalWg || s.amnezia.Load().Set()) {
420420
if datalen == device.MessageInitiationSize {
421421
s.flood(uc, ep, fkHandshake) // was probably a handshake
422422
flooded = true

intra/ipn/wgproxy.go

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ type wgtun struct {
101101
ep *channel.Endpoint // reads and writes packets to/from stack
102102
ingress chan *buffer.View // pipes ep writes to wg
103103
events chan tun.Event // wg specific tun (interface) events
104-
amnezia *wg.Amnezia // amnezia config, if any
105104
finalize chan struct{} // close signal for incomingPacket
106105
once sync.Once // closer fn; exec exactly once
107106
preferOffload bool // UDP GRO/GSO offloads
@@ -120,10 +119,12 @@ type wgtun struct {
120119
desiredmtu atomic.Uint32 // desired mtu
121120
netmtu atomic.Uint32 // underlay network mtu
122121

123-
peers *core.Volatile[map[string]device.NoisePublicKey] // peer (remote endpoint) public keys
124-
dns *core.Volatile[*multihost.MH] // dns resolver for this interface
125-
remote *core.Volatile[*multihost.MHMap] // peer (remote endpoint) addrs
126-
rt x.IpTree // route table for this interface
122+
peers *core.Volatile[map[string]device.NoisePublicKey] // peer (remote endpoint) public keys
123+
dns *core.Volatile[*multihost.MH] // dns resolver for this interface
124+
remote *core.Volatile[*multihost.MHMap] // peer (remote endpoint) addrs
125+
amnezia *core.Volatile[*wg.Amnezia] // amnezia/warp config, if any
126+
127+
rt x.IpTree // route table for this interface
127128

128129
refreshBa *core.Barrier[bool, string] // 2mins refresh barrier
129130

@@ -385,8 +386,9 @@ func (w *wgproxy) update(id, txt string) bool {
385386
}
386387

387388
if settings.Debug {
388-
if !w.amnezia.Same(opts.amnezia) {
389-
log.D("proxy: wg: update(%s): failed; amnezia %v != %v", w.id, opts.amnezia, w.amnezia)
389+
if !w.amnezia.Load().Same(opts.amnezia) {
390+
log.D("proxy: wg: update(%s): failed; amnezia %v != %v",
391+
w.id, opts.amnezia, w.amnezia.Load())
390392
}
391393
if opts.dns != nil && !opts.dns.EqualAddrs(w.dns.Load()) {
392394
log.D("proxy: wg: update(%s): failed; new/mismatched dns", w.id)
@@ -403,10 +405,10 @@ func (w *wgproxy) update(id, txt string) bool {
403405

404406
w.peers.Store(opts.peers) // re-assignment is okay (map entry modification is not)
405407
w.allowedIPs(opts.allowed)
406-
w.remote.Store(opts.eps) // requires refresh
407-
w.dns.Store(opts.dns) // requires refresh
408+
w.remote.Store(opts.eps) // requires refresh (wg.Conn:ParseEndpoint must be re-called)
409+
w.dns.Store(opts.dns) // requires refresh (client must also re-add via intra.AddDNSProxy)
408410
w.desiredmtu.Store(uint32(opts.mtu)) // requires reset; [NOMTU, MAXMTU)
409-
w.amnezia = opts.amnezia // TODO: core.Volatile?
411+
w.amnezia.Store(opts.amnezia)
410412
w.resetMtu(w.getVia())
411413

412414
return reuse
@@ -651,9 +653,11 @@ func NewWgProxy(id string, ctl protect.Controller, px ProxyProvider, lp LinkProp
651653
var wgep wgconn
652654
if wgtun.preferOffload {
653655
// todo: use wgtun.serve fn instead of ctl
656+
// todo: wgtun.remote instead of opts.eps
657+
// todo: amnezia/warp config
654658
wgep = wg.NewEndpoint2(id, ctl, opts.eps, wgtun.listener)
655659
} else {
656-
wgep = wg.NewEndpoint(id, wgtun.serve, opts.eps, wgtun.listener, wgtun.amnezia)
660+
wgep = wg.NewEndpoint(id, wgtun.serve, wgtun.remote, wgtun.listener, wgtun.amnezia)
657661
}
658662

659663
wgdev := device.NewDevice(wgtun, wgep, wglogger(id))
@@ -786,7 +790,7 @@ func makeWgTun(id, cfg string, ctl protect.Controller, px ProxyProvider, lp Link
786790
remote: core.NewVolatile(ifopts.eps), // may be nil
787791
peers: core.NewVolatile(ifopts.peers), // its entries must never be modified
788792
rt: x.NewIpTree(), // must be set to allowedaddrs
789-
amnezia: ifopts.amnezia,
793+
amnezia: core.NewVolatile(ifopts.amnezia),
790794
status: core.NewVolatile(TUP),
791795
preferOffload: preferOffload(id),
792796
refreshBa: core.NewBarrier[bool](refreshInterval),

0 commit comments

Comments
 (0)