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)
registerNodeCmd.Flags().StringP("user", "u", "", "User")
registerNodeCmd.Flags().StringP("ip", "p", "", "Ip")
registerNodeCmd.Flags().StringP("namespace", "n", "", "User")
registerNodeNamespaceFlag := registerNodeCmd.Flags().Lookup("namespace")
registerNodeNamespaceFlag.Deprecated = deprecateNamespaceMessage
@ -132,9 +132,19 @@ var registerNodeCmd = &cobra.Command{
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{
Key: machineKey,
User: user,
Ip: ip,
}
response, err := client.RegisterMachine(ctx, request)

View File

@ -127,6 +127,12 @@ docker exec headscale \
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
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>
```
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
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>
```
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
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>
```
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
Generate a key using the command line:

View File

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

View File

@ -17,6 +17,24 @@ import (
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) {
var ips types.MachineAddresses
var err error

View File

@ -31,6 +31,7 @@ var (
ErrDifferentRegisteredUser = errors.New(
"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.
@ -355,6 +356,7 @@ func (hsdb *HSDatabase) RegisterMachineFromAuthCallback(
userName string,
machineExpiry *time.Time,
registrationMethod string,
requestedIP string,
) (*types.Machine, error) {
nodeKey := key.NodePublic{}
err := nodeKey.UnmarshalText([]byte(nodeKeyStr))
@ -365,6 +367,7 @@ func (hsdb *HSDatabase) RegisterMachineFromAuthCallback(
log.Debug().
Str("nodeKey", nodeKey.ShortString()).
Str("userName", userName).
Str("requestedIp", requestedIP).
Str("registrationMethod", registrationMethod).
Str("expiresAt", fmt.Sprintf("%v", machineExpiry)).
Msg("Registering machine from API/CLI or auth callback")
@ -394,6 +397,7 @@ func (hsdb *HSDatabase) RegisterMachineFromAuthCallback(
machine, err := hsdb.RegisterMachine(
registrationMachine,
requestedIP,
)
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.
func (hsdb *HSDatabase) RegisterMachine(machine types.Machine,
func (hsdb *HSDatabase) RegisterMachine(machine types.Machine, requestedIP string,
) (*types.Machine, error) {
log.Debug().
Str("machine", machine.Hostname).
Str("machine_key", machine.MachineKey).
Str("node_key", machine.NodeKey).
Str("user", machine.User.Name).
Str("requestedIp", requestedIP).
Msg("Registering machine")
// 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
}
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 {
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().
Caller().
Str("machine", machine.Hostname).
Str("ip", strings.Join(ips.StringSlice(), ",")).
Str("ip", strings.Join(machine.IPAddresses.StringSlice(), ",")).
Msg("Machine registered with the database")
return &machine, nil

View File

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

View File

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

View File

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