@@ -5,10 +5,13 @@ import (
55 "encoding/base64"
66 "errors"
77 "fmt"
8+ "io"
89 "log"
910 "net"
1011 "net/netip"
12+ "slices"
1113 "strings"
14+ "sync"
1215 "time"
1316
1417 "github.com/fxamacker/cbor/v2"
@@ -24,8 +27,10 @@ import (
2427 "tailscale.com/types/key"
2528 "tailscale.com/types/logger"
2629 "tailscale.com/types/netmap"
30+ "tailscale.com/util/cmpx"
2731 "tailscale.com/util/mak"
2832 "tailscale.com/wgengine"
33+ "tailscale.com/wgengine/filter"
2934 "tailscale.com/wgengine/netstack"
3035 "tailscale.com/wgengine/router"
3136 "tailscale.com/wgengine/wgcfg"
@@ -53,6 +58,9 @@ type locoBackend struct {
5358 dm * tailcfg.DERPMap
5459 logf logger.Logf
5560 serverPub key.NodePublic // non-zero if we're a client (server's public key)
61+
62+ mu sync.Mutex
63+ clients map [key.NodePublic ]* tailcfg.Node // for the server
5664}
5765
5866func (b * locoBackend ) Close () error {
@@ -105,9 +113,20 @@ func NewServer(priv key.NodePrivate, logf logger.Logf, regs ...*tailcfg.DERPRegi
105113 }
106114 ns .ProcessLocalIPs = true
107115 ns .ProcessSubnets = true
116+ ns .GetTCPHandlerForFlow = func (src , dst netip.AddrPort ) (handler func (net.Conn ), intercept bool ) {
117+ logf ("XXX connection from %v to %v" , src , dst )
118+ if dst .Port () != 80 {
119+ return nil , true // sends RST
120+ }
121+ return func (c net.Conn ) {
122+ io .WriteString (c , "Hello from port 80\n " )
123+ c .Close ()
124+ }, true
125+ }
108126 lb .ns = ns
109127
110128 e := sys .Engine .Get ()
129+ e .SetFilter (filter .NewAllowAllForTest (logf )) // TODO: trashy
111130 dialer .UseNetstackForIP = func (ip netip.Addr ) bool {
112131 _ , ok := e .PeerForIP (ip )
113132 return ok
@@ -220,15 +239,20 @@ func (lb *locoBackend) Start() error {
220239 }
221240 if lb .serverPub .IsZero () {
222241 // We're the server. (hence the serverPub is zero)
242+ discoPriv := lb .priv .AsDiscoPrivate ()
243+ mc .SetDisco (discoPriv )
244+ mc .BeDerpCatServer (lb .onMeow )
245+
223246 nm .SelfNode = (& tailcfg.Node {
224247 ID : 1 ,
225248 StableID : "1" ,
226249 Name : "server.derpcat." ,
227250 User : 100 ,
228251 Key : lb .pub ,
229- DiscoKey : mc . DiscoPublicKey (), // TODO: change how disco works
252+ DiscoKey : discoPriv . Public (),
230253 Addresses : []netip.Prefix {lb .addrPrefix },
231254 AllowedIPs : []netip.Prefix {lb .addrPrefix },
255+ DERP : "127.3.3.40:1" ,
232256 }).View ()
233257 } else {
234258 // We're the client.
@@ -241,20 +265,23 @@ func (lb *locoBackend) Start() error {
241265 Name : "client.derpcat." ,
242266 User : 100 ,
243267 Key : lb .pub ,
244- DiscoKey : mc .DiscoPublicKey (), // TODO: change how disco works
268+ DiscoKey : mc .DiscoPublicKey (),
245269 Addresses : []netip.Prefix {lb .addrPrefix },
270+ DERP : "127.3.3.40:1" ,
246271 }).View ()
247272 nm .Peers = append (nm .Peers , (& tailcfg.Node {
248273 ID : 1 ,
249274 StableID : "1" ,
250275 Name : "server.derpcat." ,
251276 User : 100 ,
252277 Key : lb .serverPub ,
253- DiscoKey : key . NewDisco (). Public (), // TODO: change how disco works. This is dummy placeholder to placate magicsock for now
278+ DiscoKey : lb . serverPub . AsDiscoPublic (),
254279 Addresses : []netip.Prefix {serverAddrPrefix },
255280 AllowedIPs : []netip.Prefix {serverAddrPrefix },
281+ DERP : "127.3.3.40:1" ,
256282 }).View ())
257283 }
284+ nm .Addresses = nm .SelfNode .Addresses ().AsSlice () // dumb redundant field for now
258285 e .SetNetworkMap (nm )
259286 mc .SetNetworkUp (true )
260287 lb .logf ("NetworkMap: %v" , logger .AsJSON (nm ))
@@ -285,6 +312,71 @@ func (lb *locoBackend) Start() error {
285312 return nil
286313}
287314
315+ func (b * locoBackend ) onMeow (src key.NodePublic , discoPub key.DiscoPublic ) {
316+ b .mu .Lock ()
317+ defer b .mu .Unlock ()
318+ if _ , ok := b .clients [src ]; ok {
319+ return
320+ }
321+ id := len (b .clients ) + 2 // server id ID 1, clients are IDs 2, 3, ...
322+ mak .Set (& b .clients , src , & tailcfg.Node {
323+ ID : tailcfg .NodeID (id ),
324+ StableID : tailcfg .StableNodeID (fmt .Sprint (id )),
325+ Name : fmt .Sprintf ("client%d.derpcat." , id ),
326+ User : 100 ,
327+ Key : src ,
328+ DiscoKey : discoPub ,
329+ Addresses : []netip.Prefix {pfxOf (dcAddrForKey (src ))},
330+ AllowedIPs : []netip.Prefix {pfxOf (dcAddrForKey (src ))},
331+ DERP : "127.3.3.40:1" ,
332+ })
333+
334+ nm := & netmap.NetworkMap {
335+ PrivateKey : b .priv ,
336+ SelfNode : (& tailcfg.Node {
337+ ID : 1 ,
338+ StableID : "1" ,
339+ Name : "server.derpcat." ,
340+ User : 100 ,
341+ Key : b .pub ,
342+ DiscoKey : b .priv .AsDiscoPrivate ().Public (), // TODO: cache
343+ Addresses : []netip.Prefix {b .addrPrefix },
344+ AllowedIPs : []netip.Prefix {b .addrPrefix },
345+ DERP : "127.3.3.40:1" ,
346+ }).View (),
347+ }
348+ nm .Addresses = nm .SelfNode .Addresses ().AsSlice () // dumb redundant field for now
349+ for _ , n := range b .clients {
350+ nm .Peers = append (nm .Peers , n .View ())
351+ }
352+ slices .SortFunc (nm .Peers , func (a , b tailcfg.NodeView ) int {
353+ return cmpx .Compare (a .ID (), b .ID ())
354+ })
355+ eng := b .sys .Engine .Get ()
356+ eng .SetNetworkMap (nm )
357+
358+ wgConf := & wgcfg.Config {
359+ Name : "self" ,
360+ PrivateKey : b .priv ,
361+ Addresses : []netip.Prefix {b .addrPrefix },
362+ MTU : 1280 ,
363+ Peers : []wgcfg.Peer {}, // TODO: add peers dynamically as they disco to us
364+ }
365+ for _ , p := range b .clients {
366+ wgConf .Peers = append (wgConf .Peers , wgcfg.Peer {
367+ PublicKey : p .Key ,
368+ AllowedIPs : p .AllowedIPs ,
369+ })
370+ }
371+ routerConf := & router.Config {
372+ LocalAddrs : []netip.Prefix {b .addrPrefix },
373+ }
374+ dnsConf := & dns.Config {}
375+ if err := eng .Reconfig (wgConf , routerConf , dnsConf ); err != nil {
376+ panic (fmt .Sprintf ("e.Reconfig: %v" , err ))
377+ }
378+ }
379+
288380func (b * locoBackend ) Status () * ipnstate.Status {
289381 mc := b .sys .MagicSock .Get ()
290382 eng := b .sys .Engine .Get ()
@@ -372,11 +464,14 @@ func NewClient(logf logger.Logf, server ConnBlob) (*Client, error) {
372464 if err != nil {
373465 return nil , fmt .Errorf ("newNetstack: %w" , err )
374466 }
375- ns .ProcessLocalIPs = false
376- ns .ProcessSubnets = false
467+ ns .ProcessLocalIPs = true // required to even reply to TCP SYNs client sends out
468+ ns .GetTCPHandlerForFlow = func (src , dst netip.AddrPort ) (handler func (net.Conn ), intercept bool ) {
469+ return nil , true // don't accept any incoming connections to client
470+ }
377471 lb .ns = ns
378472
379473 e := sys .Engine .Get ()
474+ e .SetFilter (filter .NewAllowAllForTest (logf )) // TODO: trashy
380475 dialer .UseNetstackForIP = func (ip netip.Addr ) bool {
381476 _ , ok := e .PeerForIP (ip )
382477 return ok
@@ -391,8 +486,9 @@ func NewClient(logf logger.Logf, server ConnBlob) (*Client, error) {
391486 }, nil
392487}
393488
394- func (c * Client ) Start () error { return c .lb .Start () }
395- func (c * Client ) Close () error { return c .lb .Close () }
489+ func (c * Client ) PublicKey () key.NodePublic { return c .lb .pub }
490+ func (c * Client ) Start () error { return c .lb .Start () }
491+ func (c * Client ) Close () error { return c .lb .Close () }
396492
397493type PingResult struct {
398494 Latency time.Duration
@@ -422,3 +518,7 @@ func (c *Client) Ping(ctx context.Context) (PingResult, error) {
422518 return zero , ctx .Err ()
423519 }
424520}
521+
522+ func pfxOf (a netip.Addr ) netip.Prefix {
523+ return netip .PrefixFrom (a , a .BitLen ())
524+ }
0 commit comments