mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 04:55:31 +00:00
ipn/ipnlocal,net/tstun,wgengine: create and plumb jailed packet filter
This plumbs a packet filter for jailed nodes through to the tstun.Wrapper; the filter for a jailed node is equivalent to a "shields up" filter. Currently a no-op as there is no way for control to tell the client whether a peer is jailed. Updates tailscale/corp#19623 Co-authored-by: Andrew Dunham <andrew@du.nham.ca> Signed-off-by: Maisem Ali <maisem@tailscale.com> Change-Id: I5ccc5f00e197fde15dd567485b2a99d8254391ad
This commit is contained in:
parent
f62e678df8
commit
e67069550b
@ -440,7 +440,9 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, sys *tsd.System, lo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default filter blocks everything and logs nothing, until Start() is called.
|
// Default filter blocks everything and logs nothing, until Start() is called.
|
||||||
b.setFilter(filter.NewAllowNone(logf, &netipx.IPSet{}))
|
noneFilter := filter.NewAllowNone(logf, &netipx.IPSet{})
|
||||||
|
b.setFilter(noneFilter)
|
||||||
|
b.e.SetJailedFilter(noneFilter)
|
||||||
|
|
||||||
b.setTCPPortsIntercepted(nil)
|
b.setTCPPortsIntercepted(nil)
|
||||||
|
|
||||||
@ -1935,7 +1937,9 @@ func (b *LocalBackend) updateFilterLocked(netMap *netmap.NetworkMap, prefs ipn.P
|
|||||||
|
|
||||||
if !haveNetmap {
|
if !haveNetmap {
|
||||||
b.logf("[v1] netmap packet filter: (not ready yet)")
|
b.logf("[v1] netmap packet filter: (not ready yet)")
|
||||||
b.setFilter(filter.NewAllowNone(b.logf, logNets))
|
noneFilter := filter.NewAllowNone(b.logf, logNets)
|
||||||
|
b.setFilter(noneFilter)
|
||||||
|
b.e.SetJailedFilter(noneFilter)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1947,6 +1951,9 @@ func (b *LocalBackend) updateFilterLocked(netMap *netmap.NetworkMap, prefs ipn.P
|
|||||||
b.logf("[v1] netmap packet filter: %v filters", len(packetFilter))
|
b.logf("[v1] netmap packet filter: %v filters", len(packetFilter))
|
||||||
b.setFilter(filter.New(packetFilter, localNets, logNets, oldFilter, b.logf))
|
b.setFilter(filter.New(packetFilter, localNets, logNets, oldFilter, b.logf))
|
||||||
}
|
}
|
||||||
|
// The filter for a jailed node is the exact same as a ShieldsUp filter.
|
||||||
|
oldJailedFilter := b.e.GetJailedFilter()
|
||||||
|
b.e.SetJailedFilter(filter.NewShieldsUpFilter(localNets, logNets, oldJailedFilter, b.logf))
|
||||||
|
|
||||||
if b.sshServer != nil {
|
if b.sshServer != nil {
|
||||||
go b.sshServer.OnPolicyChange()
|
go b.sshServer.OnPolicyChange()
|
||||||
|
@ -153,6 +153,9 @@ type Wrapper struct {
|
|||||||
filter atomic.Pointer[filter.Filter]
|
filter atomic.Pointer[filter.Filter]
|
||||||
// filterFlags control the verbosity of logging packet drops/accepts.
|
// filterFlags control the verbosity of logging packet drops/accepts.
|
||||||
filterFlags filter.RunFlags
|
filterFlags filter.RunFlags
|
||||||
|
// jailedFilter is the packet filter for jailed nodes.
|
||||||
|
// Can be nil, which means drop all packets.
|
||||||
|
jailedFilter atomic.Pointer[filter.Filter]
|
||||||
|
|
||||||
// PreFilterPacketInboundFromWireGuard is the inbound filter function that runs before the main filter
|
// PreFilterPacketInboundFromWireGuard is the inbound filter function that runs before the main filter
|
||||||
// and therefore sees the packets that may be later dropped by it.
|
// and therefore sees the packets that may be later dropped by it.
|
||||||
@ -572,6 +575,11 @@ type peerConfig struct {
|
|||||||
// masqueraded for that address family.
|
// masqueraded for that address family.
|
||||||
dstMasqAddr4 netip.Addr
|
dstMasqAddr4 netip.Addr
|
||||||
dstMasqAddr6 netip.Addr
|
dstMasqAddr6 netip.Addr
|
||||||
|
|
||||||
|
// jailed is whether this peer is "jailed" (i.e. is restricted from being
|
||||||
|
// able to initiate connections to this node). This is the case for shared
|
||||||
|
// nodes.
|
||||||
|
jailed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *peerConfigTable) String() string {
|
func (c *peerConfigTable) String() string {
|
||||||
@ -597,7 +605,8 @@ func (c *peerConfig) String() string {
|
|||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
b.WriteString("peerConfig{")
|
b.WriteString("peerConfig{")
|
||||||
fmt.Fprintf(&b, "dstMasqAddr4: %v, ", c.dstMasqAddr4)
|
fmt.Fprintf(&b, "dstMasqAddr4: %v, ", c.dstMasqAddr4)
|
||||||
fmt.Fprintf(&b, "dstMasqAddr6: %v}", c.dstMasqAddr6)
|
fmt.Fprintf(&b, "dstMasqAddr6: %v, ", c.dstMasqAddr6)
|
||||||
|
fmt.Fprintf(&b, "jailed: %v}", c.jailed)
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
@ -735,10 +744,13 @@ func peerConfigTableFromWGConfig(wcfg *wgcfg.Config) *peerConfigTable {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const peerIsJailed = false // TODO: implement jailed peers
|
||||||
|
|
||||||
// Use the same peer configuration for each address of the peer.
|
// Use the same peer configuration for each address of the peer.
|
||||||
pc := &peerConfig{
|
pc := &peerConfig{
|
||||||
dstMasqAddr4: addrToUse4,
|
dstMasqAddr4: addrToUse4,
|
||||||
dstMasqAddr6: addrToUse6,
|
dstMasqAddr6: addrToUse6,
|
||||||
|
jailed: peerIsJailed,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert an entry into our routing table for each allowed IP.
|
// Insert an entry into our routing table for each allowed IP.
|
||||||
@ -753,6 +765,28 @@ func peerConfigTableFromWGConfig(wcfg *wgcfg.Config) *peerConfigTable {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pc *peerConfigTable) inboundPacketIsJailed(p *packet.Parsed) bool {
|
||||||
|
if pc == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
c, ok := pc.byIP.Get(p.Src.Addr())
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return c.jailed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pc *peerConfigTable) outboundPacketIsJailed(p *packet.Parsed) bool {
|
||||||
|
if pc == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
c, ok := pc.byIP.Get(p.Dst.Addr())
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return c.jailed
|
||||||
|
}
|
||||||
|
|
||||||
// SetNetMap is called when a new NetworkMap is received.
|
// SetNetMap is called when a new NetworkMap is received.
|
||||||
func (t *Wrapper) SetWGConfig(wcfg *wgcfg.Config) {
|
func (t *Wrapper) SetWGConfig(wcfg *wgcfg.Config) {
|
||||||
cfg := peerConfigTableFromWGConfig(wcfg)
|
cfg := peerConfigTableFromWGConfig(wcfg)
|
||||||
@ -812,7 +846,14 @@ func (t *Wrapper) filterPacketOutboundToWireGuard(p *packet.Parsed, pc *peerConf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
filt := t.filter.Load()
|
// If the outbound packet is to a jailed peer, use our jailed peer
|
||||||
|
// packet filter.
|
||||||
|
var filt *filter.Filter
|
||||||
|
if pc.outboundPacketIsJailed(p) {
|
||||||
|
filt = t.jailedFilter.Load()
|
||||||
|
} else {
|
||||||
|
filt = t.filter.Load()
|
||||||
|
}
|
||||||
if filt == nil {
|
if filt == nil {
|
||||||
return filter.Drop
|
return filter.Drop
|
||||||
}
|
}
|
||||||
@ -993,7 +1034,12 @@ func (t *Wrapper) filterPacketInboundFromWireGuard(p *packet.Parsed, captHook ca
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
filt := t.filter.Load()
|
var filt *filter.Filter
|
||||||
|
if pc.inboundPacketIsJailed(p) {
|
||||||
|
filt = t.jailedFilter.Load()
|
||||||
|
} else {
|
||||||
|
filt = t.filter.Load()
|
||||||
|
}
|
||||||
if filt == nil {
|
if filt == nil {
|
||||||
return filter.Drop
|
return filter.Drop
|
||||||
}
|
}
|
||||||
@ -1098,6 +1144,14 @@ func (t *Wrapper) SetFilter(filt *filter.Filter) {
|
|||||||
t.filter.Store(filt)
|
t.filter.Store(filt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Wrapper) GetJailedFilter() *filter.Filter {
|
||||||
|
return t.jailedFilter.Load()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Wrapper) SetJailedFilter(filt *filter.Filter) {
|
||||||
|
t.jailedFilter.Store(filt)
|
||||||
|
}
|
||||||
|
|
||||||
// InjectInboundPacketBuffer makes the Wrapper device behave as if a packet
|
// InjectInboundPacketBuffer makes the Wrapper device behave as if a packet
|
||||||
// with the given contents was received from the network.
|
// with the given contents was received from the network.
|
||||||
// It takes ownership of one reference count on the packet. The injected
|
// It takes ownership of one reference count on the packet. The injected
|
||||||
|
@ -1037,6 +1037,14 @@ func (e *userspaceEngine) SetFilter(filt *filter.Filter) {
|
|||||||
e.tundev.SetFilter(filt)
|
e.tundev.SetFilter(filt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *userspaceEngine) GetJailedFilter() *filter.Filter {
|
||||||
|
return e.tundev.GetJailedFilter()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *userspaceEngine) SetJailedFilter(filt *filter.Filter) {
|
||||||
|
e.tundev.SetJailedFilter(filt)
|
||||||
|
}
|
||||||
|
|
||||||
func (e *userspaceEngine) SetStatusCallback(cb StatusCallback) {
|
func (e *userspaceEngine) SetStatusCallback(cb StatusCallback) {
|
||||||
e.mu.Lock()
|
e.mu.Lock()
|
||||||
defer e.mu.Unlock()
|
defer e.mu.Unlock()
|
||||||
|
@ -129,6 +129,12 @@ func (e *watchdogEngine) GetFilter() *filter.Filter {
|
|||||||
func (e *watchdogEngine) SetFilter(filt *filter.Filter) {
|
func (e *watchdogEngine) SetFilter(filt *filter.Filter) {
|
||||||
e.watchdog("SetFilter", func() { e.wrap.SetFilter(filt) })
|
e.watchdog("SetFilter", func() { e.wrap.SetFilter(filt) })
|
||||||
}
|
}
|
||||||
|
func (e *watchdogEngine) GetJailedFilter() *filter.Filter {
|
||||||
|
return e.wrap.GetJailedFilter()
|
||||||
|
}
|
||||||
|
func (e *watchdogEngine) SetJailedFilter(filt *filter.Filter) {
|
||||||
|
e.watchdog("SetJailedFilter", func() { e.wrap.SetJailedFilter(filt) })
|
||||||
|
}
|
||||||
func (e *watchdogEngine) SetStatusCallback(cb StatusCallback) {
|
func (e *watchdogEngine) SetStatusCallback(cb StatusCallback) {
|
||||||
e.watchdog("SetStatusCallback", func() { e.wrap.SetStatusCallback(cb) })
|
e.watchdog("SetStatusCallback", func() { e.wrap.SetStatusCallback(cb) })
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,13 @@ type Engine interface {
|
|||||||
// SetFilter updates the packet filter.
|
// SetFilter updates the packet filter.
|
||||||
SetFilter(*filter.Filter)
|
SetFilter(*filter.Filter)
|
||||||
|
|
||||||
|
// GetJailedFilter returns the current packet filter for jailed nodes,
|
||||||
|
// if any.
|
||||||
|
GetJailedFilter() *filter.Filter
|
||||||
|
|
||||||
|
// SetJailedFilter updates the packet filter for jailed nodes.
|
||||||
|
SetJailedFilter(*filter.Filter)
|
||||||
|
|
||||||
// SetStatusCallback sets the function to call when the
|
// SetStatusCallback sets the function to call when the
|
||||||
// WireGuard status changes.
|
// WireGuard status changes.
|
||||||
SetStatusCallback(StatusCallback)
|
SetStatusCallback(StatusCallback)
|
||||||
|
Loading…
Reference in New Issue
Block a user