2022-08-14 21:15:58 +02:00
|
|
|
package headscale
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/binary"
|
|
|
|
"encoding/json"
|
|
|
|
|
|
|
|
"github.com/klauspost/compress/zstd"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
"tailscale.com/tailcfg"
|
|
|
|
"tailscale.com/types/key"
|
|
|
|
)
|
|
|
|
|
2022-08-14 22:50:39 +02:00
|
|
|
func (h *Headscale) getMapResponseData(
|
|
|
|
mapRequest tailcfg.MapRequest,
|
|
|
|
machine *Machine,
|
|
|
|
isNoise bool,
|
|
|
|
) ([]byte, error) {
|
|
|
|
mapResponse, err := h.generateMapResponse(mapRequest, machine)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if isNoise {
|
2022-08-19 14:19:29 +02:00
|
|
|
return h.marshalMapResponse(mapResponse, key.MachinePublic{}, mapRequest.Compress)
|
2022-08-14 22:50:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
var machineKey key.MachinePublic
|
|
|
|
err = machineKey.UnmarshalText([]byte(MachinePublicKeyEnsurePrefix(machine.MachineKey)))
|
|
|
|
if err != nil {
|
|
|
|
log.Error().
|
|
|
|
Caller().
|
|
|
|
Err(err).
|
|
|
|
Msg("Cannot parse client key")
|
|
|
|
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-08-19 14:19:29 +02:00
|
|
|
return h.marshalMapResponse(mapResponse, machineKey, mapRequest.Compress)
|
2022-08-14 22:50:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (h *Headscale) getMapKeepAliveResponseData(
|
2022-08-14 21:15:58 +02:00
|
|
|
mapRequest tailcfg.MapRequest,
|
2022-08-14 22:50:39 +02:00
|
|
|
machine *Machine,
|
|
|
|
isNoise bool,
|
2022-08-14 21:15:58 +02:00
|
|
|
) ([]byte, error) {
|
2022-08-14 22:50:39 +02:00
|
|
|
keepAliveResponse := tailcfg.MapResponse{
|
2022-08-14 21:15:58 +02:00
|
|
|
KeepAlive: true,
|
|
|
|
}
|
2022-08-14 22:50:39 +02:00
|
|
|
|
|
|
|
if isNoise {
|
2022-08-19 14:19:29 +02:00
|
|
|
return h.marshalMapResponse(keepAliveResponse, key.MachinePublic{}, mapRequest.Compress)
|
2022-08-14 22:50:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
var machineKey key.MachinePublic
|
|
|
|
err := machineKey.UnmarshalText([]byte(MachinePublicKeyEnsurePrefix(machine.MachineKey)))
|
|
|
|
if err != nil {
|
|
|
|
log.Error().
|
|
|
|
Caller().
|
|
|
|
Err(err).
|
|
|
|
Msg("Cannot parse client key")
|
|
|
|
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-08-19 14:19:29 +02:00
|
|
|
return h.marshalMapResponse(keepAliveResponse, machineKey, mapRequest.Compress)
|
2022-08-14 22:50:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (h *Headscale) marshalResponse(
|
|
|
|
resp interface{},
|
|
|
|
machineKey key.MachinePublic,
|
2022-08-19 14:19:29 +02:00
|
|
|
) ([]byte, error) {
|
|
|
|
jsonBody, err := json.Marshal(resp)
|
|
|
|
if err != nil {
|
|
|
|
log.Error().
|
|
|
|
Caller().
|
|
|
|
Err(err).
|
|
|
|
Msg("Cannot marshal response")
|
|
|
|
}
|
|
|
|
|
|
|
|
if machineKey.IsZero() { // if Noise
|
|
|
|
return jsonBody, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return h.privateKey.SealTo(machineKey, jsonBody), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *Headscale) marshalMapResponse(
|
|
|
|
resp interface{},
|
|
|
|
machineKey key.MachinePublic,
|
|
|
|
compression string,
|
2022-08-14 22:50:39 +02:00
|
|
|
) ([]byte, error) {
|
|
|
|
jsonBody, err := json.Marshal(resp)
|
|
|
|
if err != nil {
|
|
|
|
log.Error().
|
|
|
|
Caller().
|
|
|
|
Err(err).
|
|
|
|
Msg("Cannot marshal map response")
|
|
|
|
}
|
|
|
|
|
2022-08-14 21:15:58 +02:00
|
|
|
var respBody []byte
|
2022-08-14 22:50:39 +02:00
|
|
|
if compression == ZstdCompression {
|
2022-08-14 21:15:58 +02:00
|
|
|
encoder, _ := zstd.NewWriter(nil)
|
2022-08-14 22:50:39 +02:00
|
|
|
respBody = encoder.EncodeAll(jsonBody, nil)
|
|
|
|
if !machineKey.IsZero() { // if legacy protocol
|
|
|
|
respBody = h.privateKey.SealTo(machineKey, respBody)
|
|
|
|
}
|
2022-08-14 21:15:58 +02:00
|
|
|
} else {
|
2022-08-14 22:50:39 +02:00
|
|
|
if !machineKey.IsZero() { // if legacy protocol
|
|
|
|
respBody = h.privateKey.SealTo(machineKey, jsonBody)
|
2022-08-14 23:15:41 +02:00
|
|
|
} else {
|
|
|
|
respBody = jsonBody
|
2022-08-14 21:15:58 +02:00
|
|
|
}
|
|
|
|
}
|
2022-08-14 22:50:39 +02:00
|
|
|
|
2022-08-14 21:15:58 +02:00
|
|
|
data := make([]byte, reservedResponseHeaderSize)
|
|
|
|
binary.LittleEndian.PutUint32(data, uint32(len(respBody)))
|
|
|
|
data = append(data, respBody...)
|
|
|
|
|
|
|
|
return data, nil
|
|
|
|
}
|