Signed-off-by: Maisem Ali <maisem@tailscale.com>
maisem/tsnet-funnel-2
Maisem Ali 2023-03-10 11:44:28 -08:00
parent 920de86cee
commit 1555d38617
1 changed files with 36 additions and 6 deletions

View File

@ -9,6 +9,7 @@ package tsnet
import ( import (
"context" "context"
crand "crypto/rand" crand "crypto/rand"
"crypto/tls"
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt" "fmt"
@ -645,7 +646,7 @@ func networkForFamily(netBase string, is6 bool) string {
// - ("tcp", "", port) // - ("tcp", "", port)
// //
// The netBase is "tcp" or "udp" (without any '4' or '6' suffix). // The netBase is "tcp" or "udp" (without any '4' or '6' suffix).
func (s *Server) listenerForDstAddr(netBase string, dst netip.AddrPort) (_ *listener, ok bool) { func (s *Server) listenerForDstAddr(netBase string, dst netip.AddrPort, funnel bool) (_ *listener, ok bool) {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
for _, a := range [2]netip.Addr{0: dst.Addr()} { for _, a := range [2]netip.Addr{0: dst.Addr()} {
@ -653,7 +654,7 @@ func (s *Server) listenerForDstAddr(netBase string, dst netip.AddrPort) (_ *list
networkForFamily(netBase, dst.Addr().Is6()), networkForFamily(netBase, dst.Addr().Is6()),
netBase, netBase,
} { } {
if ln, ok := s.listeners[listenKey{net, a, dst.Port()}]; ok { if ln, ok := s.listeners[listenKey{net, a, dst.Port(), funnel}]; ok {
return ln, true return ln, true
} }
} }
@ -675,7 +676,7 @@ func (s *Server) getTCPHandlerForFunnelFlow(src netip.AddrPort, dstPort uint16)
} }
dst = netip.AddrPortFrom(ipv6, dstPort) dst = netip.AddrPortFrom(ipv6, dstPort)
} }
ln, ok := s.listenerForDstAddr("tcp", dst) ln, ok := s.listenerForDstAddr("tcp", dst, true)
if !ok { if !ok {
return nil return nil
} }
@ -683,7 +684,7 @@ func (s *Server) getTCPHandlerForFunnelFlow(src netip.AddrPort, dstPort uint16)
} }
func (s *Server) getTCPHandlerForFlow(src, dst netip.AddrPort) (handler func(net.Conn), intercept bool) { func (s *Server) getTCPHandlerForFlow(src, dst netip.AddrPort) (handler func(net.Conn), intercept bool) {
ln, ok := s.listenerForDstAddr("tcp", dst) ln, ok := s.listenerForDstAddr("tcp", dst, false)
if !ok { if !ok {
return nil, true // don't handle, don't forward to localhost return nil, true // don't handle, don't forward to localhost
} }
@ -691,7 +692,7 @@ func (s *Server) getTCPHandlerForFlow(src, dst netip.AddrPort) (handler func(net
} }
func (s *Server) getUDPHandlerForFlow(src, dst netip.AddrPort) (handler func(nettype.ConnPacketConn), intercept bool) { func (s *Server) getUDPHandlerForFlow(src, dst netip.AddrPort) (handler func(nettype.ConnPacketConn), intercept bool) {
ln, ok := s.listenerForDstAddr("udp", dst) ln, ok := s.listenerForDstAddr("udp", dst, false)
if !ok { if !ok {
return nil, true // don't handle, don't forward to localhost return nil, true // don't handle, don't forward to localhost
} }
@ -760,6 +761,34 @@ func (s *Server) APIClient() (*tailscale.Client, error) {
// Listen announces only on the Tailscale network. // Listen announces only on the Tailscale network.
// It will start the server if it has not been started yet. // It will start the server if it has not been started yet.
func (s *Server) Listen(network, addr string) (net.Listener, error) { func (s *Server) Listen(network, addr string) (net.Listener, error) {
return s.listen(network, addr, false)
}
func (s *Server) ListenFunnel(network string, addr string) (net.Listener, error) {
if network != "tcp" {
return nil, errors.New("only tcp is supported for ListenFunnel")
}
lc, err := s.LocalClient() // do local client first before listening.
if err != nil {
return nil, err
}
st, err := lc.StatusWithoutPeers(context.Background())
if err != nil {
return nil, err
}
if len(st.CertDomains) == 0 {
return nil, errors.New("please enable HTTPS in the Tailscale admin panel")
}
ln, err := s.listen(network, addr, true)
if err != nil {
return nil, err
}
return tls.NewListener(ln, &tls.Config{
GetCertificate: lc.GetCertificate,
}), nil
}
func (s *Server) listen(network, addr string, funnel bool) (net.Listener, error) {
switch network { switch network {
case "", "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6": case "", "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6":
default: default:
@ -794,7 +823,7 @@ func (s *Server) Listen(network, addr string) (net.Listener, error) {
return nil, err return nil, err
} }
key := listenKey{network, bindHostOrZero, uint16(port)} key := listenKey{network, bindHostOrZero, uint16(port), funnel}
ln := &listener{ ln := &listener{
s: s, s: s,
key: key, key: key,
@ -816,6 +845,7 @@ type listenKey struct {
network string network string
host netip.Addr // or zero value for unspecified host netip.Addr // or zero value for unspecified
port uint16 port uint16
funnel bool
} }
type listener struct { type listener struct {