mirror of
https://github.com/tailscale/tailscale.git
synced 2025-05-06 15:46:53 +00:00
tsnet: add FunnelTLSConfig FunnelOption type
And also validate opts for unknown types, before other side effects. Fixes #15833 Change-Id: I4cabe16c49c5b7566dcafbec59f2cd1e0c8b4b3c Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
a9b3e09a1f
commit
ab2deda4b7
@ -1101,13 +1101,33 @@ type FunnelOption interface {
|
||||
funnelOption()
|
||||
}
|
||||
|
||||
type funnelOnly int
|
||||
type funnelOnly struct{}
|
||||
|
||||
func (funnelOnly) funnelOption() {}
|
||||
|
||||
// FunnelOnly configures the listener to only respond to connections from Tailscale Funnel.
|
||||
// The local tailnet will not be able to connect to the listener.
|
||||
func FunnelOnly() FunnelOption { return funnelOnly(1) }
|
||||
func FunnelOnly() FunnelOption { return funnelOnly{} }
|
||||
|
||||
type funnelTLSConfig struct{ conf *tls.Config }
|
||||
|
||||
func (f funnelTLSConfig) funnelOption() {}
|
||||
|
||||
// FunnelTLSConfig configures the TLS configuration for [Server.ListenFunnel]
|
||||
//
|
||||
// This is rarely needed but can permit requiring client certificates, specific
|
||||
// ciphers suites, etc.
|
||||
//
|
||||
// The provided conf should at least be able to get a certificate, setting
|
||||
// GetCertificate, Certificates or GetConfigForClient appropriately.
|
||||
// The most common configuration is to set GetCertificate to
|
||||
// Server.LocalClient's GetCertificate method.
|
||||
//
|
||||
// Unless [FunnelOnly] is also used, the configuration is also used for
|
||||
// in-tailnet connections that don't arrive over Funnel.
|
||||
func FunnelTLSConfig(conf *tls.Config) FunnelOption {
|
||||
return funnelTLSConfig{conf: conf}
|
||||
}
|
||||
|
||||
// ListenFunnel announces on the public internet using Tailscale Funnel.
|
||||
//
|
||||
@ -1140,6 +1160,26 @@ func (s *Server) ListenFunnel(network, addr string, opts ...FunnelOption) (net.L
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Process, validate opts.
|
||||
lnOn := listenOnBoth
|
||||
var tlsConfig *tls.Config
|
||||
for _, opt := range opts {
|
||||
switch v := opt.(type) {
|
||||
case funnelTLSConfig:
|
||||
if v.conf == nil {
|
||||
return nil, errors.New("invalid nil FunnelTLSConfig")
|
||||
}
|
||||
tlsConfig = v.conf
|
||||
case funnelOnly:
|
||||
lnOn = listenOnFunnel
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown opts FunnelOption type %T", v)
|
||||
}
|
||||
}
|
||||
if tlsConfig == nil {
|
||||
tlsConfig = &tls.Config{GetCertificate: s.getCert}
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
st, err := s.Up(ctx)
|
||||
if err != nil {
|
||||
@ -1177,19 +1217,11 @@ func (s *Server) ListenFunnel(network, addr string, opts ...FunnelOption) (net.L
|
||||
}
|
||||
|
||||
// Start a funnel listener.
|
||||
lnOn := listenOnBoth
|
||||
for _, opt := range opts {
|
||||
if _, ok := opt.(funnelOnly); ok {
|
||||
lnOn = listenOnFunnel
|
||||
}
|
||||
}
|
||||
ln, err := s.listen(network, addr, lnOn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tls.NewListener(ln, &tls.Config{
|
||||
GetCertificate: s.getCert,
|
||||
}), nil
|
||||
return tls.NewListener(ln, tlsConfig), nil
|
||||
}
|
||||
|
||||
type listenOn string
|
||||
|
Loading…
x
Reference in New Issue
Block a user