NewServerTailnet creates a new tailnet intended for use by coderd.
( ctx context.Context, logger slog.Logger, derpServer *derp.Server, dialer tailnet.ControlProtocolDialer, derpForceWebSockets bool, blockEndpoints bool, traceProvider trace.TracerProvider, )
| 51 | |
| 52 | // NewServerTailnet creates a new tailnet intended for use by coderd. |
| 53 | func NewServerTailnet( |
| 54 | ctx context.Context, |
| 55 | logger slog.Logger, |
| 56 | derpServer *derp.Server, |
| 57 | dialer tailnet.ControlProtocolDialer, |
| 58 | derpForceWebSockets bool, |
| 59 | blockEndpoints bool, |
| 60 | traceProvider trace.TracerProvider, |
| 61 | ) (*ServerTailnet, error) { |
| 62 | logger = logger.Named("servertailnet") |
| 63 | conn, err := tailnet.NewConn(&tailnet.Options{ |
| 64 | Addresses: []netip.Prefix{tailnet.TailscaleServicePrefix.RandomPrefix()}, |
| 65 | DERPForceWebSockets: derpForceWebSockets, |
| 66 | Logger: logger, |
| 67 | BlockEndpoints: blockEndpoints, |
| 68 | }) |
| 69 | if err != nil { |
| 70 | return nil, xerrors.Errorf("create tailnet conn: %w", err) |
| 71 | } |
| 72 | serverCtx, cancel := context.WithCancel(ctx) |
| 73 | |
| 74 | // This is set to allow local DERP traffic to be proxied through memory |
| 75 | // instead of needing to hit the external access URL. Don't use the ctx |
| 76 | // given in this callback, it's only valid while connecting. |
| 77 | if derpServer != nil { |
| 78 | conn.SetDERPRegionDialer(func(_ context.Context, region *tailcfg.DERPRegion) net.Conn { |
| 79 | // Don't set up the embedded relay if we're shutting down |
| 80 | if !region.EmbeddedRelay || ctx.Err() != nil { |
| 81 | return nil |
| 82 | } |
| 83 | logger.Debug(ctx, "connecting to embedded DERP via in-memory pipe") |
| 84 | left, right := net.Pipe() |
| 85 | go func() { |
| 86 | defer left.Close() |
| 87 | defer right.Close() |
| 88 | brw := bufio.NewReadWriter(bufio.NewReader(right), bufio.NewWriter(right)) |
| 89 | derpServer.Accept(ctx, right, brw, "internal") |
| 90 | }() |
| 91 | return left |
| 92 | }) |
| 93 | } |
| 94 | |
| 95 | tracer := traceProvider.Tracer(tracing.TracerName) |
| 96 | |
| 97 | controller := tailnet.NewController(logger, dialer) |
| 98 | // it's important to set the DERPRegionDialer above _before_ we set the DERP map so that if |
| 99 | // there is an embedded relay, we use the local in-memory dialer. |
| 100 | controller.DERPCtrl = tailnet.NewBasicDERPController(logger, nil, conn) |
| 101 | coordCtrl := NewMultiAgentController(serverCtx, logger, tracer, conn) |
| 102 | controller.CoordCtrl = coordCtrl |
| 103 | // TODO: support controller.TelemetryCtrl |
| 104 | |
| 105 | tn := &ServerTailnet{ |
| 106 | ctx: serverCtx, |
| 107 | cancel: cancel, |
| 108 | logger: logger, |
| 109 | tracer: tracer, |
| 110 | conn: conn, |