ipn,ipn/ipnlocal,cmd/tailscale/cli: add support for passing a route filter via --accept-routes
Signed-off-by: James Tucker <james@tailscale.com>pull/5770/head
parent
627c60b0d1
commit
919ad7df82
|
@ -69,14 +69,17 @@ func effectiveGOOS() string {
|
|||
|
||||
// acceptRouteDefault returns the CLI's default value of --accept-routes as
|
||||
// a function of the platform it's running on.
|
||||
func acceptRouteDefault(goos string) bool {
|
||||
func acceptRouteDefault(goos string) string {
|
||||
switch goos {
|
||||
case "windows":
|
||||
return true
|
||||
return "true"
|
||||
case "darwin":
|
||||
return version.IsSandboxedMacOS()
|
||||
if version.IsSandboxedMacOS() {
|
||||
return "true"
|
||||
}
|
||||
return "false"
|
||||
default:
|
||||
return false
|
||||
return "false"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,7 +96,7 @@ func newUpFlagSet(goos string, upArgs *upArgsT) *flag.FlagSet {
|
|||
upf.BoolVar(&upArgs.reset, "reset", false, "reset unspecified settings to their default values")
|
||||
|
||||
upf.StringVar(&upArgs.server, "login-server", ipn.DefaultControlURL, "base URL of control server")
|
||||
upf.BoolVar(&upArgs.acceptRoutes, "accept-routes", acceptRouteDefault(goos), "accept routes advertised by other Tailscale nodes")
|
||||
upf.StringVar(&upArgs.acceptRoutes, "accept-routes", acceptRouteDefault(goos), "accept routes advertised by other Tailscale nodes")
|
||||
upf.BoolVar(&upArgs.acceptDNS, "accept-dns", true, "accept DNS configuration from the admin panel")
|
||||
upf.BoolVar(&upArgs.singleRoutes, "host-routes", true, "install host routes to other Tailscale nodes")
|
||||
upf.StringVar(&upArgs.exitNodeIP, "exit-node", "", "Tailscale exit node (IP or base name) for internet traffic, or empty string to not use an exit node")
|
||||
|
@ -131,7 +134,7 @@ type upArgsT struct {
|
|||
qr bool
|
||||
reset bool
|
||||
server string
|
||||
acceptRoutes bool
|
||||
acceptRoutes string
|
||||
acceptDNS bool
|
||||
singleRoutes bool
|
||||
exitNodeIP string
|
||||
|
@ -307,7 +310,25 @@ func prefsFromUpArgs(upArgs upArgsT, warnf logger.Logf, st *ipnstate.Status, goo
|
|||
prefs := ipn.NewPrefs()
|
||||
prefs.ControlURL = upArgs.server
|
||||
prefs.WantRunning = true
|
||||
prefs.RouteAll = upArgs.acceptRoutes
|
||||
|
||||
switch upArgs.acceptRoutes {
|
||||
case "0", "f", "false":
|
||||
prefs.RouteAll = false
|
||||
case "1", "t", "true":
|
||||
prefs.RouteAll = true
|
||||
default:
|
||||
prefs.RouteAll = true
|
||||
prefs.AcceptRoutesFilter = upArgs.acceptRoutes
|
||||
|
||||
// accept-routes accepts an include/exclude ip range of the form:
|
||||
// 0.0.0.0/0,-192.168.20.0/24
|
||||
// Ensure that the provided values parse correctly, as the backend can only
|
||||
// bury errors in the logs.
|
||||
_, err := ipn.ParseAcceptRoutesFilter(prefs.AcceptRoutesFilter)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("accept-routes filter %q did not parse: %w", prefs.AcceptRoutesFilter, err)
|
||||
}
|
||||
}
|
||||
|
||||
if upArgs.exitNodeIP != "" {
|
||||
if err := prefs.SetExitNodeIP(upArgs.exitNodeIP, st); err != nil {
|
||||
|
@ -453,7 +474,7 @@ func runUp(ctx context.Context, args []string) (retErr error) {
|
|||
|
||||
if distro.Get() == distro.Synology {
|
||||
notSupported := "not supported on Synology; see https://github.com/tailscale/tailscale/issues/1995"
|
||||
if upArgs.acceptRoutes {
|
||||
if upArgs.acceptRoutes != "" && upArgs.acceptRoutes != "f" && upArgs.acceptRoutes != "false" {
|
||||
return errors.New("--accept-routes is " + notSupported)
|
||||
}
|
||||
if upArgs.exitNodeIP != "" {
|
||||
|
@ -735,10 +756,10 @@ func init() {
|
|||
|
||||
// And this flag has two ipn.Prefs:
|
||||
addPrefFlagMapping("exit-node", "ExitNodeIP", "ExitNodeID")
|
||||
addPrefFlagMapping("accept-routes", "RouteAll", "AcceptRoutesFilter")
|
||||
|
||||
// The rest are 1:1:
|
||||
addPrefFlagMapping("accept-dns", "CorpDNS")
|
||||
addPrefFlagMapping("accept-routes", "RouteAll")
|
||||
addPrefFlagMapping("advertise-tags", "AdvertiseTags")
|
||||
addPrefFlagMapping("host-routes", "AllowSingleHosts")
|
||||
addPrefFlagMapping("hostname", "Hostname")
|
||||
|
|
|
@ -2775,32 +2775,6 @@ func ipPrefixLess(ri, rj netip.Prefix) bool {
|
|||
return ri.Addr().Less(rj.Addr())
|
||||
}
|
||||
|
||||
func (b *LocalBackend) parseAcceptRoutesFilter(acceptFilter string) (*netipx.IPSet, error) {
|
||||
var acceptFilterBuilder netipx.IPSetBuilder
|
||||
for _, af := range strings.Split(acceptFilter, ",") {
|
||||
af = strings.TrimSpace(af)
|
||||
if af == "" {
|
||||
continue
|
||||
}
|
||||
includeRange := true
|
||||
if strings.HasPrefix(af, "-") {
|
||||
includeRange = false
|
||||
af = af[1:]
|
||||
}
|
||||
pfx, err := netip.ParsePrefix(af)
|
||||
if err != nil {
|
||||
b.logf("accept routes filter: invalid prefix %q will be ignored: %v (check accept-routes flag)", af, err)
|
||||
continue
|
||||
}
|
||||
if includeRange {
|
||||
acceptFilterBuilder.AddPrefix(pfx)
|
||||
} else {
|
||||
acceptFilterBuilder.RemovePrefix(pfx)
|
||||
}
|
||||
}
|
||||
return acceptFilterBuilder.IPSet()
|
||||
}
|
||||
|
||||
func (b *LocalBackend) filterRoutes(routes []netip.Prefix, acceptFilter *netipx.IPSet) []netip.Prefix {
|
||||
if acceptFilter == nil {
|
||||
return routes
|
||||
|
@ -2815,6 +2789,7 @@ func (b *LocalBackend) filterRoutes(routes []netip.Prefix, acceptFilter *netipx.
|
|||
b.logf("accept routes filter: failed to build filtered set, all routes will be accepted: %v (check accept-routes flag)", err)
|
||||
return routes
|
||||
}
|
||||
b.logf("accept routes filter: accepting routes: %v", set.Ranges())
|
||||
return set.Prefixes()
|
||||
}
|
||||
|
||||
|
@ -2825,9 +2800,9 @@ func (b *LocalBackend) routerConfig(cfg *wgcfg.Config, prefs *ipn.Prefs, oneCGNA
|
|||
singleRouteThreshold = 1
|
||||
}
|
||||
|
||||
acceptRoutesFilterSet, err := b.parseAcceptRoutesFilter(prefs.AcceptRoutesFilter)
|
||||
acceptRoutesFilterSet, err := ipn.ParseAcceptRoutesFilter(prefs.AcceptRoutesFilter)
|
||||
if err != nil {
|
||||
b.logf("accept routes filter: failed to build filter set: %v", err)
|
||||
b.logf("accept routes filter: failed to build filter set from %q: %v", prefs.AcceptRoutesFilter, err)
|
||||
}
|
||||
|
||||
rs := &router.Config{
|
||||
|
|
26
ipn/prefs.go
26
ipn/prefs.go
|
@ -17,6 +17,7 @@ import (
|
|||
"runtime"
|
||||
"strings"
|
||||
|
||||
"go4.org/netipx"
|
||||
"tailscale.com/atomicfile"
|
||||
"tailscale.com/ipn/ipnstate"
|
||||
"tailscale.com/net/netaddr"
|
||||
|
@ -657,3 +658,28 @@ func SavePrefs(filename string, p *Prefs) {
|
|||
log.Printf("SavePrefs: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func ParseAcceptRoutesFilter(acceptFilter string) (*netipx.IPSet, error) {
|
||||
var acceptFilterBuilder netipx.IPSetBuilder
|
||||
for _, af := range strings.Split(acceptFilter, ",") {
|
||||
af = strings.TrimSpace(af)
|
||||
if af == "" {
|
||||
continue
|
||||
}
|
||||
includeRange := true
|
||||
if strings.HasPrefix(af, "-") {
|
||||
includeRange = false
|
||||
af = af[1:]
|
||||
}
|
||||
pfx, err := netip.ParsePrefix(af)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if includeRange {
|
||||
acceptFilterBuilder.AddPrefix(pfx)
|
||||
} else {
|
||||
acceptFilterBuilder.RemovePrefix(pfx)
|
||||
}
|
||||
}
|
||||
return acceptFilterBuilder.IPSet()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue