|
|
|
|
@ -14,6 +14,7 @@ import ( |
|
|
|
|
"os" |
|
|
|
|
"os/exec" |
|
|
|
|
"runtime" |
|
|
|
|
"sort" |
|
|
|
|
"strconv" |
|
|
|
|
"strings" |
|
|
|
|
"sync" |
|
|
|
|
@ -53,6 +54,7 @@ specify any flags, options are reset to their default. |
|
|
|
|
upf.StringVar(&upArgs.hostname, "hostname", "", "hostname to use instead of the one provided by the OS") |
|
|
|
|
if runtime.GOOS == "linux" || isBSD(runtime.GOOS) || version.OS() == "macOS" { |
|
|
|
|
upf.StringVar(&upArgs.advertiseRoutes, "advertise-routes", "", "routes to advertise to other nodes (comma-separated, e.g. 10.0.0.0/8,192.168.0.0/24)") |
|
|
|
|
upf.BoolVar(&upArgs.advertiseDefaultRoute, "advertise-exit-node", false, "offer to be an exit node for internet traffic for the tailnet") |
|
|
|
|
} |
|
|
|
|
if runtime.GOOS == "linux" { |
|
|
|
|
upf.BoolVar(&upArgs.snat, "snat-subnet-routes", true, "source NAT traffic to local routes advertised with --advertise-routes") |
|
|
|
|
@ -71,19 +73,20 @@ func defaultNetfilterMode() string { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var upArgs struct { |
|
|
|
|
server string |
|
|
|
|
acceptRoutes bool |
|
|
|
|
acceptDNS bool |
|
|
|
|
singleRoutes bool |
|
|
|
|
exitNodeIP string |
|
|
|
|
shieldsUp bool |
|
|
|
|
forceReauth bool |
|
|
|
|
advertiseRoutes string |
|
|
|
|
advertiseTags string |
|
|
|
|
snat bool |
|
|
|
|
netfilterMode string |
|
|
|
|
authKey string |
|
|
|
|
hostname string |
|
|
|
|
server string |
|
|
|
|
acceptRoutes bool |
|
|
|
|
acceptDNS bool |
|
|
|
|
singleRoutes bool |
|
|
|
|
exitNodeIP string |
|
|
|
|
shieldsUp bool |
|
|
|
|
forceReauth bool |
|
|
|
|
advertiseRoutes string |
|
|
|
|
advertiseDefaultRoute bool |
|
|
|
|
advertiseTags string |
|
|
|
|
snat bool |
|
|
|
|
netfilterMode string |
|
|
|
|
authKey string |
|
|
|
|
hostname string |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func isBSD(s string) bool { |
|
|
|
|
@ -148,7 +151,7 @@ func runUp(ctx context.Context, args []string) error { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var routes []netaddr.IPPrefix |
|
|
|
|
routeMap := map[netaddr.IPPrefix]bool{} |
|
|
|
|
var default4, default6 bool |
|
|
|
|
if upArgs.advertiseRoutes != "" { |
|
|
|
|
advroutes := strings.Split(upArgs.advertiseRoutes, ",") |
|
|
|
|
@ -165,15 +168,31 @@ func runUp(ctx context.Context, args []string) error { |
|
|
|
|
} else if ipp == ipv6default { |
|
|
|
|
default6 = true |
|
|
|
|
} |
|
|
|
|
routes = append(routes, ipp) |
|
|
|
|
routeMap[ipp] = true |
|
|
|
|
} |
|
|
|
|
if default4 && !default6 { |
|
|
|
|
fatalf("%s advertised without its IPv6 counterpart, please also advertise %s", ipv4default, ipv6default) |
|
|
|
|
} else if default6 && !default4 { |
|
|
|
|
fatalf("%s advertised without its IPv6 counterpart, please also advertise %s", ipv6default, ipv4default) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if upArgs.advertiseDefaultRoute { |
|
|
|
|
routeMap[netaddr.MustParseIPPrefix("0.0.0.0/0")] = true |
|
|
|
|
routeMap[netaddr.MustParseIPPrefix("::/0")] = true |
|
|
|
|
} |
|
|
|
|
if len(routeMap) > 0 { |
|
|
|
|
checkIPForwarding() |
|
|
|
|
} |
|
|
|
|
routes := make([]netaddr.IPPrefix, 0, len(routeMap)) |
|
|
|
|
for r := range routeMap { |
|
|
|
|
routes = append(routes, r) |
|
|
|
|
} |
|
|
|
|
sort.Slice(routes, func(i, j int) bool { |
|
|
|
|
if routes[i].Bits != routes[j].Bits { |
|
|
|
|
return routes[i].Bits < routes[j].Bits |
|
|
|
|
} |
|
|
|
|
return routes[i].IP.Less(routes[j].IP) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
var exitNodeIP netaddr.IP |
|
|
|
|
if upArgs.exitNodeIP != "" { |
|
|
|
|
|