1
0
mirror of https://github.com/juanfont/headscale.git synced 2025-09-25 17:51:11 +02:00

[ASSIGN CUSTOM IP] register new machine with custom IPv4 address

This commit is contained in:
Bela Lemle 2023-07-25 14:49:33 +02:00
parent fb203a2e45
commit 5cdc6bfcbe
11 changed files with 101 additions and 4 deletions

View File

@ -30,7 +30,7 @@ func init() {
nodeCmd.AddCommand(listNodesCmd) nodeCmd.AddCommand(listNodesCmd)
registerNodeCmd.Flags().StringP("user", "u", "", "User") registerNodeCmd.Flags().StringP("user", "u", "", "User")
registerNodeCmd.Flags().StringP("ip", "p", "", "Ip")
registerNodeCmd.Flags().StringP("namespace", "n", "", "User") registerNodeCmd.Flags().StringP("namespace", "n", "", "User")
registerNodeNamespaceFlag := registerNodeCmd.Flags().Lookup("namespace") registerNodeNamespaceFlag := registerNodeCmd.Flags().Lookup("namespace")
registerNodeNamespaceFlag.Deprecated = deprecateNamespaceMessage registerNodeNamespaceFlag.Deprecated = deprecateNamespaceMessage
@ -132,9 +132,19 @@ var registerNodeCmd = &cobra.Command{
return return
} }
ip, err := cmd.Flags().GetString("ip")
if err != nil {
ErrorOutput(
err,
fmt.Sprintf("Error getting node ip from flag: %s", err),
output,
)
}
request := &v1.RegisterMachineRequest{ request := &v1.RegisterMachineRequest{
Key: machineKey, Key: machineKey,
User: user, User: user,
Ip: ip,
} }
response, err := client.RegisterMachine(ctx, request) response, err := client.RegisterMachine(ctx, request)

View File

@ -127,6 +127,12 @@ docker exec headscale \
headscale --user myfirstuser nodes register --key <YOU_+MACHINE_KEY> headscale --user myfirstuser nodes register --key <YOU_+MACHINE_KEY>
``` ```
Optionally use the --ip flag to assign a custom IPv4 address to your machine:
```shell
docker exec headscale \
headscale --user myfirstuser nodes register --ip <YOUR_CUSTOM_IP> --key <YOU_+MACHINE_KEY>
```
### Register machine using a pre authenticated key ### Register machine using a pre authenticated key
Generate a key using the command line: Generate a key using the command line:

View File

@ -102,6 +102,12 @@ Register the machine:
headscale --user myfirstuser nodes register --key <YOUR_MACHINE_KEY> headscale --user myfirstuser nodes register --key <YOUR_MACHINE_KEY>
``` ```
Optionally use the --ip flag to assign a custom IPv4 address to your machine:
```shell
headscale --user myfirstuser nodes register --ip <YOUR_CUSTOM_IP> --key <YOUR_MACHINE_KEY>
```
### Register machine using a pre authenticated key ### Register machine using a pre authenticated key
Generate a key using the command line: Generate a key using the command line:

View File

@ -79,6 +79,12 @@ Register the machine:
headscale --user myfirstuser nodes register --key <YOUR_MACHINE_KEY> headscale --user myfirstuser nodes register --key <YOUR_MACHINE_KEY>
``` ```
Optionally use the --ip flag to assign a custom IPv4 address to your machine:
```shell
headscale --user myfirstuser nodes register --ip <YOUR_CUSTOM_IP> --key <YOUR_MACHINE_KEY>
```
### Register machine using a pre authenticated key ### Register machine using a pre authenticated key
Generate a key using the command line: Generate a key using the command line:

View File

@ -139,6 +139,12 @@ Register the machine:
headscale --user myfirstuser nodes register --key <YOU_+MACHINE_KEY> headscale --user myfirstuser nodes register --key <YOU_+MACHINE_KEY>
``` ```
Optionally use the --ip flag to assign a custom IPv4 address to your machine:
```shell
headscale --user myfirstuser nodes register --ip <YOUR_CUSTOM_IP> --key <YOUR_MACHINE_KEY>
```
### Register machine using a pre authenticated key ### Register machine using a pre authenticated key
Generate a key using the command line: Generate a key using the command line:

View File

@ -368,6 +368,7 @@ func (h *Headscale) handleAuthKey(
machine, err = h.db.RegisterMachine( machine, err = h.db.RegisterMachine(
machineToRegister, machineToRegister,
"",
) )
if err != nil { if err != nil {
log.Error(). log.Error().

View File

@ -17,6 +17,24 @@ import (
var ErrCouldNotAllocateIP = errors.New("could not find any suitable IP") var ErrCouldNotAllocateIP = errors.New("could not find any suitable IP")
func (hsdb *HSDatabase) isInRange(address netip.Addr) (bool, error) {
counter := 0
for _, ipPrefix := range hsdb.ipPrefixes {
ipPrefixNetworkAddress, ipPrefixBroadcastAddress := util.GetIPPrefixEndpoints(ipPrefix)
if ipPrefixNetworkAddress.Compare(address) == -1 &&
ipPrefixBroadcastAddress.Compare(address) == 1 {
counter += 1
}
}
if counter > 0 {
return true, nil
}
return false, ErrRequestedIPNotInPrefixRange
}
func (hsdb *HSDatabase) getAvailableIPs() (types.MachineAddresses, error) { func (hsdb *HSDatabase) getAvailableIPs() (types.MachineAddresses, error) {
var ips types.MachineAddresses var ips types.MachineAddresses
var err error var err error

View File

@ -31,6 +31,7 @@ var (
ErrDifferentRegisteredUser = errors.New( ErrDifferentRegisteredUser = errors.New(
"machine was previously registered with a different user", "machine was previously registered with a different user",
) )
ErrRequestedIPNotInPrefixRange = errors.New("the ip you provided is not in the configured prefix range")
) )
// ListPeers returns all peers of machine, regardless of any Policy or if the node is expired. // ListPeers returns all peers of machine, regardless of any Policy or if the node is expired.
@ -355,6 +356,7 @@ func (hsdb *HSDatabase) RegisterMachineFromAuthCallback(
userName string, userName string,
machineExpiry *time.Time, machineExpiry *time.Time,
registrationMethod string, registrationMethod string,
requestedIP string,
) (*types.Machine, error) { ) (*types.Machine, error) {
nodeKey := key.NodePublic{} nodeKey := key.NodePublic{}
err := nodeKey.UnmarshalText([]byte(nodeKeyStr)) err := nodeKey.UnmarshalText([]byte(nodeKeyStr))
@ -365,6 +367,7 @@ func (hsdb *HSDatabase) RegisterMachineFromAuthCallback(
log.Debug(). log.Debug().
Str("nodeKey", nodeKey.ShortString()). Str("nodeKey", nodeKey.ShortString()).
Str("userName", userName). Str("userName", userName).
Str("requestedIp", requestedIP).
Str("registrationMethod", registrationMethod). Str("registrationMethod", registrationMethod).
Str("expiresAt", fmt.Sprintf("%v", machineExpiry)). Str("expiresAt", fmt.Sprintf("%v", machineExpiry)).
Msg("Registering machine from API/CLI or auth callback") Msg("Registering machine from API/CLI or auth callback")
@ -394,6 +397,7 @@ func (hsdb *HSDatabase) RegisterMachineFromAuthCallback(
machine, err := hsdb.RegisterMachine( machine, err := hsdb.RegisterMachine(
registrationMachine, registrationMachine,
requestedIP,
) )
if err == nil { if err == nil {
@ -410,13 +414,14 @@ func (hsdb *HSDatabase) RegisterMachineFromAuthCallback(
} }
// 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.
func (hsdb *HSDatabase) RegisterMachine(machine types.Machine, func (hsdb *HSDatabase) RegisterMachine(machine types.Machine, requestedIP string,
) (*types.Machine, error) { ) (*types.Machine, error) {
log.Debug(). log.Debug().
Str("machine", machine.Hostname). Str("machine", machine.Hostname).
Str("machine_key", machine.MachineKey). Str("machine_key", machine.MachineKey).
Str("node_key", machine.NodeKey). Str("node_key", machine.NodeKey).
Str("user", machine.User.Name). Str("user", machine.User.Name).
Str("requestedIp", requestedIP).
Msg("Registering machine") Msg("Registering machine")
// If the machine exists and we had already IPs for it, we just save it // If the machine exists and we had already IPs for it, we just save it
@ -452,7 +457,42 @@ func (hsdb *HSDatabase) RegisterMachine(machine types.Machine,
return nil, err return nil, err
} }
machine.IPAddresses = ips if requestedIP != "" {
parsedip, err := netip.ParseAddr(requestedIP)
if err != nil {
return nil, err
}
inrange, err := hsdb.isInRange(parsedip)
if !inrange {
return nil, err
}
usedIps, err := hsdb.getUsedIPs()
if err != nil {
return nil, err
}
var staticip types.MachineAddresses
if !usedIps.Contains(parsedip) {
// avaliableipv6, err := netip.ParseAddr(ips.StringSlice()[1])
// if ips[1].Is4() {
// avaliableipv6, err = netip.ParseAddr(ips.StringSlice()[0])
//}
// if err != nil {
// return nil, err
//}
staticip = append(staticip, parsedip)
machine.IPAddresses = staticip
} else {
return nil, err
}
} else {
machine.IPAddresses = ips
}
if err := hsdb.db.Save(&machine).Error; err != nil { if err := hsdb.db.Save(&machine).Error; err != nil {
return nil, fmt.Errorf("failed register(save) machine in the database: %w", err) return nil, fmt.Errorf("failed register(save) machine in the database: %w", err)
@ -461,7 +501,7 @@ func (hsdb *HSDatabase) RegisterMachine(machine types.Machine,
log.Trace(). log.Trace().
Caller(). Caller().
Str("machine", machine.Hostname). Str("machine", machine.Hostname).
Str("ip", strings.Join(ips.StringSlice(), ",")). Str("ip", strings.Join(machine.IPAddresses.StringSlice(), ",")).
Msg("Machine registered with the database") Msg("Machine registered with the database")
return &machine, nil return &machine, nil

View File

@ -173,6 +173,7 @@ func (api headscaleV1APIServer) RegisterMachine(
log.Trace(). log.Trace().
Str("user", request.GetUser()). Str("user", request.GetUser()).
Str("node_key", request.GetKey()). Str("node_key", request.GetKey()).
Str("ip", request.GetIp()).
Msg("Registering machine") Msg("Registering machine")
machine, err := api.h.db.RegisterMachineFromAuthCallback( machine, err := api.h.db.RegisterMachineFromAuthCallback(
@ -181,6 +182,7 @@ func (api headscaleV1APIServer) RegisterMachine(
request.GetUser(), request.GetUser(),
nil, nil,
util.RegisterMethodCLI, util.RegisterMethodCLI,
request.GetIp(),
) )
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -651,6 +651,7 @@ func (h *Headscale) registerMachineForOIDCCallback(
user.Name, user.Name,
&expiry, &expiry,
util.RegisterMethodOIDC, util.RegisterMethodOIDC,
"",
); err != nil { ); err != nil {
util.LogErr(err, "could not register machine") util.LogErr(err, "could not register machine")
writer.Header().Set("Content-Type", "text/plain; charset=utf-8") writer.Header().Set("Content-Type", "text/plain; charset=utf-8")

View File

@ -50,6 +50,7 @@ message Machine {
message RegisterMachineRequest { message RegisterMachineRequest {
string user = 1; string user = 1;
string key = 2; string key = 2;
string ip = 3;
} }
message RegisterMachineResponse { message RegisterMachineResponse {