diff --git a/envknob/envknob.go b/envknob/envknob.go index 502940e59..aa11763cc 100644 --- a/envknob/envknob.go +++ b/envknob/envknob.go @@ -149,3 +149,9 @@ func UseWIPCode() bool { return Bool("TAILSCALE_USE_WIP_CODE") } // if already enabled and any attempt to re-enable it will result in // an error. func CanSSHD() bool { return !Bool("TS_DISABLE_SSH_SERVER") } + +// SSHPolicyFile returns the path, if any, to the SSHPolicy JSON file for development. +func SSHPolicyFile() string { return String("TS_DEBUG_SSH_POLICY_FILE") } + +// SSHIgnoreTailnetPolicy is whether to ignore the Tailnet SSH policy for development. +func SSHIgnoreTailnetPolicy() bool { return Bool("TS_DEBUG_SSH_IGNORE_TAILNET_POLICY") } diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 6ebc55b07..cbaa89c3c 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -1808,6 +1808,10 @@ func (b *LocalBackend) checkPrefsLocked(p *ipn.Prefs) error { if !canSSH { return errors.New("The Tailscale SSH server has been administratively disabled.") } + if b.netMap != nil && b.netMap.SSHPolicy == nil && + envknob.SSHPolicyFile() == "" && !envknob.SSHIgnoreTailnetPolicy() { + return errors.New("Unable to enable local Tailscale SSH server; not enabled/configured on Tailnet.") + } } return nil } diff --git a/ssh/tailssh/tailssh.go b/ssh/tailssh/tailssh.go index cffd7016b..212cac17d 100644 --- a/ssh/tailssh/tailssh.go +++ b/ssh/tailssh/tailssh.go @@ -43,8 +43,8 @@ ) var ( - debugPolicyFile = envknob.String("TS_DEBUG_SSH_POLICY_FILE") - debugIgnoreTailnetSSHPolicy = envknob.Bool("TS_DEBUG_SSH_IGNORE_TAILNET_POLICY") + debugPolicyFile = envknob.SSHPolicyFile() + debugIgnoreTailnetSSHPolicy = envknob.SSHIgnoreTailnetPolicy() sshVerboseLogging = envknob.Bool("TS_DEBUG_SSH_VLOG") )