Add support for multiple IP prefixes
This commit is contained in:
parent
3a3aecb774
commit
1a6e5d8770
18 changed files with 423 additions and 257 deletions
81
machine.go
81
machine.go
|
@ -1,6 +1,7 @@
|
|||
package headscale
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -23,6 +24,7 @@ const (
|
|||
errMachineNotFound = Error("machine not found")
|
||||
errMachineAlreadyRegistered = Error("machine already registered")
|
||||
errMachineRouteIsNotAvailable = Error("route is not available on machine")
|
||||
errMachineAddressesInvalid = Error("failed to parse machine addresses")
|
||||
)
|
||||
|
||||
// Machine is a Headscale client.
|
||||
|
@ -31,7 +33,7 @@ type Machine struct {
|
|||
MachineKey string `gorm:"type:varchar(64);unique_index"`
|
||||
NodeKey string
|
||||
DiscoKey string
|
||||
IPAddress string
|
||||
IPAddresses MachineAddresses
|
||||
Name string
|
||||
NamespaceID uint
|
||||
Namespace Namespace `gorm:"foreignKey:NamespaceID"`
|
||||
|
@ -64,6 +66,47 @@ func (machine Machine) isRegistered() bool {
|
|||
return machine.Registered
|
||||
}
|
||||
|
||||
type MachineAddresses []netaddr.IP
|
||||
|
||||
func (ma MachineAddresses) ToStringSlice() []string {
|
||||
strSlice := make([]string, 0, len(ma))
|
||||
for _, addr := range ma {
|
||||
strSlice = append(strSlice, addr.String())
|
||||
}
|
||||
|
||||
return strSlice
|
||||
}
|
||||
|
||||
func (ma *MachineAddresses) Scan(destination interface{}) error {
|
||||
switch value := destination.(type) {
|
||||
case string:
|
||||
addresses := strings.Split(value, ",")
|
||||
*ma = (*ma)[:0]
|
||||
for _, addr := range addresses {
|
||||
if len(addr) < 1 {
|
||||
continue
|
||||
}
|
||||
parsed, err := netaddr.ParseIP(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*ma = append(*ma, parsed)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
default:
|
||||
return fmt.Errorf("%w: unexpected data type %T", errMachineAddressesInvalid, destination)
|
||||
}
|
||||
}
|
||||
|
||||
// Value return json value, implement driver.Valuer interface.
|
||||
func (ma MachineAddresses) Value() (driver.Value, error) {
|
||||
addresses := strings.Join(ma.ToStringSlice(), ",")
|
||||
|
||||
return addresses, nil
|
||||
}
|
||||
|
||||
// isExpired returns whether the machine registration has expired.
|
||||
func (machine Machine) isExpired() bool {
|
||||
// If Expiry is not set, the client has not indicated that
|
||||
|
@ -470,22 +513,12 @@ func (machine Machine) toNode(
|
|||
}
|
||||
|
||||
addrs := []netaddr.IPPrefix{}
|
||||
nodeAddr, err := netaddr.ParseIP(m.IPAddresses)
|
||||
if err != nil {
|
||||
log.Trace().
|
||||
Caller().
|
||||
Str("ip", machine.IPAddresses).
|
||||
Msgf("Failed to parse machine IP: %s", machine.IPAddresses)
|
||||
return nil, err
|
||||
for _, machineAddress := range machine.IPAddresses {
|
||||
ip := netaddr.IPPrefixFrom(machineAddress, machineAddress.BitLen())
|
||||
addrs = append(addrs, ip)
|
||||
}
|
||||
ip := netaddr.IPPrefixFrom(nodeAddr, nodeAddr.BitLen())
|
||||
addrs = append(addrs, ip)
|
||||
|
||||
allowedIPs := []netaddr.IPPrefix{}
|
||||
allowedIPs = append(
|
||||
allowedIPs,
|
||||
ip,
|
||||
) // we append the node own IP, as it is required by the clients
|
||||
allowedIPs := append([]netaddr.IPPrefix{}, addrs...) // we append the node own IP, as it is required by the clients
|
||||
|
||||
if includeRoutes {
|
||||
routesStr := []string{}
|
||||
|
@ -592,11 +625,11 @@ func (machine *Machine) toProto() *v1.Machine {
|
|||
Id: machine.ID,
|
||||
MachineKey: machine.MachineKey,
|
||||
|
||||
NodeKey: machine.NodeKey,
|
||||
DiscoKey: machine.DiscoKey,
|
||||
IpAddress: machine.IPAddress,
|
||||
Name: machine.Name,
|
||||
Namespace: machine.Namespace.toProto(),
|
||||
NodeKey: machine.NodeKey,
|
||||
DiscoKey: machine.DiscoKey,
|
||||
IpAddresses: machine.IPAddresses.ToStringSlice(),
|
||||
Name: machine.Name,
|
||||
Namespace: machine.Namespace.toProto(),
|
||||
|
||||
Registered: machine.Registered,
|
||||
|
||||
|
@ -695,7 +728,7 @@ func (h *Headscale) RegisterMachine(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
ip, err := h.getAvailableIP()
|
||||
ips, err := h.getAvailableIPs()
|
||||
if err != nil {
|
||||
log.Error().
|
||||
Caller().
|
||||
|
@ -709,10 +742,10 @@ func (h *Headscale) RegisterMachine(
|
|||
log.Trace().
|
||||
Caller().
|
||||
Str("machine", machine.Name).
|
||||
Str("ip", ip.String()).
|
||||
Str("ip", strings.Join(ips.ToStringSlice(), ",")).
|
||||
Msg("Found IP for host")
|
||||
|
||||
machine.IPAddress = ip.String()
|
||||
machine.IPAddresses = ips
|
||||
machine.NamespaceID = namespace.ID
|
||||
machine.Registered = true
|
||||
machine.RegisterMethod = RegisterMethodCLI
|
||||
|
@ -722,7 +755,7 @@ func (h *Headscale) RegisterMachine(
|
|||
log.Trace().
|
||||
Caller().
|
||||
Str("machine", machine.Name).
|
||||
Str("ip", ip.String()).
|
||||
Str("ip", strings.Join(ips.ToStringSlice(), ",")).
|
||||
Msg("Machine registered with the database")
|
||||
|
||||
return machine, nil
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue