|
|
|
@ -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")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|