mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 04:55:31 +00:00
ipn/ipnlocal: error when trying to use exit node on unsupported platform (#13726)
Adds logic to `checkExitNodePrefsLocked` to return an error when attempting to use exit nodes on a platform where this is not supported. This mirrors logic that was added to error out when trying to use `ssh` on an unsupported platform, and has very similar semantics. Fixes https://github.com/tailscale/tailscale/issues/13724 Signed-off-by: Mario Minardi <mario@tailscale.com>
This commit is contained in:
parent
6a885dbc36
commit
d32d742af0
@ -26,6 +26,7 @@
|
|||||||
"tailscale.com/client/tailscale/apitype"
|
"tailscale.com/client/tailscale/apitype"
|
||||||
"tailscale.com/clientupdate"
|
"tailscale.com/clientupdate"
|
||||||
"tailscale.com/envknob"
|
"tailscale.com/envknob"
|
||||||
|
"tailscale.com/envknob/featureknob"
|
||||||
"tailscale.com/hostinfo"
|
"tailscale.com/hostinfo"
|
||||||
"tailscale.com/ipn"
|
"tailscale.com/ipn"
|
||||||
"tailscale.com/ipn/ipnstate"
|
"tailscale.com/ipn/ipnstate"
|
||||||
@ -960,37 +961,16 @@ func (s *Server) serveGetNodeData(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func availableFeatures() map[string]bool {
|
func availableFeatures() map[string]bool {
|
||||||
env := hostinfo.GetEnvType()
|
|
||||||
features := map[string]bool{
|
features := map[string]bool{
|
||||||
"advertise-exit-node": true, // available on all platforms
|
"advertise-exit-node": true, // available on all platforms
|
||||||
"advertise-routes": true, // available on all platforms
|
"advertise-routes": true, // available on all platforms
|
||||||
"use-exit-node": canUseExitNode(env) == nil,
|
"use-exit-node": featureknob.CanUseExitNode() == nil,
|
||||||
"ssh": envknob.CanRunTailscaleSSH() == nil,
|
"ssh": featureknob.CanRunTailscaleSSH() == nil,
|
||||||
"auto-update": version.IsUnstableBuild() && clientupdate.CanAutoUpdate(),
|
"auto-update": version.IsUnstableBuild() && clientupdate.CanAutoUpdate(),
|
||||||
}
|
}
|
||||||
if env == hostinfo.HomeAssistantAddOn {
|
|
||||||
// Setting SSH on Home Assistant causes trouble on startup
|
|
||||||
// (since the flag is not being passed to `tailscale up`).
|
|
||||||
// Although Tailscale SSH does work here,
|
|
||||||
// it's not terribly useful since it's running in a separate container.
|
|
||||||
features["ssh"] = false
|
|
||||||
}
|
|
||||||
return features
|
return features
|
||||||
}
|
}
|
||||||
|
|
||||||
func canUseExitNode(env hostinfo.EnvType) error {
|
|
||||||
switch dist := distro.Get(); dist {
|
|
||||||
case distro.Synology, // see https://github.com/tailscale/tailscale/issues/1995
|
|
||||||
distro.QNAP,
|
|
||||||
distro.Unraid:
|
|
||||||
return fmt.Errorf("Tailscale exit nodes cannot be used on %s.", dist)
|
|
||||||
}
|
|
||||||
if env == hostinfo.HomeAssistantAddOn {
|
|
||||||
return errors.New("Tailscale exit nodes cannot be used on Home Assistant.")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// aclsAllowAccess returns whether tailnet ACLs (as expressed in the provided filter rules)
|
// aclsAllowAccess returns whether tailnet ACLs (as expressed in the provided filter rules)
|
||||||
// permit any devices to access the local web client.
|
// permit any devices to access the local web client.
|
||||||
// This does not currently check whether a specific device can connect, just any device.
|
// This does not currently check whether a specific device can connect, just any device.
|
||||||
|
@ -668,6 +668,7 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
|||||||
tailscale.com/doctor/routetable from tailscale.com/ipn/ipnlocal
|
tailscale.com/doctor/routetable from tailscale.com/ipn/ipnlocal
|
||||||
tailscale.com/drive from tailscale.com/client/tailscale+
|
tailscale.com/drive from tailscale.com/client/tailscale+
|
||||||
tailscale.com/envknob from tailscale.com/client/tailscale+
|
tailscale.com/envknob from tailscale.com/client/tailscale+
|
||||||
|
tailscale.com/envknob/featureknob from tailscale.com/client/web+
|
||||||
tailscale.com/health from tailscale.com/control/controlclient+
|
tailscale.com/health from tailscale.com/control/controlclient+
|
||||||
tailscale.com/health/healthmsg from tailscale.com/ipn/ipnlocal
|
tailscale.com/health/healthmsg from tailscale.com/ipn/ipnlocal
|
||||||
tailscale.com/hostinfo from tailscale.com/client/web+
|
tailscale.com/hostinfo from tailscale.com/client/web+
|
||||||
|
@ -92,6 +92,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
|
|||||||
tailscale.com/disco from tailscale.com/derp
|
tailscale.com/disco from tailscale.com/derp
|
||||||
tailscale.com/drive from tailscale.com/client/tailscale+
|
tailscale.com/drive from tailscale.com/client/tailscale+
|
||||||
tailscale.com/envknob from tailscale.com/client/tailscale+
|
tailscale.com/envknob from tailscale.com/client/tailscale+
|
||||||
|
tailscale.com/envknob/featureknob from tailscale.com/client/web
|
||||||
tailscale.com/health from tailscale.com/net/tlsdial+
|
tailscale.com/health from tailscale.com/net/tlsdial+
|
||||||
tailscale.com/health/healthmsg from tailscale.com/cmd/tailscale/cli
|
tailscale.com/health/healthmsg from tailscale.com/cmd/tailscale/cli
|
||||||
tailscale.com/hostinfo from tailscale.com/client/web+
|
tailscale.com/hostinfo from tailscale.com/client/web+
|
||||||
|
@ -263,6 +263,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/drive/driveimpl/dirfs from tailscale.com/drive/driveimpl+
|
tailscale.com/drive/driveimpl/dirfs from tailscale.com/drive/driveimpl+
|
||||||
tailscale.com/drive/driveimpl/shared from tailscale.com/drive/driveimpl+
|
tailscale.com/drive/driveimpl/shared from tailscale.com/drive/driveimpl+
|
||||||
tailscale.com/envknob from tailscale.com/client/tailscale+
|
tailscale.com/envknob from tailscale.com/client/tailscale+
|
||||||
|
tailscale.com/envknob/featureknob from tailscale.com/client/web+
|
||||||
tailscale.com/health from tailscale.com/control/controlclient+
|
tailscale.com/health from tailscale.com/control/controlclient+
|
||||||
tailscale.com/health/healthmsg from tailscale.com/ipn/ipnlocal
|
tailscale.com/health/healthmsg from tailscale.com/ipn/ipnlocal
|
||||||
tailscale.com/hostinfo from tailscale.com/client/web+
|
tailscale.com/hostinfo from tailscale.com/client/web+
|
||||||
|
68
envknob/featureknob/featureknob.go
Normal file
68
envknob/featureknob/featureknob.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
// Package featureknob provides a facility to control whether features
|
||||||
|
// can run based on either an envknob or running OS / distro.
|
||||||
|
package featureknob
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"tailscale.com/envknob"
|
||||||
|
"tailscale.com/hostinfo"
|
||||||
|
"tailscale.com/version"
|
||||||
|
"tailscale.com/version/distro"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CanRunTailscaleSSH reports whether serving a Tailscale SSH server is
|
||||||
|
// supported for the current os/distro.
|
||||||
|
func CanRunTailscaleSSH() error {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "linux":
|
||||||
|
if distro.Get() == distro.Synology && !envknob.UseWIPCode() {
|
||||||
|
return errors.New("The Tailscale SSH server does not run on Synology.")
|
||||||
|
}
|
||||||
|
if distro.Get() == distro.QNAP && !envknob.UseWIPCode() {
|
||||||
|
return errors.New("The Tailscale SSH server does not run on QNAP.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setting SSH on Home Assistant causes trouble on startup
|
||||||
|
// (since the flag is not being passed to `tailscale up`).
|
||||||
|
// Although Tailscale SSH does work here,
|
||||||
|
// it's not terribly useful since it's running in a separate container.
|
||||||
|
if hostinfo.GetEnvType() == hostinfo.HomeAssistantAddOn {
|
||||||
|
return errors.New("The Tailscale SSH server does not run on HomeAssistant.")
|
||||||
|
}
|
||||||
|
// otherwise okay
|
||||||
|
case "darwin":
|
||||||
|
// okay only in tailscaled mode for now.
|
||||||
|
if version.IsSandboxedMacOS() {
|
||||||
|
return errors.New("The Tailscale SSH server does not run in sandboxed Tailscale GUI builds.")
|
||||||
|
}
|
||||||
|
case "freebsd", "openbsd":
|
||||||
|
default:
|
||||||
|
return errors.New("The Tailscale SSH server is not supported on " + runtime.GOOS)
|
||||||
|
}
|
||||||
|
if !envknob.CanSSHD() {
|
||||||
|
return errors.New("The Tailscale SSH server has been administratively disabled.")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CanUseExitNode reports whether using an exit node is supported for the
|
||||||
|
// current os/distro.
|
||||||
|
func CanUseExitNode() error {
|
||||||
|
switch dist := distro.Get(); dist {
|
||||||
|
case distro.Synology, // see https://github.com/tailscale/tailscale/issues/1995
|
||||||
|
distro.QNAP,
|
||||||
|
distro.Unraid:
|
||||||
|
return errors.New("Tailscale exit nodes cannot be used on " + string(dist))
|
||||||
|
}
|
||||||
|
|
||||||
|
if hostinfo.GetEnvType() == hostinfo.HomeAssistantAddOn {
|
||||||
|
return errors.New("Tailscale exit nodes cannot be used on HomeAssistant.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -1,39 +0,0 @@
|
|||||||
// Copyright (c) Tailscale Inc & AUTHORS
|
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
|
|
||||||
package envknob
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"tailscale.com/version"
|
|
||||||
"tailscale.com/version/distro"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CanRunTailscaleSSH reports whether serving a Tailscale SSH server is
|
|
||||||
// supported for the current os/distro.
|
|
||||||
func CanRunTailscaleSSH() error {
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "linux":
|
|
||||||
if distro.Get() == distro.Synology && !UseWIPCode() {
|
|
||||||
return errors.New("The Tailscale SSH server does not run on Synology.")
|
|
||||||
}
|
|
||||||
if distro.Get() == distro.QNAP && !UseWIPCode() {
|
|
||||||
return errors.New("The Tailscale SSH server does not run on QNAP.")
|
|
||||||
}
|
|
||||||
// otherwise okay
|
|
||||||
case "darwin":
|
|
||||||
// okay only in tailscaled mode for now.
|
|
||||||
if version.IsSandboxedMacOS() {
|
|
||||||
return errors.New("The Tailscale SSH server does not run in sandboxed Tailscale GUI builds.")
|
|
||||||
}
|
|
||||||
case "freebsd", "openbsd":
|
|
||||||
default:
|
|
||||||
return errors.New("The Tailscale SSH server is not supported on " + runtime.GOOS)
|
|
||||||
}
|
|
||||||
if !CanSSHD() {
|
|
||||||
return errors.New("The Tailscale SSH server has been administratively disabled.")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -51,6 +51,7 @@
|
|||||||
"tailscale.com/doctor/routetable"
|
"tailscale.com/doctor/routetable"
|
||||||
"tailscale.com/drive"
|
"tailscale.com/drive"
|
||||||
"tailscale.com/envknob"
|
"tailscale.com/envknob"
|
||||||
|
"tailscale.com/envknob/featureknob"
|
||||||
"tailscale.com/health"
|
"tailscale.com/health"
|
||||||
"tailscale.com/health/healthmsg"
|
"tailscale.com/health/healthmsg"
|
||||||
"tailscale.com/hostinfo"
|
"tailscale.com/hostinfo"
|
||||||
@ -3484,7 +3485,7 @@ func (b *LocalBackend) checkSSHPrefsLocked(p *ipn.Prefs) error {
|
|||||||
if !p.RunSSH {
|
if !p.RunSSH {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := envknob.CanRunTailscaleSSH(); err != nil {
|
if err := featureknob.CanRunTailscaleSSH(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if runtime.GOOS == "linux" {
|
if runtime.GOOS == "linux" {
|
||||||
@ -3565,6 +3566,10 @@ func updateExitNodeUsageWarning(p ipn.PrefsView, state *netmon.State, healthTrac
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *LocalBackend) checkExitNodePrefsLocked(p *ipn.Prefs) error {
|
func (b *LocalBackend) checkExitNodePrefsLocked(p *ipn.Prefs) error {
|
||||||
|
if err := featureknob.CanUseExitNode(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if (p.ExitNodeIP.IsValid() || p.ExitNodeID != "") && p.AdvertisesExitNode() {
|
if (p.ExitNodeIP.IsValid() || p.ExitNodeID != "") && p.AdvertisesExitNode() {
|
||||||
return errors.New("Cannot advertise an exit node and use an exit node at the same time.")
|
return errors.New("Cannot advertise an exit node and use an exit node at the same time.")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user