mirror of
https://github.com/tailscale/tailscale.git
synced 2025-05-23 15:59:53 +00:00
add stateful firewall
Change-Id: I4a963f144f24481746c50a2aa97671b7bfc1f267 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
37249f68ca
commit
2e3a896cab
@ -5,6 +5,7 @@ package vnet
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"log"
|
||||||
"math/rand/v2"
|
"math/rand/v2"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"time"
|
"time"
|
||||||
@ -111,7 +112,7 @@ func (n *oneToOneNAT) PickIncomingDst(src, dst netip.AddrPort, at time.Time) (la
|
|||||||
return netip.AddrPortFrom(n.lanIP, dst.Port())
|
return netip.AddrPortFrom(n.lanIP, dst.Port())
|
||||||
}
|
}
|
||||||
|
|
||||||
type hardKeyOut struct {
|
type srcDstTuple struct {
|
||||||
src netip.AddrPort
|
src netip.AddrPort
|
||||||
dst netip.AddrPort
|
dst netip.AddrPort
|
||||||
}
|
}
|
||||||
@ -137,7 +138,7 @@ type lanAddrAndTime struct {
|
|||||||
type hardNAT struct {
|
type hardNAT struct {
|
||||||
wanIP netip.Addr
|
wanIP netip.Addr
|
||||||
|
|
||||||
out map[hardKeyOut]portMappingAndTime
|
out map[srcDstTuple]portMappingAndTime
|
||||||
in map[hardKeyIn]lanAddrAndTime
|
in map[hardKeyIn]lanAddrAndTime
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +149,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *hardNAT) PickOutgoingSrc(src, dst netip.AddrPort, at time.Time) (wanSrc netip.AddrPort) {
|
func (n *hardNAT) PickOutgoingSrc(src, dst netip.AddrPort, at time.Time) (wanSrc netip.AddrPort) {
|
||||||
ko := hardKeyOut{src, dst}
|
ko := srcDstTuple{src, dst}
|
||||||
if pm, ok := n.out[ko]; ok {
|
if pm, ok := n.out[ko]; ok {
|
||||||
// Existing flow.
|
// Existing flow.
|
||||||
// TODO: bump timestamp
|
// TODO: bump timestamp
|
||||||
@ -196,9 +197,10 @@ func (n *hardNAT) PickIncomingDst(src, dst netip.AddrPort, at time.Time) (lanDst
|
|||||||
// Unlike Linux, this implementation is capped at 32k entries and doesn't resort
|
// Unlike Linux, this implementation is capped at 32k entries and doesn't resort
|
||||||
// to other allocation strategies when all 32k WAN ports are taken.
|
// to other allocation strategies when all 32k WAN ports are taken.
|
||||||
type easyNAT struct {
|
type easyNAT struct {
|
||||||
wanIP netip.Addr
|
wanIP netip.Addr
|
||||||
out map[netip.AddrPort]portMappingAndTime
|
out map[netip.AddrPort]portMappingAndTime
|
||||||
in map[uint16]lanAddrAndTime
|
in map[uint16]lanAddrAndTime
|
||||||
|
lastOut map[srcDstTuple]time.Time // (lan:port, wan:port) => last packet out time
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -208,6 +210,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *easyNAT) PickOutgoingSrc(src, dst netip.AddrPort, at time.Time) (wanSrc netip.AddrPort) {
|
func (n *easyNAT) PickOutgoingSrc(src, dst netip.AddrPort, at time.Time) (wanSrc netip.AddrPort) {
|
||||||
|
mak.Set(&n.lastOut, srcDstTuple{src, dst}, at)
|
||||||
if pm, ok := n.out[src]; ok {
|
if pm, ok := n.out[src]; ok {
|
||||||
// Existing flow.
|
// Existing flow.
|
||||||
// TODO: bump timestamp
|
// TODO: bump timestamp
|
||||||
@ -235,5 +238,14 @@ func (n *easyNAT) PickIncomingDst(src, dst netip.AddrPort, at time.Time) (lanDst
|
|||||||
if dst.Addr() != n.wanIP {
|
if dst.Addr() != n.wanIP {
|
||||||
return netip.AddrPort{} // drop; not for us. shouldn't happen if natlabd routing isn't broken.
|
return netip.AddrPort{} // drop; not for us. shouldn't happen if natlabd routing isn't broken.
|
||||||
}
|
}
|
||||||
return n.in[dst.Port()].lanAddr
|
lanDst = n.in[dst.Port()].lanAddr
|
||||||
|
|
||||||
|
// Stateful firewall: drop incoming packets that don't have traffic out.
|
||||||
|
// TODO(bradfitz): verify Linux does this in the router code, not in the NAT code.
|
||||||
|
if t, ok := n.lastOut[srcDstTuple{lanDst, src}]; !ok || at.Sub(t) > 300*time.Second {
|
||||||
|
log.Printf("Drop incoming packet from %v to %v; no recent outgoing packet", src, dst)
|
||||||
|
return netip.AddrPort{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lanDst
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user