1
0
mirror of https://github.com/juanfont/headscale.git synced 2025-08-14 13:51:01 +02:00

noise: make func, get by node

this commit splits the additional validation into a
separate function so it can be reused if we add more
endpoints in the future.

It swaps the check, so we still look up by NodeKey, but before
accepting the connection, we validate the known machinekey from
the db against the noise connection.

The reason for this is that when a node logs in or out, the node key
is replaced and it will no longer be possible to look it up, breaking
reauthentication.

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
Kristoffer Dalby 2025-06-06 08:35:28 +02:00
parent fe97600c88
commit e03ec310ed
No known key found for this signature in database

View File

@ -209,20 +209,9 @@ func (ns *noiseServer) NoisePollNetMapHandler(
return
}
node, err := ns.headscale.db.GetNodeByMachineKey(ns.machineKey)
node, err := ns.getAndValidateNode(mapRequest)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
httpError(writer, NewHTTPError(http.StatusNotFound, "node not found", nil))
return
}
httpError(writer, err)
return
}
// Ensure the NodeKey in the request matches the one associated with the machine key from the Noise session
if node.NodeKey != mapRequest.NodeKey {
httpError(writer, NewHTTPError(http.StatusNotFound, "node key in request does not match the one associated with this machine key", nil))
return
}
@ -273,7 +262,6 @@ func (ns *noiseServer) NoiseRegistrationHandler(
Error: httpErr.Msg,
}
return &regReq, resp
} else {
}
return &regReq, regErr(err)
@ -297,3 +285,22 @@ func (ns *noiseServer) NoiseRegistrationHandler(
writer.WriteHeader(http.StatusOK)
writer.Write(respBody)
}
// getAndValidateNode retrieves the node from the database using the NodeKey
// and validates that it matches the MachineKey from the Noise session.
func (ns *noiseServer) getAndValidateNode(mapRequest tailcfg.MapRequest) (*types.Node, error) {
node, err := ns.headscale.db.GetNodeByNodeKey(mapRequest.NodeKey)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, NewHTTPError(http.StatusNotFound, "node not found", nil)
}
return nil, err
}
// Validate that the MachineKey in the Noise session matches the one associated with the NodeKey.
if ns.machineKey != node.MachineKey {
return nil, NewHTTPError(http.StatusNotFound, "node key in request does not match the one associated with this machine key", nil)
}
return node, nil
}