mirror of
https://github.com/juanfont/headscale.git
synced 2026-01-14 21:23:37 +01:00
Compare commits
34 Commits
v0.12.0-be
...
v0.12.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5192841016 | ||
|
|
07384fd2bb | ||
|
|
a795e7c0c9 | ||
|
|
ebfbd4a37d | ||
|
|
fb933b7d41 | ||
|
|
1c7cb98042 | ||
|
|
fb634cdfc2 | ||
|
|
f60f62792a | ||
|
|
418fde2731 | ||
|
|
53108207be | ||
|
|
3fb3db6f20 | ||
|
|
5a504fa711 | ||
|
|
b4cce22415 | ||
|
|
54c2306637 | ||
|
|
bc8f5f484d | ||
|
|
686384ebb7 | ||
|
|
3a85c4d367 | ||
|
|
5a7f669505 | ||
|
|
0c13d9da15 | ||
|
|
58ec26ee89 | ||
|
|
969bcf17c4 | ||
|
|
04d81a0e5c | ||
|
|
a6e99525ac | ||
|
|
7e95b3501d | ||
|
|
3435d95c80 | ||
|
|
acaab7a3de | ||
|
|
74ba452025 | ||
|
|
500be2de58 | ||
|
|
78eba97bf9 | ||
|
|
6350d528a7 | ||
|
|
42eb6b9e01 | ||
|
|
2e2fb68715 | ||
|
|
6fc6355d66 | ||
|
|
48fc93bbdc |
28
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
28
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
name: "Bug report"
|
||||
about: "Create a bug report to help us improve"
|
||||
title: ""
|
||||
labels: ["bug"]
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Bug description**
|
||||
|
||||
<!-- A clear and concise description of what the bug is. Describe the expected bahavior
|
||||
and how it is currently different. If you are unsure if it is a bug, consider discussing
|
||||
it on our Discord server first. -->
|
||||
|
||||
**To Reproduce**
|
||||
|
||||
<!-- Steps to reproduce the behavior. -->
|
||||
|
||||
**Context info**
|
||||
|
||||
<!-- Please add relevant information about your system. For example:
|
||||
- Version of headscale used
|
||||
- Version of tailscale client
|
||||
- OS (e.g. Linux, Mac, Cygwin, WSL, etc.) and version
|
||||
- Kernel version
|
||||
- The relevant config parameters you used
|
||||
- Log output
|
||||
-->
|
||||
11
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
11
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# Issues must have some content
|
||||
blank_issues_enabled: false
|
||||
|
||||
# Contact links
|
||||
contact_links:
|
||||
- name: "headscale usage documentation"
|
||||
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"
|
||||
about: "Please ask and answer questions about usage of headscale here."
|
||||
15
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
15
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: "Feature request"
|
||||
about: "Suggest an idea for headscale"
|
||||
title: ""
|
||||
labels: ["enhancement"]
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Feature request**
|
||||
|
||||
<!-- A clear and precise description of what new or changed feature you want. -->
|
||||
|
||||
<!-- Please include the reason, why you would need the feature. E.g. what problem
|
||||
does it solve? Or which workflow is currently frustrating and will be improved by
|
||||
this? -->
|
||||
28
.github/ISSUE_TEMPLATE/other_issue.md
vendored
Normal file
28
.github/ISSUE_TEMPLATE/other_issue.md
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
name: "Other issue"
|
||||
about: "Report a different issue"
|
||||
title: ""
|
||||
labels: ["bug"]
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
<!-- If you have a question, please consider using our Discord for asking questions -->
|
||||
|
||||
**Issue description**
|
||||
|
||||
<!-- Please add your issue description. -->
|
||||
|
||||
**To Reproduce**
|
||||
|
||||
<!-- Steps to reproduce the behavior. -->
|
||||
|
||||
**Context info**
|
||||
|
||||
<!-- Please add relevant information about your system. For example:
|
||||
- Version of headscale used
|
||||
- Version of tailscale client
|
||||
- OS (e.g. Linux, Mac, Cygwin, WSL, etc.) and version
|
||||
- Kernel version
|
||||
- The relevant config parameters you used
|
||||
- Log output
|
||||
-->
|
||||
10
.github/pull_request_template.md
vendored
Normal file
10
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<!-- Please tick if the following things apply. You… -->
|
||||
|
||||
- [] read the [CONTRIBUTING guidelines](README.md#user-content-contributing)
|
||||
- [] raised a GitHub issue or discussed it on the projects chat beforehand
|
||||
- [] added unit tests
|
||||
- [] added integration tests
|
||||
- [] updated documentation if needed
|
||||
- [] updated CHANGELOG.md
|
||||
|
||||
<!-- If applicable, please reference the issue using `Fixes #XXX` and add tests to cover your new code. -->
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -17,6 +17,8 @@
|
||||
/headscale
|
||||
config.json
|
||||
config.yaml
|
||||
derp.yaml
|
||||
*.hujson
|
||||
*.key
|
||||
/db.sqlite
|
||||
*.sqlite3
|
||||
|
||||
32
CHANGELOG.md
Normal file
32
CHANGELOG.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# CHANGELOG
|
||||
|
||||
**TBD (TBD):**
|
||||
|
||||
**0.12.1 (2021-12-24):**
|
||||
|
||||
(We are skipping 0.12.0 to correct a mishap done weeks ago with the version tagging)
|
||||
|
||||
**BREAKING**:
|
||||
|
||||
- Upgrade to Tailscale 1.18 [#229](https://github.com/juanfont/headscale/pull/229)
|
||||
- This change requires a new format for private key, private keys are now generated automatically:
|
||||
1. Delete your current key
|
||||
2. Restart `headscale`, a new key will be generated.
|
||||
3. Restart all Tailscale clients to fetch the new key
|
||||
|
||||
**Changes**:
|
||||
|
||||
- Unify configuration example [#197](https://github.com/juanfont/headscale/pull/197)
|
||||
- Add stricter linting and formatting [#223](https://github.com/juanfont/headscale/pull/223)
|
||||
|
||||
**Features**:
|
||||
|
||||
- Add gRPC and HTTP API (HTTP API is currently disabled) [#204](https://github.com/juanfont/headscale/pull/204)
|
||||
- Use gRPC between the CLI and the server [#206](https://github.com/juanfont/headscale/pull/206), [#212](https://github.com/juanfont/headscale/pull/212)
|
||||
- Beta OpenID Connect support [#126](https://github.com/juanfont/headscale/pull/126), [#227](https://github.com/juanfont/headscale/pull/227)
|
||||
|
||||
**0.11.0 (2021-10-25):**
|
||||
|
||||
**BREAKING**:
|
||||
|
||||
- Make headscale fetch DERP map from URL and file [#196](https://github.com/juanfont/headscale/pull/196)
|
||||
@@ -57,7 +57,7 @@ Please have a look at the documentation under [`docs/`](docs/).
|
||||
## Disclaimer
|
||||
|
||||
1. We have nothing to do with Tailscale, or Tailscale Inc.
|
||||
2. The purpose of writing this was to learn how Tailscale works.
|
||||
2. The purpose of Headscale is maintaining a working, self-hosted Tailscale control panel.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
7
acls.go
7
acls.go
@@ -34,6 +34,11 @@ const (
|
||||
|
||||
// LoadACLPolicy loads the ACL policy from the specify path, and generates the ACL rules.
|
||||
func (h *Headscale) LoadACLPolicy(path string) error {
|
||||
log.Debug().
|
||||
Str("func", "LoadACLPolicy").
|
||||
Str("path", path).
|
||||
Msg("Loading ACL policy from path")
|
||||
|
||||
policyFile, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -67,6 +72,8 @@ func (h *Headscale) LoadACLPolicy(path string) error {
|
||||
}
|
||||
h.aclRules = rules
|
||||
|
||||
log.Trace().Interface("ACL", rules).Msg("ACL rules generated")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
56
api.go
56
api.go
@@ -1,10 +1,12 @@
|
||||
package headscale
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
@@ -38,6 +40,28 @@ func (h *Headscale) KeyHandler(ctx *gin.Context) {
|
||||
)
|
||||
}
|
||||
|
||||
type registerWebAPITemplateConfig struct {
|
||||
Key string
|
||||
}
|
||||
|
||||
var registerWebAPITemplate = template.Must(
|
||||
template.New("registerweb").Parse(`<html>
|
||||
<body>
|
||||
<h1>headscale</h1>
|
||||
<p>
|
||||
Run the command below in the headscale server to add this machine to your network:
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<code>
|
||||
<b>headscale -n NAMESPACE nodes register --key {{.Key}}</b>
|
||||
</code>
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>`),
|
||||
)
|
||||
|
||||
// RegisterWebAPI shows a simple message in the browser to point to the CLI
|
||||
// Listens in /register.
|
||||
func (h *Headscale) RegisterWebAPI(ctx *gin.Context) {
|
||||
@@ -48,24 +72,22 @@ func (h *Headscale) RegisterWebAPI(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data(http.StatusOK, "text/html; charset=utf-8", []byte(fmt.Sprintf(`
|
||||
<html>
|
||||
<body>
|
||||
<h1>headscale</h1>
|
||||
<p>
|
||||
Run the command below in the headscale server to add this machine to your network:
|
||||
</p>
|
||||
var content bytes.Buffer
|
||||
if err := registerWebAPITemplate.Execute(&content, registerWebAPITemplateConfig{
|
||||
Key: machineKeyStr,
|
||||
}); err != nil {
|
||||
log.Error().
|
||||
Str("func", "RegisterWebAPI").
|
||||
Err(err).
|
||||
Msg("Could not render register web API template")
|
||||
ctx.Data(
|
||||
http.StatusInternalServerError,
|
||||
"text/html; charset=utf-8",
|
||||
[]byte("Could not render register web API template"),
|
||||
)
|
||||
}
|
||||
|
||||
<p>
|
||||
<code>
|
||||
<b>headscale -n NAMESPACE nodes register --key %s</b>
|
||||
</code>
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
`, machineKeyStr)))
|
||||
ctx.Data(http.StatusOK, "text/html; charset=utf-8", content.Bytes())
|
||||
}
|
||||
|
||||
// RegistrationHandler handles the actual registration process of a machine
|
||||
|
||||
6
app.go
6
app.go
@@ -418,12 +418,12 @@ func (h *Headscale) Serve() error {
|
||||
|
||||
err = h.ensureUnixSocketIsAbsent()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return fmt.Errorf("unable to remove old socket file: %w", err)
|
||||
}
|
||||
|
||||
socketListener, err := net.Listen("unix", h.cfg.UnixSocket)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return fmt.Errorf("failed to set up gRPC socket: %w", err)
|
||||
}
|
||||
|
||||
// Handle common process-killing signals so we can gracefully shut down:
|
||||
@@ -441,7 +441,7 @@ func (h *Headscale) Serve() error {
|
||||
|
||||
networkListener, err := net.Listen("tcp", h.cfg.Addr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return fmt.Errorf("failed to bind to TCP address: %w", err)
|
||||
}
|
||||
|
||||
// Create the cmux object that will multiplex 2 protocols on the same port.
|
||||
|
||||
@@ -2,8 +2,8 @@ package headscale
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"text/template"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gofrs/uuid"
|
||||
|
||||
@@ -54,6 +54,8 @@ tls_letsencrypt_challenge_type: HTTP-01
|
||||
tls_cert_path: ""
|
||||
tls_key_path: ""
|
||||
|
||||
log_level: info
|
||||
|
||||
# Path to a file containg ACL policies.
|
||||
acl_policy_path: ""
|
||||
|
||||
|
||||
7
docs/README.md
Normal file
7
docs/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Official headscale documentation
|
||||
|
||||
- [Configuration](Configuration.md)
|
||||
- [Running](Running.md)
|
||||
- [DNS](DNS.md)
|
||||
- [TLS](TLS.md)
|
||||
- [Glossary](Glossary.md)
|
||||
72
oidc.go
72
oidc.go
@@ -1,11 +1,13 @@
|
||||
package headscale
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -108,6 +110,22 @@ func (h *Headscale) RegisterOIDC(ctx *gin.Context) {
|
||||
ctx.Redirect(http.StatusFound, authURL)
|
||||
}
|
||||
|
||||
type oidcCallbackTemplateConfig struct {
|
||||
User string
|
||||
Verb string
|
||||
}
|
||||
|
||||
var oidcCallbackTemplate = template.Must(
|
||||
template.New("oidccallback").Parse(`<html>
|
||||
<body>
|
||||
<h1>headscale</h1>
|
||||
<p>
|
||||
{{.Verb}} as {{.User}}, you can now close this window.
|
||||
</p>
|
||||
</body>
|
||||
</html>`),
|
||||
)
|
||||
|
||||
// OIDCCallback handles the callback from the OIDC endpoint
|
||||
// Retrieves the mkey from the state cache and adds the machine to the users email namespace
|
||||
// TODO: A confirmation page for new machines should be added to avoid phishing vulnerabilities
|
||||
@@ -239,17 +257,24 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) {
|
||||
|
||||
h.RefreshMachine(machine, requestedTime)
|
||||
|
||||
ctx.Data(http.StatusOK, "text/html; charset=utf-8", []byte(fmt.Sprintf(`
|
||||
<html>
|
||||
<body>
|
||||
<h1>headscale</h1>
|
||||
<p>
|
||||
Reuthenticated as %s, you can now close this window.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
var content bytes.Buffer
|
||||
if err := oidcCallbackTemplate.Execute(&content, oidcCallbackTemplateConfig{
|
||||
User: claims.Email,
|
||||
Verb: "Reauthenticated",
|
||||
}); err != nil {
|
||||
log.Error().
|
||||
Str("func", "OIDCCallback").
|
||||
Str("type", "reauthenticate").
|
||||
Err(err).
|
||||
Msg("Could not render OIDC callback template")
|
||||
ctx.Data(
|
||||
http.StatusInternalServerError,
|
||||
"text/html; charset=utf-8",
|
||||
[]byte("Could not render OIDC callback template"),
|
||||
)
|
||||
}
|
||||
|
||||
`, claims.Email)))
|
||||
ctx.Data(http.StatusOK, "text/html; charset=utf-8", content.Bytes())
|
||||
|
||||
return
|
||||
}
|
||||
@@ -314,17 +339,24 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) {
|
||||
h.db.Save(&machine)
|
||||
}
|
||||
|
||||
ctx.Data(http.StatusOK, "text/html; charset=utf-8", []byte(fmt.Sprintf(`
|
||||
<html>
|
||||
<body>
|
||||
<h1>headscale</h1>
|
||||
<p>
|
||||
Authenticated as %s, you can now close this window.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
var content bytes.Buffer
|
||||
if err := oidcCallbackTemplate.Execute(&content, oidcCallbackTemplateConfig{
|
||||
User: claims.Email,
|
||||
Verb: "Authenticated",
|
||||
}); err != nil {
|
||||
log.Error().
|
||||
Str("func", "OIDCCallback").
|
||||
Str("type", "authenticate").
|
||||
Err(err).
|
||||
Msg("Could not render OIDC callback template")
|
||||
ctx.Data(
|
||||
http.StatusInternalServerError,
|
||||
"text/html; charset=utf-8",
|
||||
[]byte("Could not render OIDC callback template"),
|
||||
)
|
||||
}
|
||||
|
||||
`, claims.Email)))
|
||||
ctx.Data(http.StatusOK, "text/html; charset=utf-8", content.Bytes())
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ package headscale
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"text/template"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
Reference in New Issue
Block a user