hoopsnake

package module
v0.0.0-...-741eb71 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 20, 2024 License: Apache-2.0 Imports: 28 Imported by: 0

README

A not-featureful SSH server listening on your tailnet, for your initrd

If you live in the 2020, your Linux servers probably have encrypted storage. That means that if you reboot them, you have to provide a password before they can become useful to the world again. The usual way to do this is to include a dropbear SSH daemon in your init ram file system image, and run it before the init process gets started, so you have a chance to SSH in and provide the key material your encrypted drives need to unlock.

I do that too, but I really dislike the idea of having yet another highly-privileged network service that's written in a memory unsafe language listen on the public internet this early in the boot process. So here's a dropbear alternative: hoopsnake.

Docs

What you get

Hoopsnake can do the following:

  • Register a new "device" on your tailnet, like tsnsrv does
  • Start an SSH server (all in go) that listens on :22 on that tailnet device (so you can reach it, the internet can't!)
  • That does public key authentication (no user accounts, you just tell it what program to run) and it spawns whatever program you tell it to run, with the same privileges that hoopsnake runs on; it allocates a PTY if required (so interactive shells/busybox work).

...and that's mostly it.

What you don't get

  • No listening on the public internet. Tailscale (or tailscale with headscale if you like to self-host) is the easiest way to get a VPN that doesn't suck. Please give it a try.
  • No SSH extensions like scp/sftp. Too much trouble and I expect you'll only ssh in to type a command and immediately exit again.
  • No keyboard-interactive auth. Please use SSH keys. Secretive is great if you're on a mac.
  • No mitigation for initrd's storing the server's private keys and API tokens in plaintext (see threat model)
  • Hopefully no buffer overruns

How well does it work? Is it stable?

Uh, well. I just uploaded it to github. It seems to do a thing in my personal tests, but should you make the bootability of your machines depend on it? I don't advise that yet.

Is it secure? I'm pretty hopeful that I got the auth portion right, and if not - it'll only listen on a network you alone control (the tailnet). Ideally that doesn't have that many threat actors? In any case, reach me on Signal if you need to report a security issue.

What's with the name?

A dropbear is an Australian mythical animal that Australians will insist is totally real, I swear to you, please be afraid.

A hoop snake is an Australian mythical animal that Australians will insist is totally real, I swear to you, please be afraid.

To demonstrate how committed I was to the "Australians insisting something is real" bit, check out the git history where this tool started out being named "spidereffer"; let's all be glad that this isn't called that anymore.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrMissingACLTag = fmt.Errorf("service must have at least one ACL tag")
View Source
var ErrMissingCommand = fmt.Errorf("ssh connections must run a command - pass that as the remaining cli arguments")
View Source
var ErrMissingOauthCredential = fmt.Errorf("either none or both of -clientIdFile and -clientSecretFile must be passed")
View Source
var ErrMissingServiceName = fmt.Errorf("service name must be set via -name")
View Source
var ErrNoAPIKeys = fmt.Errorf("neither TS_API_KEY, nor TS_API_CLIENT_ID and TS_API_CLIENT_SECRET are set")

Functions

This section is empty.

Types

type TailnetSSH

type TailnetSSH struct {
	ssh.Server
	// contains filtered or unexported fields
}

TailnetSSH defines an SSH service that listens on a tailnet and runs a given shell program.

The zero value of TailnetSSH is not a valid instance. Use TailnetSSHFromArgs to construct a valid one.

func TailnetSSHFromArgs

func TailnetSSHFromArgs(args []string) (*TailnetSSH, error)

/ TailnetSSHFromArgs parses CLI arguments and constructs a validated TailnetSSH structure.

func (*TailnetSSH) Run

func (s *TailnetSSH) Run(ctx context.Context) error

Run starts listening for connections and runs, in perpetuity.

If Run returns an error, that means it can no longer listen - these errors are fatal.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL