mirror of
https://github.com/juanfont/headscale.git
synced 2025-09-29 17:54:59 +02:00
[ASSIGN CUSTOM IP] optionally assign a custom ip when registering a machine
This commit is contained in:
parent
fb203a2e45
commit
0db30e1472
@ -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,24 @@ var registerNodeCmd = &cobra.Command{
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ip, err := cmd.Flags().GetString("ip")
|
||||||
|
|
||||||
|
if ip == "" {
|
||||||
|
ip = "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
@ -263,6 +263,7 @@ type RegisterMachineRequest struct {
|
|||||||
|
|
||||||
User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
|
User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
|
||||||
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
|
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
|
||||||
|
Ip string `protobuf:"bytes,3,opt,name=ip,proto3" json:"ip,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RegisterMachineRequest) Reset() {
|
func (x *RegisterMachineRequest) Reset() {
|
||||||
@ -311,6 +312,13 @@ func (x *RegisterMachineRequest) GetKey() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *RegisterMachineRequest) GetIp() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Ip
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type RegisterMachineResponse struct {
|
type RegisterMachineResponse struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@ -1207,11 +1215,12 @@ var file_headscale_v1_machine_proto_rawDesc = []byte{
|
|||||||
0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x69, 0x76,
|
0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x69, 0x76,
|
||||||
0x65, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65,
|
0x65, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65,
|
||||||
0x18, 0x16, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x4a, 0x04,
|
0x18, 0x16, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x4a, 0x04,
|
||||||
0x08, 0x0e, 0x10, 0x12, 0x22, 0x3e, 0x0a, 0x16, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
|
0x08, 0x0e, 0x10, 0x12, 0x22, 0x4e, 0x0a, 0x16, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
|
||||||
0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12,
|
0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12,
|
||||||
0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x73,
|
0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x73,
|
||||||
0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x03, 0x6b, 0x65, 0x79, 0x22, 0x4a, 0x0a, 0x17, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
|
0x03, 0x6b, 0x65, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
||||||
|
0x52, 0x02, 0x69, 0x70, 0x22, 0x4a, 0x0a, 0x17, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
|
||||||
0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||||
0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e,
|
0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e,
|
||||||
|
@ -193,6 +193,12 @@
|
|||||||
"in": "query",
|
"in": "query",
|
||||||
"required": false,
|
"required": false,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ip",
|
||||||
|
"in": "query",
|
||||||
|
"required": false,
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
|
@ -355,6 +355,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 +366,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")
|
||||||
@ -387,6 +389,7 @@ func (hsdb *HSDatabase) RegisterMachineFromAuthCallback(
|
|||||||
|
|
||||||
registrationMachine.UserID = user.ID
|
registrationMachine.UserID = user.ID
|
||||||
registrationMachine.RegisterMethod = registrationMethod
|
registrationMachine.RegisterMethod = registrationMethod
|
||||||
|
registrationMachine.RequestedIP = requestedIP
|
||||||
|
|
||||||
if machineExpiry != nil {
|
if machineExpiry != nil {
|
||||||
registrationMachine.Expiry = machineExpiry
|
registrationMachine.Expiry = machineExpiry
|
||||||
@ -417,6 +420,7 @@ func (hsdb *HSDatabase) RegisterMachine(machine types.Machine,
|
|||||||
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", machine.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 +456,33 @@ func (hsdb *HSDatabase) RegisterMachine(machine types.Machine,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
machine.IPAddresses = ips
|
if machine.RequestedIP != "0" {
|
||||||
|
parsedip, err := netip.ParseAddr(machine.RequestedIP)
|
||||||
|
if err != nil {
|
||||||
|
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()[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
staticip = append(staticip, avaliableipv6)
|
||||||
|
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 +491,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
|
||||||
|
@ -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
|
||||||
|
@ -651,6 +651,7 @@ func (h *Headscale) registerMachineForOIDCCallback(
|
|||||||
user.Name,
|
user.Name,
|
||||||
&expiry,
|
&expiry,
|
||||||
util.RegisterMethodOIDC,
|
util.RegisterMethodOIDC,
|
||||||
|
"0",
|
||||||
); 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")
|
||||||
|
@ -30,6 +30,7 @@ type Machine struct {
|
|||||||
NodeKey string
|
NodeKey string
|
||||||
DiscoKey string
|
DiscoKey string
|
||||||
IPAddresses MachineAddresses
|
IPAddresses MachineAddresses
|
||||||
|
RequestedIP string
|
||||||
|
|
||||||
// Hostname represents the name given by the Tailscale
|
// Hostname represents the name given by the Tailscale
|
||||||
// client during registration
|
// client during registration
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user