cmd/natc: add optional consensus backend

Enable nat connector to be run on a cluster of machines for high
availability.

Updates #14667

Signed-off-by: Fran Bull <fran@tailscale.com>
This commit is contained in:
Fran Bull
2025-04-16 10:21:50 -07:00
committed by franbull
parent 13ee285675
commit 486a55f0a9
7 changed files with 1029 additions and 10 deletions

View File

@@ -10,6 +10,7 @@ import (
"math/big"
"net/netip"
"sync"
"time"
"github.com/gaissmai/bart"
"go4.org/netipx"
@@ -21,12 +22,26 @@ import (
var ErrNoIPsAvailable = errors.New("no IPs available")
type IPPool struct {
// IPPool allocates IPv4 addresses from a pool to DNS domains, on a per tailcfg.NodeID basis.
// For each tailcfg.NodeID, IPv4 addresses are associated with at most one DNS domain.
// Addresses may be reused across other tailcfg.NodeID's for the same or other domains.
type IPPool interface {
// DomainForIP looks up the domain associated with a tailcfg.NodeID and netip.Addr pair.
// If there is no association, the result is empty and ok is false.
DomainForIP(tailcfg.NodeID, netip.Addr, time.Time) (string, bool)
// IPForDomain looks up or creates an IP address allocation for the tailcfg.NodeID and domain pair.
// If no address association is found, one is allocated from the range of free addresses for this tailcfg.NodeID.
// If no more address are available, an error is returned.
IPForDomain(tailcfg.NodeID, string) (netip.Addr, error)
}
type SingleMachineIPPool struct {
perPeerMap syncs.Map[tailcfg.NodeID, *perPeerState]
IPSet *netipx.IPSet
}
func (ipp *IPPool) DomainForIP(from tailcfg.NodeID, addr netip.Addr) (string, bool) {
func (ipp *SingleMachineIPPool) DomainForIP(from tailcfg.NodeID, addr netip.Addr, _ time.Time) (string, bool) {
ps, ok := ipp.perPeerMap.Load(from)
if !ok {
log.Printf("handleTCPFlow: no perPeerState for %v", from)
@@ -40,7 +55,7 @@ func (ipp *IPPool) DomainForIP(from tailcfg.NodeID, addr netip.Addr) (string, bo
return domain, ok
}
func (ipp *IPPool) IPForDomain(from tailcfg.NodeID, domain string) (netip.Addr, error) {
func (ipp *SingleMachineIPPool) IPForDomain(from tailcfg.NodeID, domain string) (netip.Addr, error) {
npps := &perPeerState{
ipset: ipp.IPSet,
}