summaryrefslogtreecommitdiffhomepage
path: root/wgengine/netstack/netstack.go
diff options
context:
space:
mode:
authorPercy Wegmann <percy@tailscale.com>2023-12-21 15:57:01 -0600
committerPercy Wegmann <percy@tailscale.com>2024-02-02 12:33:48 -0600
commit857cef70c97fe019ea24f7b4f24252f4746ebcc3 (patch)
tree257a7ec87af6ad29c06cdfe0e8774259f5e83cc3 /wgengine/netstack/netstack.go
parent60657ac83f415555c19027b0b18c0fe2d15bf40a (diff)
downloadtailscale-flyingsquirrel_bak.tar.xz
tailscale-flyingsquirrel_bak.zip
tailfs: initial implementationflyingsquirrel_bak
Implemented WebDAV-based core of Tailfs Updates tailscale/corp#16827 Signed-off-by: Percy Wegmann <percy@tailscale.com>
Diffstat (limited to 'wgengine/netstack/netstack.go')
-rw-r--r--wgengine/netstack/netstack.go64
1 files changed, 39 insertions, 25 deletions
diff --git a/wgengine/netstack/netstack.go b/wgengine/netstack/netstack.go
index 2c2214d8d..1aeaf2855 100644
--- a/wgengine/netstack/netstack.go
+++ b/wgengine/netstack/netstack.go
@@ -48,6 +48,7 @@ import (
"tailscale.com/proxymap"
"tailscale.com/syncs"
"tailscale.com/tailcfg"
+ "tailscale.com/tailfs"
"tailscale.com/types/ipproto"
"tailscale.com/types/logger"
"tailscale.com/types/netmap"
@@ -63,8 +64,8 @@ const debugPackets = false
var debugNetstack = envknob.RegisterBool("TS_DEBUG_NETSTACK")
var (
- magicDNSIP = tsaddr.TailscaleServiceIP()
- magicDNSIPv6 = tsaddr.TailscaleServiceIPv6()
+ serviceIP = tsaddr.TailscaleServiceIP()
+ serviceIPv6 = tsaddr.TailscaleServiceIPv6()
)
func init() {
@@ -120,18 +121,19 @@ type Impl struct {
// It can only be set before calling Start.
ProcessSubnets bool
- ipstack *stack.Stack
- linkEP *channel.Endpoint
- tundev *tstun.Wrapper
- e wgengine.Engine
- pm *proxymap.Mapper
- mc *magicsock.Conn
- logf logger.Logf
- dialer *tsdial.Dialer
- ctx context.Context // alive until Close
- ctxCancel context.CancelFunc // called on Close
- lb *ipnlocal.LocalBackend // or nil
- dns *dns.Manager
+ ipstack *stack.Stack
+ linkEP *channel.Endpoint
+ tundev *tstun.Wrapper
+ e wgengine.Engine
+ pm *proxymap.Mapper
+ mc *magicsock.Conn
+ logf logger.Logf
+ dialer *tsdial.Dialer
+ ctx context.Context // alive until Close
+ ctxCancel context.CancelFunc // called on Close
+ lb *ipnlocal.LocalBackend // or nil
+ dns *dns.Manager
+ tailfsForLocal tailfs.ForLocal // or nil
peerapiPort4Atomic atomic.Uint32 // uint16 port number for IPv4 peerapi
peerapiPort6Atomic atomic.Uint32 // uint16 port number for IPv6 peerapi
@@ -159,7 +161,7 @@ const nicID = 1
const maxUDPPacketSize = tstun.MaxPacketSize
// Create creates and populates a new Impl.
-func Create(logf logger.Logf, tundev *tstun.Wrapper, e wgengine.Engine, mc *magicsock.Conn, dialer *tsdial.Dialer, dns *dns.Manager, pm *proxymap.Mapper) (*Impl, error) {
+func Create(logf logger.Logf, tundev *tstun.Wrapper, e wgengine.Engine, mc *magicsock.Conn, dialer *tsdial.Dialer, dns *dns.Manager, pm *proxymap.Mapper, tailfsForLocal tailfs.ForLocal) (*Impl, error) {
if mc == nil {
return nil, errors.New("nil magicsock.Conn")
}
@@ -239,6 +241,7 @@ func Create(logf logger.Logf, tundev *tstun.Wrapper, e wgengine.Engine, mc *magi
dialer: dialer,
connsOpenBySubnetIP: make(map[netip.Addr]int),
dns: dns,
+ tailfsForLocal: tailfsForLocal,
}
ns.ctx, ns.ctxCancel = context.WithCancel(context.Background())
ns.atomicIsLocalIPFunc.Store(tsaddr.FalseContainsIPFunc())
@@ -440,16 +443,16 @@ func (ns *Impl) handleLocalPackets(p *packet.Parsed, t *tstun.Wrapper) filter.Re
return filter.DropSilently
}
- // If it's not traffic to the service IP (i.e. magicDNS) we don't
+ // If it's not traffic to the service IP (e.g. magicDNS) we don't
// care; resume processing.
- if dst := p.Dst.Addr(); dst != magicDNSIP && dst != magicDNSIPv6 {
+ if dst := p.Dst.Addr(); dst != serviceIP && dst != serviceIPv6 {
return filter.Accept
}
// Of traffic to the service IP, we only care about UDP 53, and TCP
- // on port 80 & 53.
+ // on port 53, 80, and 8080.
switch p.IPProto {
case ipproto.TCP:
- if port := p.Dst.Port(); port != 53 && port != 80 {
+ if port := p.Dst.Port(); port != 53 && port != 80 && port != 8080 {
return filter.Accept
}
case ipproto.UDP:
@@ -546,12 +549,12 @@ func (ns *Impl) inject() {
if b := pkt.NetworkHeader().Slice(); len(b) >= 20 { // min ipv4 header
switch b[0] >> 4 { // ip proto field
case 4:
- if srcIP := netaddr.IPv4(b[12], b[13], b[14], b[15]); magicDNSIP == srcIP {
+ if srcIP := netaddr.IPv4(b[12], b[13], b[14], b[15]); serviceIP == srcIP {
sendToHost = true
}
case 6:
if len(b) >= 40 { // min ipv6 header
- if srcIP, ok := netip.AddrFromSlice(net.IP(b[8:24])); ok && magicDNSIPv6 == srcIP {
+ if srcIP, ok := netip.AddrFromSlice(net.IP(b[8:24])); ok && serviceIPv6 == srcIP {
sendToHost = true
}
}
@@ -916,13 +919,24 @@ func (ns *Impl) acceptTCP(r *tcp.ForwarderRequest) {
return gonet.NewTCPConn(&wq, ep)
}
- // DNS
- if reqDetails.LocalPort == 53 && (dialIP == magicDNSIP || dialIP == magicDNSIPv6) {
+ // Local DNS Service (DNS and WebDAV)
+ hittingServiceIP := dialIP == serviceIP || dialIP == serviceIPv6
+ hittingDNS := hittingServiceIP && reqDetails.LocalPort == 53
+ hittingTailfs := hittingServiceIP && ns.tailfsForLocal != nil && reqDetails.LocalPort == 8080
+ if hittingDNS || hittingTailfs {
c := getConnOrReset()
if c == nil {
return
}
- go ns.dns.HandleTCPConn(c, netip.AddrPortFrom(clientRemoteIP, reqDetails.RemotePort))
+ addrPort := netip.AddrPortFrom(clientRemoteIP, reqDetails.RemotePort)
+ if hittingDNS {
+ go ns.dns.HandleTCPConn(c, addrPort)
+ } else if hittingTailfs {
+ err := ns.tailfsForLocal.HandleConn(c, net.TCPAddrFromAddrPort(addrPort))
+ if err != nil {
+ ns.logf("netstack: tailfs.HandleConn: %v", err)
+ }
+ }
return
}
@@ -1056,7 +1070,7 @@ func (ns *Impl) acceptUDP(r *udp.ForwarderRequest) {
}
// Handle magicDNS traffic (via UDP) here.
- if dst := dstAddr.Addr(); dst == magicDNSIP || dst == magicDNSIPv6 {
+ if dst := dstAddr.Addr(); dst == serviceIP || dst == serviceIPv6 {
if dstAddr.Port() != 53 {
ep.Close()
return // Only MagicDNS traffic runs on the service IPs for now.