Update code to Tailscale 1.10

This commit is contained in:
Juan Font Alonso 2021-06-25 18:57:08 +02:00
parent 736182f651
commit aa27709e60
6 changed files with 30 additions and 32 deletions

27
api.go
View file

@ -16,7 +16,7 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
"inet.af/netaddr" "inet.af/netaddr"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/wgengine/wgcfg" "tailscale.com/types/wgkey"
) )
// KeyHandler provides the Headscale pub key // KeyHandler provides the Headscale pub key
@ -61,7 +61,7 @@ func (h *Headscale) RegisterWebAPI(c *gin.Context) {
func (h *Headscale) RegistrationHandler(c *gin.Context) { func (h *Headscale) RegistrationHandler(c *gin.Context) {
body, _ := io.ReadAll(c.Request.Body) body, _ := io.ReadAll(c.Request.Body)
mKeyStr := c.Param("id") mKeyStr := c.Param("id")
mKey, err := wgcfg.ParseHexKey(mKeyStr) mKey, err := wgkey.ParseHex(mKeyStr)
if err != nil { if err != nil {
log.Printf("Cannot parse machine key: %s", err) log.Printf("Cannot parse machine key: %s", err)
c.String(http.StatusInternalServerError, "Sad!") c.String(http.StatusInternalServerError, "Sad!")
@ -89,7 +89,7 @@ func (h *Headscale) RegistrationHandler(c *gin.Context) {
Expiry: &req.Expiry, Expiry: &req.Expiry,
MachineKey: mKey.HexString(), MachineKey: mKey.HexString(),
Name: req.Hostinfo.Hostname, Name: req.Hostinfo.Hostname,
NodeKey: wgcfg.Key(req.NodeKey).HexString(), NodeKey: wgkey.Key(req.NodeKey).HexString(),
} }
if err := db.Create(&m).Error; err != nil { if err := db.Create(&m).Error; err != nil {
log.Printf("Could not create row: %s", err) log.Printf("Could not create row: %s", err)
@ -105,7 +105,7 @@ func (h *Headscale) RegistrationHandler(c *gin.Context) {
resp := tailcfg.RegisterResponse{} resp := tailcfg.RegisterResponse{}
// We have the updated key! // We have the updated key!
if m.NodeKey == wgcfg.Key(req.NodeKey).HexString() { if m.NodeKey == wgkey.Key(req.NodeKey).HexString() {
if m.Registered { if m.Registered {
log.Printf("[%s] Client is registered and we have the current NodeKey. All clear to /map", m.Name) log.Printf("[%s] Client is registered and we have the current NodeKey. All clear to /map", m.Name)
resp.AuthURL = "" resp.AuthURL = ""
@ -135,9 +135,9 @@ func (h *Headscale) RegistrationHandler(c *gin.Context) {
} }
// The NodeKey we have matches OldNodeKey, which means this is a refresh after an key expiration // The NodeKey we have matches OldNodeKey, which means this is a refresh after an key expiration
if m.NodeKey == wgcfg.Key(req.OldNodeKey).HexString() { if m.NodeKey == wgkey.Key(req.OldNodeKey).HexString() {
log.Printf("[%s] We have the OldNodeKey in the database. This is a key refresh", m.Name) log.Printf("[%s] We have the OldNodeKey in the database. This is a key refresh", m.Name)
m.NodeKey = wgcfg.Key(req.NodeKey).HexString() m.NodeKey = wgkey.Key(req.NodeKey).HexString()
db.Save(&m) db.Save(&m)
resp.AuthURL = "" resp.AuthURL = ""
@ -192,7 +192,7 @@ func (h *Headscale) RegistrationHandler(c *gin.Context) {
func (h *Headscale) PollNetMapHandler(c *gin.Context) { func (h *Headscale) PollNetMapHandler(c *gin.Context) {
body, _ := io.ReadAll(c.Request.Body) body, _ := io.ReadAll(c.Request.Body)
mKeyStr := c.Param("id") mKeyStr := c.Param("id")
mKey, err := wgcfg.ParseHexKey(mKeyStr) mKey, err := wgkey.ParseHex(mKeyStr)
if err != nil { if err != nil {
log.Printf("Cannot parse client key: %s", err) log.Printf("Cannot parse client key: %s", err)
return return
@ -218,7 +218,7 @@ func (h *Headscale) PollNetMapHandler(c *gin.Context) {
hostinfo, _ := json.Marshal(req.Hostinfo) hostinfo, _ := json.Marshal(req.Hostinfo)
m.Name = req.Hostinfo.Hostname m.Name = req.Hostinfo.Hostname
m.HostInfo = datatypes.JSON(hostinfo) m.HostInfo = datatypes.JSON(hostinfo)
m.DiscoKey = wgcfg.Key(req.DiscoKey).HexString() m.DiscoKey = wgkey.Key(req.DiscoKey).HexString()
now := time.Now().UTC() now := time.Now().UTC()
// From Tailscale client: // From Tailscale client:
@ -334,7 +334,7 @@ func (h *Headscale) PollNetMapHandler(c *gin.Context) {
}) })
} }
func (h *Headscale) keepAlive(cancel chan []byte, pollData chan []byte, mKey wgcfg.Key, req tailcfg.MapRequest, m Machine) { func (h *Headscale) keepAlive(cancel chan []byte, pollData chan []byte, mKey wgkey.Key, req tailcfg.MapRequest, m Machine) {
for { for {
select { select {
case <-cancel: case <-cancel:
@ -355,7 +355,7 @@ func (h *Headscale) keepAlive(cancel chan []byte, pollData chan []byte, mKey wgc
} }
} }
func (h *Headscale) getMapResponse(mKey wgcfg.Key, req tailcfg.MapRequest, m Machine) (*[]byte, error) { func (h *Headscale) getMapResponse(mKey wgkey.Key, req tailcfg.MapRequest, m Machine) (*[]byte, error) {
node, err := m.toNode() node, err := m.toNode()
if err != nil { if err != nil {
log.Printf("Cannot convert to node: %s", err) log.Printf("Cannot convert to node: %s", err)
@ -376,7 +376,6 @@ func (h *Headscale) getMapResponse(mKey wgcfg.Key, req tailcfg.MapRequest, m Mac
PacketFilter: tailcfg.FilterAllowAll, PacketFilter: tailcfg.FilterAllowAll,
DERPMap: h.cfg.DerpMap, DERPMap: h.cfg.DerpMap,
UserProfiles: []tailcfg.UserProfile{}, UserProfiles: []tailcfg.UserProfile{},
Roles: []tailcfg.Role{},
} }
var respBody []byte var respBody []byte
@ -402,7 +401,7 @@ func (h *Headscale) getMapResponse(mKey wgcfg.Key, req tailcfg.MapRequest, m Mac
return &data, nil return &data, nil
} }
func (h *Headscale) getMapKeepAliveResponse(mKey wgcfg.Key, req tailcfg.MapRequest, m Machine) (*[]byte, error) { func (h *Headscale) getMapKeepAliveResponse(mKey wgkey.Key, req tailcfg.MapRequest, m Machine) (*[]byte, error) {
resp := tailcfg.MapResponse{ resp := tailcfg.MapResponse{
KeepAlive: true, KeepAlive: true,
} }
@ -428,7 +427,7 @@ func (h *Headscale) getMapKeepAliveResponse(mKey wgcfg.Key, req tailcfg.MapReque
return &data, nil return &data, nil
} }
func (h *Headscale) handleAuthKey(c *gin.Context, db *gorm.DB, idKey wgcfg.Key, req tailcfg.RegisterRequest, m Machine) { func (h *Headscale) handleAuthKey(c *gin.Context, db *gorm.DB, idKey wgkey.Key, req tailcfg.RegisterRequest, m Machine) {
resp := tailcfg.RegisterResponse{} resp := tailcfg.RegisterResponse{}
pak, err := h.checkKeyValidity(req.Auth.AuthKey) pak, err := h.checkKeyValidity(req.Auth.AuthKey)
if err != nil { if err != nil {
@ -452,7 +451,7 @@ func (h *Headscale) handleAuthKey(c *gin.Context, db *gorm.DB, idKey wgcfg.Key,
m.AuthKeyID = uint(pak.ID) m.AuthKeyID = uint(pak.ID)
m.IPAddress = ip.String() m.IPAddress = ip.String()
m.NamespaceID = pak.NamespaceID m.NamespaceID = pak.NamespaceID
m.NodeKey = wgcfg.Key(req.NodeKey).HexString() // we update it just in case m.NodeKey = wgkey.Key(req.NodeKey).HexString() // we update it just in case
m.Registered = true m.Registered = true
m.RegisterMethod = "authKey" m.RegisterMethod = "authKey"
db.Save(&m) db.Save(&m)

8
app.go
View file

@ -13,7 +13,7 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"golang.org/x/crypto/acme/autocert" "golang.org/x/crypto/acme/autocert"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/wgengine/wgcfg" "tailscale.com/types/wgkey"
) )
// Config contains the initial Headscale configuration // Config contains the initial Headscale configuration
@ -46,8 +46,8 @@ type Headscale struct {
dbString string dbString string
dbType string dbType string
dbDebug bool dbDebug bool
publicKey *wgcfg.Key publicKey *wgkey.Key
privateKey *wgcfg.PrivateKey privateKey *wgkey.Private
pollMu sync.Mutex pollMu sync.Mutex
clientsPolling map[uint64]chan []byte // this is by all means a hackity hack clientsPolling map[uint64]chan []byte // this is by all means a hackity hack
@ -59,7 +59,7 @@ func NewHeadscale(cfg Config) (*Headscale, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
privKey, err := wgcfg.ParsePrivateKey(string(content)) privKey, err := wgkey.ParsePrivate(string(content))
if err != nil { if err != nil {
return nil, err return nil, err
} }

4
cli.go
View file

@ -5,7 +5,7 @@ import (
"log" "log"
"gorm.io/gorm" "gorm.io/gorm"
"tailscale.com/wgengine/wgcfg" "tailscale.com/types/wgkey"
) )
// RegisterMachine is executed from the CLI to register a new Machine using its MachineKey // RegisterMachine is executed from the CLI to register a new Machine using its MachineKey
@ -14,7 +14,7 @@ func (h *Headscale) RegisterMachine(key string, namespace string) (*Machine, err
if err != nil { if err != nil {
return nil, err return nil, err
} }
mKey, err := wgcfg.ParseHexKey(key) mKey, err := wgkey.ParseHex(key)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -11,7 +11,7 @@ import (
"gorm.io/datatypes" "gorm.io/datatypes"
"inet.af/netaddr" "inet.af/netaddr"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/wgengine/wgcfg" "tailscale.com/types/wgkey"
) )
// Machine is a Headscale client // Machine is a Headscale client
@ -23,7 +23,7 @@ type Machine struct {
IPAddress string IPAddress string
Name string Name string
NamespaceID uint NamespaceID uint
Namespace Namespace Namespace Namespace `gorm:"foreignKey:NamespaceID"`
Registered bool // temp Registered bool // temp
RegisterMethod string RegisterMethod string
@ -48,18 +48,18 @@ func (m Machine) isAlreadyRegistered() bool {
} }
func (m Machine) toNode() (*tailcfg.Node, error) { func (m Machine) toNode() (*tailcfg.Node, error) {
nKey, err := wgcfg.ParseHexKey(m.NodeKey) nKey, err := wgkey.ParseHex(m.NodeKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
mKey, err := wgcfg.ParseHexKey(m.MachineKey) mKey, err := wgkey.ParseHex(m.MachineKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var discoKey tailcfg.DiscoKey var discoKey tailcfg.DiscoKey
if m.DiscoKey != "" { if m.DiscoKey != "" {
dKey, err := wgcfg.ParseHexKey(m.DiscoKey) dKey, err := wgkey.ParseHex(m.DiscoKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -144,7 +144,6 @@ func (n *Namespace) toUser() *tailcfg.User {
ProfilePicURL: "", ProfilePicURL: "",
Domain: "", Domain: "",
Logins: []tailcfg.LoginID{}, Logins: []tailcfg.LoginID{},
Roles: []tailcfg.RoleID{},
Created: time.Time{}, Created: time.Time{},
} }
return &u return &u

View file

@ -19,7 +19,7 @@ import (
"golang.org/x/crypto/nacl/box" "golang.org/x/crypto/nacl/box"
"gorm.io/gorm" "gorm.io/gorm"
"tailscale.com/wgengine/wgcfg" "tailscale.com/types/wgkey"
) )
// Error is used to compare errors as per https://dave.cheney.net/2016/04/07/constant-errors // Error is used to compare errors as per https://dave.cheney.net/2016/04/07/constant-errors
@ -27,11 +27,11 @@ type Error string
func (e Error) Error() string { return string(e) } func (e Error) Error() string { return string(e) }
func decode(msg []byte, v interface{}, pubKey *wgcfg.Key, privKey *wgcfg.PrivateKey) error { func decode(msg []byte, v interface{}, pubKey *wgkey.Key, privKey *wgkey.Private) error {
return decodeMsg(msg, v, pubKey, privKey) return decodeMsg(msg, v, pubKey, privKey)
} }
func decodeMsg(msg []byte, v interface{}, pubKey *wgcfg.Key, privKey *wgcfg.PrivateKey) error { func decodeMsg(msg []byte, v interface{}, pubKey *wgkey.Key, privKey *wgkey.Private) error {
decrypted, err := decryptMsg(msg, pubKey, privKey) decrypted, err := decryptMsg(msg, pubKey, privKey)
if err != nil { if err != nil {
return err return err
@ -43,7 +43,7 @@ func decodeMsg(msg []byte, v interface{}, pubKey *wgcfg.Key, privKey *wgcfg.Priv
return nil return nil
} }
func decryptMsg(msg []byte, pubKey *wgcfg.Key, privKey *wgcfg.PrivateKey) ([]byte, error) { func decryptMsg(msg []byte, pubKey *wgkey.Key, privKey *wgkey.Private) ([]byte, error) {
var nonce [24]byte var nonce [24]byte
if len(msg) < len(nonce)+1 { if len(msg) < len(nonce)+1 {
return nil, fmt.Errorf("response missing nonce, len=%d", len(msg)) return nil, fmt.Errorf("response missing nonce, len=%d", len(msg))
@ -59,7 +59,7 @@ func decryptMsg(msg []byte, pubKey *wgcfg.Key, privKey *wgcfg.PrivateKey) ([]byt
return decrypted, nil return decrypted, nil
} }
func encode(v interface{}, pubKey *wgcfg.Key, privKey *wgcfg.PrivateKey) ([]byte, error) { func encode(v interface{}, pubKey *wgkey.Key, privKey *wgkey.Private) ([]byte, error) {
b, err := json.Marshal(v) b, err := json.Marshal(v)
if err != nil { if err != nil {
return nil, err return nil, err
@ -67,7 +67,7 @@ func encode(v interface{}, pubKey *wgcfg.Key, privKey *wgcfg.PrivateKey) ([]byte
return encodeMsg(b, pubKey, privKey) return encodeMsg(b, pubKey, privKey)
} }
func encodeMsg(b []byte, pubKey *wgcfg.Key, privKey *wgcfg.PrivateKey) ([]byte, error) { func encodeMsg(b []byte, pubKey *wgkey.Key, privKey *wgkey.Private) ([]byte, error) {
var nonce [24]byte var nonce [24]byte
if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil { if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
panic(err) panic(err)