ipn: serve web client requests from LocalBackend

instead of starting a separate server listening on a particular port,
use the TCPHandlerForDst method to intercept requests for the special
web client port (currently 5252, probably configurable later).

Updates tailscale/corp#14335

Signed-off-by: Will Norris <will@tailscale.com>
pull/10032/head
Will Norris 1 year ago committed by Will Norris
parent 28ad910840
commit ea599b018c

@ -3129,6 +3129,10 @@ func (b *LocalBackend) TCPHandlerForDst(src, dst netip.AddrPort) (handler func(c
opts = append(opts, ptr.To(tcpip.KeepaliveIdleOption(72*time.Hour))) opts = append(opts, ptr.To(tcpip.KeepaliveIdleOption(72*time.Hour)))
return b.handleSSHConn, opts return b.handleSSHConn, opts
} }
// TODO(will,sonia): allow customizing web client port ?
if dst.Port() == 5252 && b.ShouldRunWebClient() {
return b.handleWebClientConn, opts
}
if port, ok := b.GetPeerAPIPort(dst.Addr()); ok && dst.Port() == port { if port, ok := b.GetPeerAPIPort(dst.Addr()); ok && dst.Port() == port {
return func(c net.Conn) error { return func(c net.Conn) error {
b.handlePeerAPIConn(src, dst, c) b.handlePeerAPIConn(src, dst, c)

@ -6,30 +6,27 @@
package ipnlocal package ipnlocal
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"net"
"net/http" "net/http"
"sync"
"tailscale.com/client/tailscale" "tailscale.com/client/tailscale"
"tailscale.com/client/web" "tailscale.com/client/web"
"tailscale.com/envknob" "tailscale.com/envknob"
"tailscale.com/net/netutil"
) )
// webServer holds state for the web interface for managing // webServer holds state for the web interface for managing
// this tailscale instance. The web interface is not used by // this tailscale instance. The web interface is not used by
// default, but initialized by calling LocalBackend.WebOrInit. // default, but initialized by calling LocalBackend.WebOrInit.
type webServer struct { type webServer struct {
ws *web.Server // or nil, initialized lazily ws *web.Server // or nil, initialized lazily
httpServer *http.Server // or nil, initialized lazily
// lc optionally specifies a LocalClient to use to connect // lc optionally specifies a LocalClient to use to connect
// to the localapi for this tailscaled instance. // to the localapi for this tailscaled instance.
// If nil, a default is used. // If nil, a default is used.
lc *tailscale.LocalClient lc *tailscale.LocalClient
wg sync.WaitGroup
} }
// SetWebLocalClient sets the b.web.lc function. // SetWebLocalClient sets the b.web.lc function.
@ -63,24 +60,6 @@ func (b *LocalBackend) WebInit() (err error) {
return fmt.Errorf("web.NewServer: %w", err) return fmt.Errorf("web.NewServer: %w", err)
} }
// Start up the server.
b.web.wg.Add(1)
go func() {
defer b.web.wg.Done()
// TODO(sonia/will): only listen on Tailscale IP addresses
addr := ":5252"
b.web.httpServer = &http.Server{
Addr: addr,
Handler: http.HandlerFunc(b.web.ws.ServeHTTP),
}
b.logf("WebInit: serving web ui on %s", addr)
if err := b.web.httpServer.ListenAndServe(); err != nil {
if err != http.ErrServerClosed {
b.logf("[unexpected] WebInit: %v", err)
}
}
}()
b.logf("WebInit: started web ui") b.logf("WebInit: started web ui")
return nil return nil
} }
@ -93,18 +72,19 @@ func (b *LocalBackend) WebInit() (err error) {
func (b *LocalBackend) WebShutdown() { func (b *LocalBackend) WebShutdown() {
b.mu.Lock() b.mu.Lock()
webS := b.web.ws webS := b.web.ws
httpS := b.web.httpServer
b.web.ws = nil b.web.ws = nil
b.web.httpServer = nil
b.mu.Unlock() // release lock before shutdown b.mu.Unlock() // release lock before shutdown
if webS != nil { if webS != nil {
b.web.ws.Shutdown() b.web.ws.Shutdown()
} }
if httpS != nil {
if err := b.web.httpServer.Shutdown(context.Background()); err != nil {
b.logf("[unexpected] WebShutdown: %v", err)
}
}
b.web.wg.Wait()
b.logf("WebShutdown: shut down web ui") b.logf("WebShutdown: shut down web ui")
} }
// handleWebClientConn serves web client requests.
func (b *LocalBackend) handleWebClientConn(c net.Conn) error {
if err := b.WebInit(); err != nil {
return err
}
s := http.Server{Handler: b.web.ws}
return s.Serve(netutil.NewOneConnListener(c, nil))
}

@ -7,6 +7,7 @@ package ipnlocal
import ( import (
"errors" "errors"
"net"
"tailscale.com/client/tailscale" "tailscale.com/client/tailscale"
) )
@ -20,3 +21,7 @@ func (b *LocalBackend) WebInit() error {
} }
func (b *LocalBackend) WebShutdown() {} func (b *LocalBackend) WebShutdown() {}
func (b *LocalBackend) handleWebClientConn(c net.Conn) error {
return errors.New("not implemented")
}

Loading…
Cancel
Save