make hard NAT work

Change-Id: Id7b4195639c7fbff17c5b52e3780a1fdbcefbd31
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2024-07-28 11:43:01 -07:00
parent 92c3a4ce9a
commit 38aa2687ac
2 changed files with 10 additions and 8 deletions

View File

@ -4,6 +4,8 @@ import (
"math/rand/v2"
"net/netip"
"time"
"tailscale.com/util/mak"
)
// NATTable is what a NAT implementation is expected to do.
@ -101,16 +103,16 @@ func (n *hardNAT) PickOutgoingSrc(src, dst netip.AddrPort, at time.Time) (wanSrc
// Instead of proper data structures that would be efficient, we instead
// just loop a bunch and look for a free port. This project is only used
// by tests and doesn't care about performance, this is good enough.
port := src.Port() // start with the port the client used? (TODO: does FreeBSD do this? make knob?)
for {
port := rand.N(uint16(32<<10)) + 32<<10 // pick some "ephemeral" port
ki := hardKeyIn{wanPort: port, src: dst}
if _, ok := n.in[ki]; ok {
// Collision. Try again.
port = rand.N(uint16(32<<10)) + 32<<10 // pick some "ephemeral" port
// Port already in use.
continue
}
n.in[ki] = lanAddrAndTime{lanAddr: src, at: at}
n.out[ko] = portMappingAndTime{port: port, at: at}
mak.Set(&n.in, ki, lanAddrAndTime{lanAddr: src, at: at})
mak.Set(&n.out, ko, portMappingAndTime{port: port, at: at})
return netip.AddrPortFrom(n.wanIP, port)
}
}
@ -160,8 +162,8 @@ func (n *easyNAT) PickOutgoingSrc(src, dst netip.AddrPort, at time.Time) (wanSrc
port := 32<<10 + (start + off)
if _, ok := n.in[port]; !ok {
// Found a free port.
n.out[src] = portMappingAndTime{port: port, at: at}
n.in[port] = lanAddrAndTime{lanAddr: src, at: at}
mak.Set(&n.out, src, portMappingAndTime{port: port, at: at})
mak.Set(&n.in, port, lanAddrAndTime{lanAddr: src, at: at})
return netip.AddrPortFrom(n.wanIP, port)
}
}

View File

@ -81,7 +81,7 @@ func main() {
}
s.nodes[node1.mac] = node1
net1.SetNATTable(&oneToOneNAT{wanIP: net1.wanIP, lanIP: node1.lanIP})
net1.SetNATTable(&hardNAT{wanIP: net1.wanIP})
net2 := &network{
s: s,
mac: MAC{0x52, 0x54, 0x00, 0x01, 0x01, 0x2},