|
|
|
|
@ -17,7 +17,6 @@ import ( |
|
|
|
|
"os" |
|
|
|
|
"path" |
|
|
|
|
"path/filepath" |
|
|
|
|
"slices" |
|
|
|
|
"strings" |
|
|
|
|
"sync" |
|
|
|
|
"time" |
|
|
|
|
@ -35,6 +34,7 @@ import ( |
|
|
|
|
"tailscale.com/net/tsaddr" |
|
|
|
|
"tailscale.com/tailcfg" |
|
|
|
|
"tailscale.com/types/logger" |
|
|
|
|
"tailscale.com/types/views" |
|
|
|
|
"tailscale.com/util/httpm" |
|
|
|
|
"tailscale.com/version" |
|
|
|
|
"tailscale.com/version/distro" |
|
|
|
|
@ -113,11 +113,6 @@ const ( |
|
|
|
|
ManageServerMode ServerMode = "manage" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
exitNodeRouteV4 = netip.MustParsePrefix("0.0.0.0/0") |
|
|
|
|
exitNodeRouteV6 = netip.MustParsePrefix("::/0") |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
// ServerOpts contains options for constructing a new Server.
|
|
|
|
|
type ServerOpts struct { |
|
|
|
|
// Mode specifies the mode of web client being constructed.
|
|
|
|
|
@ -927,10 +922,10 @@ func (s *Server) serveGetNodeData(w http.ResponseWriter, r *http.Request) { |
|
|
|
|
return p == route |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
data.AdvertisingExitNodeApproved = routeApproved(exitNodeRouteV4) || routeApproved(exitNodeRouteV6) |
|
|
|
|
data.AdvertisingExitNodeApproved = routeApproved(tsaddr.AllIPv4()) || routeApproved(tsaddr.AllIPv6()) |
|
|
|
|
|
|
|
|
|
for _, r := range prefs.AdvertiseRoutes { |
|
|
|
|
if r == exitNodeRouteV4 || r == exitNodeRouteV6 { |
|
|
|
|
if tsaddr.IsExitRoute(r) { |
|
|
|
|
data.AdvertisingExitNode = true |
|
|
|
|
} else { |
|
|
|
|
data.AdvertisedRoutes = append(data.AdvertisedRoutes, subnetRoute{ |
|
|
|
|
@ -1071,7 +1066,7 @@ func (s *Server) servePostRoutes(ctx context.Context, data postRoutesRequest) er |
|
|
|
|
var currNonExitRoutes []string |
|
|
|
|
var currAdvertisingExitNode bool |
|
|
|
|
for _, r := range prefs.AdvertiseRoutes { |
|
|
|
|
if r == exitNodeRouteV4 || r == exitNodeRouteV6 { |
|
|
|
|
if tsaddr.IsExitRoute(r) { |
|
|
|
|
currAdvertisingExitNode = true |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
@ -1092,12 +1087,7 @@ func (s *Server) servePostRoutes(ctx context.Context, data postRoutesRequest) er |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
hasExitNodeRoute := func(all []netip.Prefix) bool { |
|
|
|
|
return slices.Contains(all, exitNodeRouteV4) || |
|
|
|
|
slices.Contains(all, exitNodeRouteV6) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if !data.UseExitNode.IsZero() && hasExitNodeRoute(routes) { |
|
|
|
|
if !data.UseExitNode.IsZero() && tsaddr.ContainsExitRoutes(views.SliceOf(routes)) { |
|
|
|
|
return errors.New("cannot use and advertise exit node at same time") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|