@@ -81,51 +81,65 @@ func (h *Headscale) RegistrationHandler(c *gin.Context) {
8181 return
8282 }
8383 defer db .Close ()
84- var m Machine
85- resp := tailcfg.RegisterResponse {}
8684
85+ var m Machine
8786 if db .First (& m , "machine_key = ?" , mKey .HexString ()).RecordNotFound () {
8887 log .Println ("New Machine!" )
89- h .handleNewServer (c , db , mKey , req )
88+ m = Machine {
89+ Expiry : & req .Expiry ,
90+ MachineKey : mKey .HexString (),
91+ Name : req .Hostinfo .Hostname ,
92+ NodeKey : wgcfg .Key (req .NodeKey ).HexString (),
93+ }
94+ if err := db .Create (& m ).Error ; err != nil {
95+ log .Printf ("Could not create row: %s" , err )
96+ return
97+ }
98+ }
99+
100+ if ! m .Registered && req .Auth .AuthKey != "" {
101+ h .handleAuthKey (c , db , mKey , req , m )
90102 return
91103 }
92104
93- // We do have the updated key!
105+ resp := tailcfg.RegisterResponse {}
106+
107+ // We have the updated key!
94108 if m .NodeKey == wgcfg .Key (req .NodeKey ).HexString () {
95109 if m .Registered {
96- log .Printf ("[%s] Client is registered and we have the current key . All clear to /map\n " , m .Name )
110+ log .Printf ("[%s] Client is registered and we have the current NodeKey . All clear to /map" , m .Name )
97111 resp .AuthURL = ""
98- resp .User = * m .Namespace .toUser ()
99112 resp .MachineAuthorized = true
113+ resp .User = * m .Namespace .toUser ()
100114 respBody , err := encode (resp , & mKey , h .privateKey )
101115 if err != nil {
102116 log .Printf ("Cannot encode message: %s" , err )
103- c .String (http .StatusInternalServerError , "Extremely sad! " )
117+ c .String (http .StatusInternalServerError , "" )
104118 return
105119 }
106120 c .Data (200 , "application/json; charset=utf-8" , respBody )
107121 return
108122 }
109123
110- log .Println ( "Hey! Not registered. Not asking for key rotation. Send a passive-aggressive authurl to register" )
124+ log .Printf ( "[%s] Not registered and not NodeKey rotation. Sending a authurl to register", m . Name )
111125 resp .AuthURL = fmt .Sprintf ("%s/register?key=%s" ,
112126 h .cfg .ServerURL , mKey .HexString ())
113127 respBody , err := encode (resp , & mKey , h .privateKey )
114128 if err != nil {
115129 log .Printf ("Cannot encode message: %s" , err )
116- c .String (http .StatusInternalServerError , "Extremely sad! " )
130+ c .String (http .StatusInternalServerError , "" )
117131 return
118132 }
119133 c .Data (200 , "application/json; charset=utf-8" , respBody )
120134 return
121-
122135 }
123136
124- // We dont have the updated key in the DB. Lets try with the old one.
137+ // The NodeKey we have matches OldNodeKey, which means this is a refresh after an key expiration
125138 if m .NodeKey == wgcfg .Key (req .OldNodeKey ).HexString () {
126- log .Println ( "Key rotation!" )
139+ log .Printf ( "[%s] We have the NodeKey in the database. This is a key refresh" , m . Name )
127140 m .NodeKey = wgcfg .Key (req .NodeKey ).HexString ()
128141 db .Save (& m )
142+
129143 resp .AuthURL = ""
130144 resp .User = * m .Namespace .toUser ()
131145 respBody , err := encode (resp , & mKey , h .privateKey )
@@ -138,8 +152,32 @@ func (h *Headscale) RegistrationHandler(c *gin.Context) {
138152 return
139153 }
140154
141- log .Println ("We dont know anything about the new key. WTF" )
142- // spew.Dump(req)
155+ // We arrive here after a client is restarted without finalizing the authentication flow or
156+ // when headscale is stopped in the middle of the auth process.
157+ if m .Registered {
158+ log .Printf ("[%s] The node is sending us a new NodeKey, but machine is registered. All clear for /map" , m .Name )
159+ resp .AuthURL = ""
160+ resp .MachineAuthorized = true
161+ resp .User = * m .Namespace .toUser ()
162+ respBody , err := encode (resp , & mKey , h .privateKey )
163+ if err != nil {
164+ log .Printf ("Cannot encode message: %s" , err )
165+ c .String (http .StatusInternalServerError , "" )
166+ return
167+ }
168+ c .Data (200 , "application/json; charset=utf-8" , respBody )
169+ return
170+ }
171+ log .Printf ("[%s] The node is sending us a new NodeKey, sending auth url" , m .Name )
172+ resp .AuthURL = fmt .Sprintf ("%s/register?key=%s" ,
173+ h .cfg .ServerURL , mKey .HexString ())
174+ respBody , err := encode (resp , & mKey , h .privateKey )
175+ if err != nil {
176+ log .Printf ("Cannot encode message: %s" , err )
177+ c .String (http .StatusInternalServerError , "" )
178+ return
179+ }
180+ c .Data (200 , "application/json; charset=utf-8" , respBody )
143181}
144182
145183// PollNetMapHandler takes care of /machine/:id/map
@@ -390,66 +428,44 @@ func (h *Headscale) getMapKeepAliveResponse(mKey wgcfg.Key, req tailcfg.MapReque
390428 return & data , nil
391429}
392430
393- func (h * Headscale ) handleNewServer (c * gin.Context , db * gorm.DB , idKey wgcfg.Key , req tailcfg.RegisterRequest ) {
394- m := Machine {
395- MachineKey : idKey .HexString (),
396- NodeKey : wgcfg .Key (req .NodeKey ).HexString (),
397- Expiry : & req .Expiry ,
398- Name : req .Hostinfo .Hostname ,
399- }
400- if err := db .Create (& m ).Error ; err != nil {
401- log .Printf ("Could not create row: %s" , err )
402- return
403- }
404-
431+ func (h * Headscale ) handleAuthKey (c * gin.Context , db * gorm.DB , idKey wgcfg.Key , req tailcfg.RegisterRequest , m Machine ) {
405432 resp := tailcfg.RegisterResponse {}
406-
407- if req .Auth .AuthKey != "" {
408- pak , err := h .checkKeyValidity (req .Auth .AuthKey )
409- if err != nil {
410- resp .MachineAuthorized = false
411- respBody , err := encode (resp , & idKey , h .privateKey )
412- if err != nil {
413- log .Printf ("Cannot encode message: %s" , err )
414- c .String (http .StatusInternalServerError , "" )
415- return
416- }
417- c .Data (200 , "application/json; charset=utf-8" , respBody )
418- return
419- }
420- ip , err := h .getAvailableIP ()
421- if err != nil {
422- log .Println (err )
423- return
424- }
425-
426- m .IPAddress = ip .String ()
427- m .NamespaceID = pak .NamespaceID
428- m .AuthKeyID = uint (pak .ID )
429- m .RegisterMethod = "authKey"
430- m .Registered = true
431- db .Save (& m )
432-
433- resp .MachineAuthorized = true
434- resp .User = * pak .Namespace .toUser ()
433+ pak , err := h .checkKeyValidity (req .Auth .AuthKey )
434+ if err != nil {
435+ resp .MachineAuthorized = false
435436 respBody , err := encode (resp , & idKey , h .privateKey )
436437 if err != nil {
437438 log .Printf ("Cannot encode message: %s" , err )
438- c .String (http .StatusInternalServerError , "Extremely sad! " )
439+ c .String (http .StatusInternalServerError , "" )
439440 return
440441 }
441442 c .Data (200 , "application/json; charset=utf-8" , respBody )
443+ log .Printf ("[%s] Failed authentication via AuthKey" , m .Name )
444+ return
445+ }
446+ ip , err := h .getAvailableIP ()
447+ if err != nil {
448+ log .Println (err )
442449 return
443450 }
444451
445- resp .AuthURL = fmt .Sprintf ("%s/register?key=%s" ,
446- h .cfg .ServerURL , idKey .HexString ())
452+ m .AuthKeyID = uint (pak .ID )
453+ m .IPAddress = ip .String ()
454+ m .NamespaceID = pak .NamespaceID
455+ m .NodeKey = wgcfg .Key (req .NodeKey ).HexString () // we update it just in case
456+ m .Registered = true
457+ m .RegisterMethod = "authKey"
458+ db .Save (& m )
447459
460+ resp .MachineAuthorized = true
461+ resp .User = * pak .Namespace .toUser ()
448462 respBody , err := encode (resp , & idKey , h .privateKey )
449463 if err != nil {
450464 log .Printf ("Cannot encode message: %s" , err )
451465 c .String (http .StatusInternalServerError , "Extremely sad!" )
452466 return
453467 }
454468 c .Data (200 , "application/json; charset=utf-8" , respBody )
469+ log .Printf ("[%s] Successfully authenticated via AuthKey" , m .Name )
470+ return
455471}
0 commit comments