diff --git a/CHANGELOG.md b/CHANGELOG.md index cf0afb7f..ac1e3832 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Target Go 1.19 for Headscale [#778](https://github.com/juanfont/headscale/pull/778) - Target Tailscale v1.30.0 to build Headscale [#780](https://github.com/juanfont/headscale/pull/780) - Give a warning when running Headscale with reverse proxy improperly configured for WebSockets [#788](https://github.com/juanfont/headscale/pull/788) +- Fix subnet routers with Primary Routes [#811](https://github.com/juanfont/headscale/pull/811) ## 0.16.4 (2022-08-21) diff --git a/machine.go b/machine.go index 9fe450a7..92d714e7 100644 --- a/machine.go +++ b/machine.go @@ -26,15 +26,22 @@ const ( ) ErrCouldNotConvertMachineInterface = Error("failed to convert machine interface") ErrHostnameTooLong = Error("Hostname too long") - ErrDifferentRegisteredNamespace = Error("machine was previously registered with a different namespace") - MachineGivenNameHashLength = 8 - MachineGivenNameTrimSize = 2 + ErrDifferentRegisteredNamespace = Error( + "machine was previously registered with a different namespace", + ) + MachineGivenNameHashLength = 8 + MachineGivenNameTrimSize = 2 ) const ( maxHostnameLength = 255 ) +var ( + ExitRouteV4 = netip.MustParsePrefix("0.0.0.0/0") + ExitRouteV6 = netip.MustParsePrefix("::/0") +) + // Machine is a Headscale client. type Machine struct { ID uint64 `gorm:"primary_key"` @@ -633,10 +640,22 @@ func (machine Machine) toNode( []netip.Prefix{}, addrs...) // we append the node own IP, as it is required by the clients - // TODO(kradalby): Needs investigation, We probably dont need this condition - // now that we dont have shared nodes - if includeRoutes { - allowedIPs = append(allowedIPs, machine.EnabledRoutes...) + allowedIPs = append(allowedIPs, machine.EnabledRoutes...) + + // TODO(kradalby): This is kind of a hack where we say that + // all the announced routes (except exit), is presented as primary + // routes. This might be problematic if two nodes expose the same route. + // This was added to address an issue where subnet routers stopped working + // when we only populated AllowedIPs. + primaryRoutes := []netip.Prefix{} + if len(machine.EnabledRoutes) > 0 { + for _, route := range machine.EnabledRoutes { + if route == ExitRouteV4 || route == ExitRouteV6 { + continue + } + + primaryRoutes = append(primaryRoutes, route) + } } var derp string @@ -683,16 +702,17 @@ func (machine Machine) toNode( StableID: tailcfg.StableNodeID( strconv.FormatUint(machine.ID, Base10), ), // in headscale, unlike tailcontrol server, IDs are permanent - Name: hostname, - User: tailcfg.UserID(machine.NamespaceID), - Key: nodeKey, - KeyExpiry: keyExpiry, - Machine: machineKey, - DiscoKey: discoKey, - Addresses: addrs, - AllowedIPs: allowedIPs, - Endpoints: machine.Endpoints, - DERP: derp, + Name: hostname, + User: tailcfg.UserID(machine.NamespaceID), + Key: nodeKey, + KeyExpiry: keyExpiry, + Machine: machineKey, + DiscoKey: discoKey, + Addresses: addrs, + AllowedIPs: allowedIPs, + PrimaryRoutes: primaryRoutes, + Endpoints: machine.Endpoints, + DERP: derp, Online: &online, Hostinfo: hostInfo.View(), @@ -807,7 +827,8 @@ func (h *Headscale) RegisterMachineFromAuthCallback( } // Registration of expired machine with different namespace - if registrationMachine.ID != 0 && registrationMachine.NamespaceID != namespace.ID { + if registrationMachine.ID != 0 && + registrationMachine.NamespaceID != namespace.ID { return nil, ErrDifferentRegisteredNamespace }