diff --git a/tsnet/example/tsnet-services/tsnet-services.go b/tsnet/example/tsnet-services/tsnet-services.go index b519e3bcd..23b129671 100644 --- a/tsnet/example/tsnet-services/tsnet-services.go +++ b/tsnet/example/tsnet-services/tsnet-services.go @@ -2,8 +2,11 @@ // SPDX-License-Identifier: BSD-3-Clause // The tsnet-services example demonstrates how to use tsnet with Services. -// TODO: explain that a Service must be defined for the tailent and link to KB -// on defining a Service +// TODO: +// - explain that a Service must be defined for the tailent and link to KB on +// defining a Service +// - recommend using an auth key with associated tags +// - recommend an auto-approval rule for service tags // // To use it, generate an auth key from the Tailscale admin panel and // run the demo with the key: @@ -15,7 +18,6 @@ import ( "flag" "fmt" "log" - "math" "net/http" "tailscale.com/tailcfg" @@ -24,7 +26,6 @@ import ( var ( svcName = flag.String("service", "", "the name of your Service, e.g. svc:demo-service") - port = flag.Uint("port", 0, "the port to listen on") ) // TODO: this worked several times, then my host got stuck in 'Partially configured: has-config, config-valid' @@ -34,12 +35,8 @@ func main() { if *svcName == "" { log.Fatal("a Service name must be provided") } - if *port == 0 { - log.Fatal("the listening port must be provided") - } - if *port > math.MaxUint16 { - log.Fatal("invalid port number") - } + + const port uint16 = 443 s := &tsnet.Server{ Dir: "./services-demo-config", @@ -47,16 +44,14 @@ func main() { } defer s.Close() - ln, err := s.ListenService(*svcName, uint16(*port)) + ln, err := s.ListenService(*svcName, port, tsnet.ServiceOptionTerminateTLS()) if err != nil { log.Fatal(err) } defer ln.Close() - fmt.Printf("Listening on http://%v\n", tailcfg.AsServiceName(*svcName).WithoutPrefix()) + fmt.Printf("Listening on https://%v\n", tailcfg.AsServiceName(*svcName).WithoutPrefix()) - // TODO: maybe just respond to TCP connections? (since we don't know the port) - // Actually, let's hard-code port 80 and provide an example Service definition to use err = http.Serve(ln, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "

Hello, tailnet!

") })) diff --git a/tsnet/tsnet.go b/tsnet/tsnet.go index 715c08d0b..e0ff44b26 100644 --- a/tsnet/tsnet.go +++ b/tsnet/tsnet.go @@ -1320,6 +1320,7 @@ func (s *Server) ListenService(name string, port uint16, opts ...ServiceOption) return nil, fmt.Errorf("fetching node preferences: %w", err) } if !slices.Contains(prefs.AdvertiseServices, name) { + // TODO: do we need to undo this edit on error? _, err = lc.EditPrefs(ctx, &ipn.MaskedPrefs{ AdvertiseServicesSet: true, Prefs: ipn.Prefs{ @@ -1345,7 +1346,9 @@ func (s *Server) ListenService(name string, port uint16, opts ...ServiceOption) return nil, fmt.Errorf("starting local listener: %w", err) } // Forward all connections from service-hostname:port to our socket. - srvConfig.SetTCPForwarding(port, ln.Addr().String(), terminateTLS, proxyProtocol, name) + srvConfig.SetTCPForwardingForService( // TODO: tangent, but can we reduce the number of args here? + port, ln.Addr().String(), tailcfg.ServiceName(name), + terminateTLS, proxyProtocol, st.CurrentTailnet.MagicDNSSuffix) if err := lc.SetServeConfig(ctx, srvConfig); err != nil { ln.Close()