diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 99cc36fa..37a8cb80 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -7,5 +7,5 @@ contact_links: url: "https://github.com/juanfont/headscale/blob/main/docs" about: "Find documentation about how to configure and run headscale." - name: "headscale Discord community" - url: "https://discord.com/invite/XcQxk2VHjx" + url: "https://discord.gg/xGj2TuqyxY" about: "Please ask and answer questions about usage of headscale here." diff --git a/CHANGELOG.md b/CHANGELOG.md index c970be23..359ace64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Headscale fails to serve if the ACL policy file cannot be parsed [#537](https://github.com/juanfont/headscale/pull/537) - Fix labels cardinality error when registering unknown pre-auth key [#519](https://github.com/juanfont/headscale/pull/519) +- Fix send on closed channel crash in polling [#542](https://github.com/juanfont/headscale/pull/542) ## 0.15.0 (2022-03-20) diff --git a/Makefile b/Makefile index 73630d3f..74ecd89e 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # Calculate version -version = $(shell ./scripts/version-at-commit.sh) +version = $(git describe --always --tags --dirty) rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)) @@ -10,7 +10,7 @@ PROTO_SOURCES = $(call rwildcard,,*.proto) build: - GGO_ENABLED=0 go build -ldflags "-s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=$(version)" cmd/headscale/headscale.go + CGO_ENABLED=0 go build -trimpath -buildmode=pie -mod=readonly -ldflags "-s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=$(version)" cmd/headscale/headscale.go dev: lint test build diff --git a/README.md b/README.md index b2bac98d..7f712416 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ An open source, self-hosted implementation of the Tailscale control server. -Join our [Discord](https://discord.gg/XcQxk2VHjx) server for a chat. +Join our [Discord](https://discord.gg/xGj2TuqyxY) server for a chat. **Note:** Always select the same GitHub tag as the released version you use to ensure you have the correct example configuration and documentation. @@ -280,6 +280,13 @@ make build + + + Artem +
+ Artem Klevtsov +
+ Casey @@ -315,6 +322,8 @@ make build thomas + + Abraham @@ -322,8 +331,6 @@ make build Abraham Ingersoll - - Aofei @@ -331,13 +338,6 @@ make build Aofei Sheng - - - Artem -
- Artem Klevtsov -
- Arthur @@ -352,6 +352,13 @@ make build Bryan Stenson + + + Carson +
+ Carson Yang +
+ Felix @@ -359,6 +366,8 @@ make build Felix Kronlage-Dammers + + Felix @@ -366,8 +375,6 @@ make build Felix Yan - - JJGadgets/ @@ -403,6 +410,8 @@ make build rcursaru + + WhiteSource @@ -410,8 +419,6 @@ make build WhiteSource Renovate - - Ryan @@ -447,6 +454,8 @@ make build The Gitter Badger + + Tianon @@ -454,8 +463,6 @@ make build Tianon Gravi - - Tjerk @@ -491,6 +498,8 @@ make build bravechamp + + derelm/ @@ -498,8 +507,13 @@ make build derelm - - + + + henning +
+ henning mueller +
+ ignoramous/ @@ -528,6 +542,8 @@ make build Wakeful-Cloud + + zy/ diff --git a/derp-example.yaml b/derp-example.yaml index 0ebe32ed..732c4ba0 100644 --- a/derp-example.yaml +++ b/derp-example.yaml @@ -12,4 +12,4 @@ regions: ipv6: "2604:a880:400:d1::828:b001" stunport: 0 stunonly: false - derptestport: 0 + derpport: 0 diff --git a/docs/running-headscale-linux.md b/docs/running-headscale-linux.md index 1e9d11c4..98a67f1d 100644 --- a/docs/running-headscale-linux.md +++ b/docs/running-headscale-linux.md @@ -178,7 +178,7 @@ systemctl status headscale Verify `headscale` is available: ```shell -curl http://127.0.0.1:8080/metrics +curl http://127.0.0.1:9090/metrics ``` `headscale` will now run in the background and start at boot. diff --git a/poll.go b/poll.go index 15945a9b..3bad0b89 100644 --- a/poll.go +++ b/poll.go @@ -175,32 +175,13 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) { Str("machine", machine.Name). Msg("Loading or creating update channel") - // TODO: could probably remove all that duplication once generics land. - closeChanWithLog := func(channel interface{}, name string) { - log.Trace(). - Str("handler", "PollNetMap"). - Str("machine", machine.Name). - Str("channel", "Done"). - Msg(fmt.Sprintf("Closing %s channel", name)) - - switch c := channel.(type) { - case (chan struct{}): - close(c) - - case (chan []byte): - close(c) - } - } - const chanSize = 8 updateChan := make(chan struct{}, chanSize) - defer closeChanWithLog(updateChan, "updateChan") pollDataChan := make(chan []byte, chanSize) - defer closeChanWithLog(pollDataChan, "pollDataChan") + defer closeChanWithLog(pollDataChan, machine.Name, "pollDataChan") keepAliveChan := make(chan []byte) - defer closeChanWithLog(keepAliveChan, "keepAliveChan") if req.OmitPeers && !req.Stream { log.Info(). @@ -273,7 +254,27 @@ func (h *Headscale) PollNetMapStream( updateChan chan struct{}, ) { { - ctx, cancel := context.WithCancel(ctx.Request.Context()) + machine, err := h.GetMachineByMachineKey(machineKey) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + log.Warn(). + Str("handler", "PollNetMap"). + Msgf("Ignoring request, cannot find machine with key %s", machineKey.String()) + ctx.String(http.StatusUnauthorized, "") + + return + } + log.Error(). + Str("handler", "PollNetMap"). + Msgf("Failed to fetch machine from the database with Machine key: %s", machineKey.String()) + ctx.String(http.StatusInternalServerError, "") + + return + } + + ctx := context.WithValue(ctx.Request.Context(), "machineName", machine.Name) + + ctx, cancel := context.WithCancel(ctx) defer cancel() go h.scheduledPollWorker( @@ -564,8 +565,8 @@ func (h *Headscale) PollNetMapStream( func (h *Headscale) scheduledPollWorker( ctx context.Context, - updateChan chan<- struct{}, - keepAliveChan chan<- []byte, + updateChan chan struct{}, + keepAliveChan chan []byte, machineKey key.MachinePublic, mapRequest tailcfg.MapRequest, machine *Machine, @@ -573,6 +574,17 @@ func (h *Headscale) scheduledPollWorker( keepAliveTicker := time.NewTicker(keepAliveInterval) updateCheckerTicker := time.NewTicker(updateCheckInterval) + defer closeChanWithLog( + updateChan, + fmt.Sprint(ctx.Value("machineName")), + "updateChan", + ) + defer closeChanWithLog( + keepAliveChan, + fmt.Sprint(ctx.Value("machineName")), + "updateChan", + ) + for { select { case <-ctx.Done(): @@ -606,3 +618,13 @@ func (h *Headscale) scheduledPollWorker( } } } + +func closeChanWithLog[C chan []byte | chan struct{}](channel C, machine, name string) { + log.Trace(). + Str("handler", "PollNetMap"). + Str("machine", machine). + Str("channel", "Done"). + Msg(fmt.Sprintf("Closing %s channel", name)) + + close(channel) +} diff --git a/scripts/version-at-commit.sh b/scripts/version-at-commit.sh deleted file mode 100755 index 2f7fab84..00000000 --- a/scripts/version-at-commit.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash - -set -e -o pipefail -commit="$1" -versionglob="v[0-9].[0-9]*.[0-9]*" -devsuffix=".dev" -if [ -z "$commit" ]; then - commit=`git log -n1 --first-parent "--format=format:%h"` -fi - -# automatically assign version -# -# handles the following cases: -# -# 0. no tags on the repository. Print "dev". -# -# 1. no local modifications and commit is directly tagged. Print tag. -# -# 2. no local modifications and commit is not tagged. Take greatest version tag in repo X.Y.Z and assign X.Y.(Z+1). Print that + $devsuffix + $timestamp. -# -# 3. local modifications. Print "dev". - -tags=$(git tag) -if [[ -z "$tags" ]]; then - echo "dev" -elif `git diff --quiet 2>/dev/null`; then - tagged=$(git tag --points-at "$commit") - if [[ -n "$tagged" ]] ; then - echo $tagged - else - nearest_tag=$(git describe --tags --abbrev=0 --match "$versionglob" "$commit") - v=$(echo $nearest_tag | perl -pe 's/(\d+)$/$1+1/e') - isodate=$(TZ=UTC git log -n1 --format=%cd --date=iso "$commit") - ts=$(TZ=UTC date --date="$isodate" "+%Y%m%d%H%M%S") - echo "${v}${devsuffix}${ts}" - fi -else - echo "dev" -fi