mirror of
https://github.com/tailscale/tailscale.git
synced 2025-12-23 17:16:29 +00:00
net/tstun: add TSMPDiscoAdvertisement to TSMPPing (#17995)
Adds a new types of TSMP messages for advertising disco keys keys to/from a peer, and implements the advertising triggered by a TSMP ping. Needed as part of the effort to cache the netmap and still let clients connect without control being reachable. Updates #12639 Signed-off-by: Claus Lensbøl <claus@tailscale.com> Co-authored-by: James Tucker <james@tailscale.com>
This commit is contained in:
@@ -36,6 +36,8 @@ import (
|
||||
"tailscale.com/types/netlogtype"
|
||||
"tailscale.com/types/ptr"
|
||||
"tailscale.com/types/views"
|
||||
"tailscale.com/util/eventbus"
|
||||
"tailscale.com/util/eventbus/eventbustest"
|
||||
"tailscale.com/util/must"
|
||||
"tailscale.com/util/usermetric"
|
||||
"tailscale.com/wgengine/filter"
|
||||
@@ -170,10 +172,10 @@ func setfilter(logf logger.Logf, tun *Wrapper) {
|
||||
tun.SetFilter(filter.New(matches, nil, ipSet, ipSet, nil, logf))
|
||||
}
|
||||
|
||||
func newChannelTUN(logf logger.Logf, secure bool) (*tuntest.ChannelTUN, *Wrapper) {
|
||||
func newChannelTUN(logf logger.Logf, bus *eventbus.Bus, secure bool) (*tuntest.ChannelTUN, *Wrapper) {
|
||||
chtun := tuntest.NewChannelTUN()
|
||||
reg := new(usermetric.Registry)
|
||||
tun := Wrap(logf, chtun.TUN(), reg)
|
||||
tun := Wrap(logf, chtun.TUN(), reg, bus)
|
||||
if secure {
|
||||
setfilter(logf, tun)
|
||||
} else {
|
||||
@@ -183,10 +185,10 @@ func newChannelTUN(logf logger.Logf, secure bool) (*tuntest.ChannelTUN, *Wrapper
|
||||
return chtun, tun
|
||||
}
|
||||
|
||||
func newFakeTUN(logf logger.Logf, secure bool) (*fakeTUN, *Wrapper) {
|
||||
func newFakeTUN(logf logger.Logf, bus *eventbus.Bus, secure bool) (*fakeTUN, *Wrapper) {
|
||||
ftun := NewFake()
|
||||
reg := new(usermetric.Registry)
|
||||
tun := Wrap(logf, ftun, reg)
|
||||
tun := Wrap(logf, ftun, reg, bus)
|
||||
if secure {
|
||||
setfilter(logf, tun)
|
||||
} else {
|
||||
@@ -196,7 +198,8 @@ func newFakeTUN(logf logger.Logf, secure bool) (*fakeTUN, *Wrapper) {
|
||||
}
|
||||
|
||||
func TestReadAndInject(t *testing.T) {
|
||||
chtun, tun := newChannelTUN(t.Logf, false)
|
||||
bus := eventbustest.NewBus(t)
|
||||
chtun, tun := newChannelTUN(t.Logf, bus, false)
|
||||
defer tun.Close()
|
||||
|
||||
const size = 2 // all payloads have this size
|
||||
@@ -221,7 +224,7 @@ func TestReadAndInject(t *testing.T) {
|
||||
}
|
||||
|
||||
var buf [MaxPacketSize]byte
|
||||
var seen = make(map[string]bool)
|
||||
seen := make(map[string]bool)
|
||||
sizes := make([]int, 1)
|
||||
// We expect the same packets back, in no particular order.
|
||||
for i := range len(written) + len(injected) {
|
||||
@@ -257,7 +260,8 @@ func TestReadAndInject(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWriteAndInject(t *testing.T) {
|
||||
chtun, tun := newChannelTUN(t.Logf, false)
|
||||
bus := eventbustest.NewBus(t)
|
||||
chtun, tun := newChannelTUN(t.Logf, bus, false)
|
||||
defer tun.Close()
|
||||
|
||||
written := []string{"w0", "w1"}
|
||||
@@ -316,8 +320,8 @@ func mustHexDecode(s string) []byte {
|
||||
}
|
||||
|
||||
func TestFilter(t *testing.T) {
|
||||
|
||||
chtun, tun := newChannelTUN(t.Logf, true)
|
||||
bus := eventbustest.NewBus(t)
|
||||
chtun, tun := newChannelTUN(t.Logf, bus, true)
|
||||
defer tun.Close()
|
||||
|
||||
// Reset the metrics before test. These are global
|
||||
@@ -462,7 +466,8 @@ func assertMetricPackets(t *testing.T, metricName string, want, got int64) {
|
||||
}
|
||||
|
||||
func TestAllocs(t *testing.T) {
|
||||
ftun, tun := newFakeTUN(t.Logf, false)
|
||||
bus := eventbustest.NewBus(t)
|
||||
ftun, tun := newFakeTUN(t.Logf, bus, false)
|
||||
defer tun.Close()
|
||||
|
||||
buf := [][]byte{{0x00}}
|
||||
@@ -473,14 +478,14 @@ func TestAllocs(t *testing.T) {
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClose(t *testing.T) {
|
||||
ftun, tun := newFakeTUN(t.Logf, false)
|
||||
bus := eventbustest.NewBus(t)
|
||||
ftun, tun := newFakeTUN(t.Logf, bus, false)
|
||||
|
||||
data := [][]byte{udp4("1.2.3.4", "5.6.7.8", 98, 98)}
|
||||
_, err := ftun.Write(data, 0)
|
||||
@@ -497,7 +502,8 @@ func TestClose(t *testing.T) {
|
||||
|
||||
func BenchmarkWrite(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
ftun, tun := newFakeTUN(b.Logf, true)
|
||||
bus := eventbustest.NewBus(b)
|
||||
ftun, tun := newFakeTUN(b.Logf, bus, true)
|
||||
defer tun.Close()
|
||||
|
||||
packet := [][]byte{udp4("5.6.7.8", "1.2.3.4", 89, 89)}
|
||||
@@ -887,7 +893,8 @@ func TestCaptureHook(t *testing.T) {
|
||||
|
||||
now := time.Unix(1682085856, 0)
|
||||
|
||||
_, w := newFakeTUN(t.Logf, true)
|
||||
bus := eventbustest.NewBus(t)
|
||||
_, w := newFakeTUN(t.Logf, bus, true)
|
||||
w.timeNow = func() time.Time {
|
||||
return now
|
||||
}
|
||||
@@ -957,3 +964,30 @@ func TestCaptureHook(t *testing.T) {
|
||||
captured, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTSMPDisco(t *testing.T) {
|
||||
t.Run("IPv6DiscoAdvert", func(t *testing.T) {
|
||||
src := netip.MustParseAddr("2001:db8::1")
|
||||
dst := netip.MustParseAddr("2001:db8::2")
|
||||
discoKey := key.NewDisco()
|
||||
buf, _ := (&packet.TSMPDiscoKeyAdvertisement{
|
||||
Src: src,
|
||||
Dst: dst,
|
||||
Key: discoKey.Public(),
|
||||
}).Marshal()
|
||||
|
||||
var p packet.Parsed
|
||||
p.Decode(buf)
|
||||
|
||||
tda, ok := p.AsTSMPDiscoAdvertisement()
|
||||
if !ok {
|
||||
t.Error("Unable to parse message as TSMPDiscoAdversitement")
|
||||
}
|
||||
if tda.Src != src {
|
||||
t.Errorf("Src address did not match, expected %v, got %v", src, tda.Src)
|
||||
}
|
||||
if !reflect.DeepEqual(tda.Key, discoKey.Public()) {
|
||||
t.Errorf("Key did not match, expected %q, got %q", discoKey.Public(), tda.Key)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user