diff --git a/CHANGELOG.md b/CHANGELOG.md index 538d1432..2bf0a6d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Next +- Remove versions older than 1.56 [#2149](https://github.com/juanfont/headscale/pull/2149) + - Clean up old code required by old versions - Improved compatibilty of built-in DERP server with clients connecting over WebSocket. - Allow nodes to use SSH agent forwarding [#2145](https://github.com/juanfont/headscale/pull/2145) diff --git a/hscontrol/mapper/mapper_test.go b/hscontrol/mapper/mapper_test.go index 0484fc02..01f27261 100644 --- a/hscontrol/mapper/mapper_test.go +++ b/hscontrol/mapper/mapper_test.go @@ -244,11 +244,11 @@ func Test_fullMapResponse(t *testing.T) { PrimaryRoutes: []netip.Prefix{netip.MustParsePrefix("192.168.0.0/24")}, LastSeen: &lastSeen, MachineAuthorized: true, - Capabilities: []tailcfg.NodeCapability{ - tailcfg.CapabilityFileSharing, - tailcfg.CapabilityAdmin, - tailcfg.CapabilitySSH, - tailcfg.NodeAttrDisableUPnP, + + CapMap: tailcfg.NodeCapMap{ + tailcfg.CapabilityFileSharing: []tailcfg.RawMessage{}, + tailcfg.CapabilityAdmin: []tailcfg.RawMessage{}, + tailcfg.CapabilitySSH: []tailcfg.RawMessage{}, }, } @@ -299,11 +299,11 @@ func Test_fullMapResponse(t *testing.T) { PrimaryRoutes: []netip.Prefix{}, LastSeen: &lastSeen, MachineAuthorized: true, - Capabilities: []tailcfg.NodeCapability{ - tailcfg.CapabilityFileSharing, - tailcfg.CapabilityAdmin, - tailcfg.CapabilitySSH, - tailcfg.NodeAttrDisableUPnP, + + CapMap: tailcfg.NodeCapMap{ + tailcfg.CapabilityFileSharing: []tailcfg.RawMessage{}, + tailcfg.CapabilityAdmin: []tailcfg.RawMessage{}, + tailcfg.CapabilitySSH: []tailcfg.RawMessage{}, }, } diff --git a/hscontrol/mapper/tail.go b/hscontrol/mapper/tail.go index b0878d1a..a8ccf978 100644 --- a/hscontrol/mapper/tail.go +++ b/hscontrol/mapper/tail.go @@ -114,32 +114,14 @@ func tailNode( Expired: node.IsExpired(), } - // - 74: 2023-09-18: Client understands NodeCapMap - if capVer >= 74 { - tNode.CapMap = tailcfg.NodeCapMap{ - tailcfg.CapabilityFileSharing: []tailcfg.RawMessage{}, - tailcfg.CapabilityAdmin: []tailcfg.RawMessage{}, - tailcfg.CapabilitySSH: []tailcfg.RawMessage{}, - } - - if cfg.RandomizeClientPort { - tNode.CapMap[tailcfg.NodeAttrRandomizeClientPort] = []tailcfg.RawMessage{} - } - } else { - tNode.Capabilities = []tailcfg.NodeCapability{ - tailcfg.CapabilityFileSharing, - tailcfg.CapabilityAdmin, - tailcfg.CapabilitySSH, - } - - if cfg.RandomizeClientPort { - tNode.Capabilities = append(tNode.Capabilities, tailcfg.NodeAttrRandomizeClientPort) - } + tNode.CapMap = tailcfg.NodeCapMap{ + tailcfg.CapabilityFileSharing: []tailcfg.RawMessage{}, + tailcfg.CapabilityAdmin: []tailcfg.RawMessage{}, + tailcfg.CapabilitySSH: []tailcfg.RawMessage{}, } - // - 72: 2023-08-23: TS-2023-006 UPnP issue fixed; UPnP can now be used again - if capVer < 72 { - tNode.Capabilities = append(tNode.Capabilities, tailcfg.NodeAttrDisableUPnP) + if cfg.RandomizeClientPort { + tNode.CapMap[tailcfg.NodeAttrRandomizeClientPort] = []tailcfg.RawMessage{} } if node.IsOnline == nil || !*node.IsOnline { diff --git a/hscontrol/mapper/tail_test.go b/hscontrol/mapper/tail_test.go index f744c9c6..c0d1c146 100644 --- a/hscontrol/mapper/tail_test.go +++ b/hscontrol/mapper/tail_test.go @@ -72,9 +72,11 @@ func TestTailNode(t *testing.T) { Tags: []string{}, PrimaryRoutes: []netip.Prefix{}, MachineAuthorized: true, - Capabilities: []tailcfg.NodeCapability{ - "https://tailscale.com/cap/file-sharing", "https://tailscale.com/cap/is-admin", - "https://tailscale.com/cap/ssh", "debug-disable-upnp", + + CapMap: tailcfg.NodeCapMap{ + tailcfg.CapabilityFileSharing: []tailcfg.RawMessage{}, + tailcfg.CapabilityAdmin: []tailcfg.RawMessage{}, + tailcfg.CapabilitySSH: []tailcfg.RawMessage{}, }, }, wantErr: false, @@ -166,11 +168,10 @@ func TestTailNode(t *testing.T) { LastSeen: &lastSeen, MachineAuthorized: true, - Capabilities: []tailcfg.NodeCapability{ - tailcfg.CapabilityFileSharing, - tailcfg.CapabilityAdmin, - tailcfg.CapabilitySSH, - tailcfg.NodeAttrDisableUPnP, + CapMap: tailcfg.NodeCapMap{ + tailcfg.CapabilityFileSharing: []tailcfg.RawMessage{}, + tailcfg.CapabilityAdmin: []tailcfg.RawMessage{}, + tailcfg.CapabilitySSH: []tailcfg.RawMessage{}, }, }, wantErr: false, diff --git a/hscontrol/metrics.go b/hscontrol/metrics.go index 4870e74e..0be59eec 100644 --- a/hscontrol/metrics.go +++ b/hscontrol/metrics.go @@ -37,11 +37,6 @@ var ( Name: "mapresponse_updates_received_total", Help: "total count of mapresponse updates received on update channel", }, []string{"type"}) - mapResponseWriteUpdatesInStream = promauto.NewCounterVec(prometheus.CounterOpts{ - Namespace: prometheusNamespace, - Name: "mapresponse_write_updates_in_stream_total", - Help: "total count of writes that occurred in a stream session, pre-68 nodes", - }, []string{"status"}) mapResponseEndpointUpdates = promauto.NewCounterVec(prometheus.CounterOpts{ Namespace: prometheusNamespace, Name: "mapresponse_endpoint_updates_total", diff --git a/hscontrol/noise.go b/hscontrol/noise.go index 554be65c..35450809 100644 --- a/hscontrol/noise.go +++ b/hscontrol/noise.go @@ -166,7 +166,7 @@ func (ns *noiseServer) earlyNoise(protocolVersion int, writer io.Writer) error { } const ( - MinimumCapVersion tailcfg.CapabilityVersion = 61 + MinimumCapVersion tailcfg.CapabilityVersion = 82 ) // NoisePollNetMapHandler takes care of /machine/:id/map using the Noise protocol @@ -182,15 +182,6 @@ func (ns *noiseServer) NoisePollNetMapHandler( writer http.ResponseWriter, req *http.Request, ) { - log.Trace(). - Str("handler", "NoisePollNetMap"). - Msg("PollNetMapHandler called") - - log.Trace(). - Any("headers", req.Header). - Caller(). - Msg("Headers") - body, _ := io.ReadAll(req.Body) mapRequest := tailcfg.MapRequest{} @@ -204,6 +195,14 @@ func (ns *noiseServer) NoisePollNetMapHandler( return } + log.Trace(). + Caller(). + Str("handler", "NoisePollNetMap"). + Any("headers", req.Header). + Str("node", mapRequest.Hostinfo.Hostname). + Int("capver", int(mapRequest.Version)). + Msg("PollNetMapHandler called") + // Reject unsupported versions if mapRequest.Version < MinimumCapVersion { log.Info(). diff --git a/hscontrol/poll.go b/hscontrol/poll.go index 82a5295f..252f338b 100644 --- a/hscontrol/poll.go +++ b/hscontrol/poll.go @@ -214,21 +214,6 @@ func (m *mapSession) serveLongPoll() { m.infof("node has disconnected, mapSession: %p, chan: %p", m, m.ch) }() - // From version 68, all streaming requests can be treated as read only. - // TODO: Remove when we drop support for 1.48 - if m.capVer < 68 { - // Error has been handled/written to client in the func - // return - err := m.handleSaveNode() - if err != nil { - mapResponseWriteUpdatesInStream.WithLabelValues("error").Inc() - - m.close() - return - } - mapResponseWriteUpdatesInStream.WithLabelValues("ok").Inc() - } - // Set up the client stream m.h.pollNetMapStreamWG.Add(1) defer m.h.pollNetMapStreamWG.Done() @@ -549,72 +534,6 @@ func (m *mapSession) handleEndpointUpdate() { return } -// handleSaveNode saves node updates in the maprequest _streaming_ -// path and is mostly the same code as in handleEndpointUpdate. -// It is not attempted to be deduplicated since it will go away -// when we stop supporting older than 68 which removes updates -// when the node is streaming. -func (m *mapSession) handleSaveNode() error { - m.tracef("saving node update from stream session") - - change := m.node.PeerChangeFromMapRequest(m.req) - - // A stream is being set up, the node is Online - online := true - change.Online = &online - - m.node.ApplyPeerChange(&change) - - sendUpdate, routesChanged := hostInfoChanged(m.node.Hostinfo, m.req.Hostinfo) - m.node.Hostinfo = m.req.Hostinfo - - // If there is no changes and nothing to save, - // return early. - if peerChangeEmpty(change) || !sendUpdate { - return nil - } - - // Check if the Hostinfo of the node has changed. - // If it has changed, check if there has been a change to - // the routable IPs of the host and update update them in - // the database. Then send a Changed update - // (containing the whole node object) to peers to inform about - // the route change. - // If the hostinfo has changed, but not the routes, just update - // hostinfo and let the function continue. - if routesChanged { - var err error - _, err = m.h.db.SaveNodeRoutes(m.node) - if err != nil { - return err - } - - if m.h.ACLPolicy != nil { - // update routes with peer information - err := m.h.db.EnableAutoApprovedRoutes(m.h.ACLPolicy, m.node) - if err != nil { - return err - } - } - } - - if err := m.h.db.DB.Save(m.node).Error; err != nil { - return err - } - - ctx := types.NotifyCtx(context.Background(), "pre-68-update-while-stream", m.node.Hostname) - m.h.nodeNotifier.NotifyWithIgnore( - ctx, - types.StateUpdate{ - Type: types.StatePeerChanged, - ChangeNodes: []types.NodeID{m.node.ID}, - Message: "called from handlePoll -> pre-68-update-while-stream", - }, - m.node.ID) - - return nil -} - func (m *mapSession) handleReadOnlyRequest() { m.tracef("Client asked for a lite update, responding without peers") diff --git a/integration/scenario.go b/integration/scenario.go index df978f2a..b45c5fe7 100644 --- a/integration/scenario.go +++ b/integration/scenario.go @@ -53,21 +53,23 @@ var ( tailscaleVersions2021 = map[string]bool{ "head": true, "unstable": true, - "1.70": true, // CapVer: not checked - "1.68": true, // CapVer: not checked - "1.66": true, // CapVer: not checked - "1.64": true, // CapVer: not checked - "1.62": true, // CapVer: not checked - "1.60": true, // CapVer: not checked - "1.58": true, // CapVer: not checked - "1.56": true, // CapVer: 82 - "1.54": true, // CapVer: 79 - "1.52": true, // CapVer: 79 - "1.50": true, // CapVer: 74 - "1.48": true, // CapVer: 68 - "1.46": true, // CapVer: 65 + "1.74": true, // CapVer: 106 + "1.72": true, // CapVer: 104 + "1.70": true, // CapVer: 102 + "1.68": true, // CapVer: 97 + "1.66": true, // CapVer: 95 + "1.64": true, // CapVer: 90 + "1.62": true, // CapVer: 88 + "1.60": true, // CapVer: 87 + "1.58": true, // CapVer: 85 + "1.56": true, // Oldest supported version, CapVer: 82 + "1.54": false, // CapVer: 79 + "1.52": false, // CapVer: 79 + "1.50": false, // CapVer: 74 + "1.48": false, // CapVer: 68 + "1.46": false, // CapVer: 65 "1.44": false, // CapVer: 63 - "1.42": false, // Oldest supported version, CapVer: 61 + "1.42": false, // CapVer: 61 "1.40": false, // CapVer: 61 "1.38": false, // CapVer: 58 "1.36": false, // CapVer: 56