mirror of
https://github.com/tailscale/tailscale.git
synced 2024-12-01 22:15:51 +00:00
wip
This commit is contained in:
parent
1ae16546af
commit
d32aaffca6
@ -1417,6 +1417,14 @@ func (lc *LocalClient) CheckUpdate(ctx context.Context) (*tailcfg.ClientVersion,
|
||||
return &cv, nil
|
||||
}
|
||||
|
||||
func (lc *LocalClient) SuggestExitNode(ctx context.Context) error {
|
||||
body, err := lc.send(ctx, "POST", "/localapi/v0/suggest-exit-node", 200, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error %w: %s", err, body)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IPNBusWatcher is an active subscription (watch) of the local tailscaled IPN bus.
|
||||
// It's returned by LocalClient.WatchIPNBus.
|
||||
//
|
||||
|
@ -64,7 +64,7 @@ func newSetFlagSet(goos string, setArgs *setArgsT) *flag.FlagSet {
|
||||
setf.StringVar(&setArgs.profileName, "nickname", "", "nickname for the current account")
|
||||
setf.BoolVar(&setArgs.acceptRoutes, "accept-routes", false, "accept routes advertised by other Tailscale nodes")
|
||||
setf.BoolVar(&setArgs.acceptDNS, "accept-dns", false, "accept DNS configuration from the admin panel")
|
||||
setf.StringVar(&setArgs.exitNodeIP, "exit-node", "", "Tailscale exit node (IP or base name) for internet traffic, or empty string to not use an exit node")
|
||||
setf.StringVar(&setArgs.exitNodeIP, "exit-node", "", "Tailscale exit node (IP or base name) for internet traffic, or empty string to not use an exit node. Input suggest as the string for Tailscale to pick the best exit node.")
|
||||
setf.BoolVar(&setArgs.exitNodeAllowLANAccess, "exit-node-allow-lan-access", false, "Allow direct access to the local network when routing traffic via an exit node")
|
||||
setf.BoolVar(&setArgs.shieldsUp, "shields-up", false, "don't allow incoming connections")
|
||||
setf.BoolVar(&setArgs.runSSH, "ssh", false, "run an SSH server, permitting access per tailnet admin's declared policy")
|
||||
@ -128,12 +128,19 @@ func runSet(ctx context.Context, args []string) (retErr error) {
|
||||
}
|
||||
|
||||
if setArgs.exitNodeIP != "" {
|
||||
if err := maskedPrefs.Prefs.SetExitNodeIP(setArgs.exitNodeIP, st); err != nil {
|
||||
var e ipn.ExitNodeLocalIPError
|
||||
if errors.As(err, &e) {
|
||||
return fmt.Errorf("%w; did you mean --advertise-exit-node?", err)
|
||||
if setArgs.exitNodeIP == "suggest" {
|
||||
err := localClient.SuggestExitNode(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := maskedPrefs.Prefs.SetExitNodeIP(setArgs.exitNodeIP, st); err != nil {
|
||||
var e ipn.ExitNodeLocalIPError
|
||||
if errors.As(err, &e) {
|
||||
return fmt.Errorf("%w; did you mean --advertise-exit-node?", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
"io"
|
||||
"log"
|
||||
"maps"
|
||||
"math"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/netip"
|
||||
@ -107,6 +108,8 @@
|
||||
|
||||
var controlDebugFlags = getControlDebugFlags()
|
||||
|
||||
const derpPrefix = "127.3.3.40:"
|
||||
|
||||
func getControlDebugFlags() []string {
|
||||
if e := envknob.String("TS_DEBUG_CONTROL_FLAGS"); e != "" {
|
||||
return strings.Split(e, ",")
|
||||
@ -306,7 +309,8 @@ type LocalBackend struct {
|
||||
clock tstime.Clock
|
||||
|
||||
// Last ClientVersion received in MapResponse, guarded by mu.
|
||||
lastClientVersion *tailcfg.ClientVersion
|
||||
lastClientVersion *tailcfg.ClientVersion
|
||||
suggestedExitNodeMap map[tailcfg.NodeID]tailcfg.DERPRegion
|
||||
}
|
||||
|
||||
type updateStatus struct {
|
||||
@ -1431,7 +1435,6 @@ func setExitNodeID(prefs *ipn.Prefs, nm *netmap.NetworkMap) (prefsChanged bool)
|
||||
return oldExitNodeID != prefs.ExitNodeID
|
||||
}
|
||||
}
|
||||
|
||||
return prefsChanged
|
||||
}
|
||||
|
||||
@ -5909,3 +5912,36 @@ func mayDeref[T any](p *T) (v T) {
|
||||
}
|
||||
return *p
|
||||
}
|
||||
|
||||
func (b *LocalBackend) SuggestExitNode() error {
|
||||
//b.mu.Lock()
|
||||
netMap := b.netMap
|
||||
peers := netMap.Peers
|
||||
lastReport := b.MagicConn().GetLastNetcheckReport()
|
||||
var fastestRegionLatency = time.Duration(math.MaxInt64)
|
||||
var preferredExitNodeID tailcfg.StableNodeID
|
||||
for _, peer := range peers {
|
||||
if tsaddr.ContainsExitRoutes(peer.AllowedIPs()) && strings.HasPrefix(peer.DERP(), derpPrefix) {
|
||||
ipp, _ := netip.ParseAddrPort(peer.DERP())
|
||||
regionID := int(ipp.Port())
|
||||
if lastReport.RegionLatency[regionID] < fastestRegionLatency {
|
||||
fastestRegionLatency = lastReport.RegionLatency[regionID]
|
||||
preferredExitNodeID = peer.StableID()
|
||||
b.logf("fastest region latency %v preferred exit node id %v", lastReport.RegionLatency[regionID], peer.StableID())
|
||||
}
|
||||
}
|
||||
}
|
||||
// b.mu.Unlock()
|
||||
prefs := b.Prefs().AsStruct()
|
||||
prefs.ExitNodeID = preferredExitNodeID
|
||||
_, err := b.EditPrefs(&ipn.MaskedPrefs{
|
||||
Prefs: ipn.Prefs{
|
||||
ExitNodeID: preferredExitNodeID,
|
||||
},
|
||||
ExitNodeIDSet: true,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to suggest exit node %v, err %v", preferredExitNodeID, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -129,6 +129,7 @@
|
||||
"update/check": (*Handler).serveUpdateCheck,
|
||||
"update/install": (*Handler).serveUpdateInstall,
|
||||
"update/progress": (*Handler).serveUpdateProgress,
|
||||
"suggest-exit-node": (*Handler).serveSuggestExitNode,
|
||||
}
|
||||
|
||||
var (
|
||||
@ -2504,3 +2505,19 @@ func (h *Handler) serveUpdateProgress(w http.ResponseWriter, r *http.Request) {
|
||||
// User-visible LocalAPI endpoints.
|
||||
metricFilePutCalls = clientmetric.NewCounter("localapi_file_put")
|
||||
)
|
||||
|
||||
func (h *Handler) serveSuggestExitNode(w http.ResponseWriter, r *http.Request) {
|
||||
if !h.PermitWrite {
|
||||
http.Error(w, "access denied", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
if r.Method != "POST" {
|
||||
http.Error(w, "want POST", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
err := h.b.SuggestExitNode()
|
||||
if err != nil {
|
||||
writeErrorJSON(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -799,6 +799,7 @@ func (p *Prefs) SetExitNodeIP(s string, st *ipnstate.Status) error {
|
||||
if err == nil {
|
||||
p.ExitNodeIP = ip
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user