tnnlr

package module
v0.0.0-...-7d415a8 Latest Latest
Warning

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

Go to latest
Published: May 6, 2020 License: MIT Imports: 17 Imported by: 0

README

Tnnlr Build Status

Tnnlr is a simple utility to managing ssh tunnels. It is currently a very ugly work in progress, but it does help to do the following

  • keep ssh tunnels open
  • compose new tunnels using a helpful ui
  • reload a whole set of tunnels quickly

Tnnlr shells out to a local version of ssh instead of bundling in its own ssh utilities. This was done so that complex local ssh configurations are respected by default.

So if you find yourself commonly launching a set of the same tunnels to access admin apis and other utilies when working on a project, tnnlr may save you some time.

Usage

# Get the tool
$ go get github.com/turtlemonvh/tnnlr

# Install binary
$ ( cd $GOPATH/src/github.com/turtlemonvh/tnnlr && go install ./tnnlr )

# Create a config file with tunnels for this project
# You can also just start the server and create it through the UI
$ cat > $GOPATH/src/github.com/turtlemonvh/tnnlr/.tnnlr << EOF
[
    {
        "defaultUrl": "/", 
        "host": "52.33.93.76", 
        "localPort": 15673, 
        "name": "rabbitmq_dashboard", 
        "remotePort": 15672
    }, 
    {
        "defaultUrl": "/ui/", 
        "host": "53.34.92.76", 
        "localPort": 8503, 
        "name": "consul_dashboard", 
        "remotePort": 8500
    }
]
EOF

# Start up the web ui on localhost:8080
$ tnnlr

# Go to localhost:8080 and click the "Reload Tunnels from File" button.

# Check help docs for more information
$ go run tnnlr -h
APP:
cli

COMMAND:
tnnlr


AVAILABLE SUBCOMMANDS:
help : Print this help message

PARSING ORDER: (set values will override in this order)
CLI Flag > Environment

VARIABLES:
+-------------+---------+----------+-----------+----------------------------------------+
|    FLAG     | DEFAULT | REQUIRED | ENV NAME  |              DESCRIPTION               |
+-------------+---------+----------+-----------+----------------------------------------+
| --log-level | info    | No       | LOG_LEVEL | Logging levels. Options are:           |
|             |         |          |           | [panic,fatal,error,warning,info,debug] |
| --tunnels   | .tnnlr  | No       | TUNNELS   | Configuration file listing             |
|             |         |          |           | tunnels. This can be read from         |
|             |         |          |           | and written to via the web UI.         |
| --ssh-exec  | ssh     | No       | SSH_EXEC  | The executable to use                  |
|             |         |          |           | for ssh. Can be a full path or         |
|             |         |          |           | just a command name that works         |
|             |         |          |           | in your shell.                         |
| --port      |    8080 | No       | PORT      | The port to run the server on          |
|             |         |          |           | for the web UI.                        |
+-------------+---------+----------+-----------+----------------------------------------+


Authors:
Timothy Van Heest (timothy@ionic.com)

Web UI

It's not pretty but it works.

Alt text

Tips

SSH config

For your ssh config (~/.ssh/config), something like this works well. Note that StrictHostKeyChecking means you won't get any warning about conneting to new hosts.

Host *
  User myusername
  StrictHostKeyChecking no
  ServerAliveInterval 60

Depending on your network configuration, you may want to use the TCPKeepAlive setting as well.

Alternatives

There are many other ssh tunnel management tools that are more mature than this. I created my own for a mixture of these reasons

  • I wanted to be able to configure it programmatically from the output of other tools (e.g. inventory scripts). This is why the config is in json.
  • I wanted the tunnels to be project specific. Different projects have different configurations, and I may only be able to create the tunnel when I'm VPN'd to a specific network.
  • I wanted something that would repect my ssh config, which is pretty complex.
  • I mainly wanted this for connecting to dashboards for monitoring products (Kibana, Grafana, CheckMK), so I wanted to be able to include a default url that I could just click on to get to the dashboard I wanted to view.
  • I kept forgetting the sytax for creating an ssh tunnel, and I wanted to make sure the tool would have an option show that so I could run the tunnel directly (via ssh on the command line).
  • I wanted something that would work on multiple OSes (Mac, Windows, Linux).
  • I wanted a web UI. In addition to being easy to work with, this means I can use this same program to manage tunnels in a headless VM.

Some things that seem to be present in other tools that are missing here

  • SOCKS proxy
  • UN/PW authentication for a tunnel
  • A less ugly UI
  • Tunnels that are created automatically on startup

Sample of example tools (there are many more):

TODO

  • Options to let tunnels continue running on shutdown
  • Option for https default url
  • Option to load whole sets of tunnels at a time easily, via file select in browser
  • Option for un/pw auth for ssh connections (pub/priv key only right now)
  • Option for multiple named dashboard views for a single tunnel
  • Less ugly code
  • Less ugly UI
  • Command line interface
  • Make ls command do something useful
  • Move from dep to go modules

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Message

type Message struct {
	// contains filtered or unexported fields
}

Store messages for the user in between views FIXME: Add fields to improve UI

func (*Message) Mstring

func (m *Message) Mstring() string

func (*Message) Tstring

func (m *Message) Tstring() string

type Tnnlr

type Tnnlr struct {
	sync.Mutex
	Template         *template.Template
	SshExec          string // path to ssh executable
	LogLevel         string
	TunnelReloadFile string
	Port             int
	// contains filtered or unexported fields
}

Server

func (*Tnnlr) Add

func (t *Tnnlr) Add(c *gin.Context)

Add a new tunnel Accepts html form or json

func (*Tnnlr) AddMessage

func (t *Tnnlr) AddMessage(msg string)

Add a message to the queue If the channel is full, the message is logged and discarded

func (*Tnnlr) AddTunnel

func (t *Tnnlr) AddTunnel(tnnl Tunnel) error

Add a single tunnel Threadsafe

func (*Tnnlr) CleanBookkeepingDirs

func (t *Tnnlr) CleanBookkeepingDirs()

Background cleanup and management of jobs

TODO - check cmd and pid information directly to see if process is running instead of checking port - option to leave process running when tnnlr shuts down

func (*Tnnlr) HomepageView

func (t *Tnnlr) HomepageView(c *gin.Context)

func (*Tnnlr) Init

func (t *Tnnlr) Init()

func (*Tnnlr) KillAllTunnels

func (t *Tnnlr) KillAllTunnels()

Kill all active tunnels

func (*Tnnlr) Load

func (t *Tnnlr) Load() ([]Tunnel, error)

Load from disk

func (*Tnnlr) ManagedTunnels

func (t *Tnnlr) ManagedTunnels() map[string]bool

func (*Tnnlr) Reload

func (t *Tnnlr) Reload(c *gin.Context)

Reload from config file

func (*Tnnlr) ReloadOne

func (t *Tnnlr) ReloadOne(c *gin.Context)

Reload a single tunnel from disk

func (*Tnnlr) Remove

func (t *Tnnlr) Remove(c *gin.Context)

Stop and remove a single tunnel

func (*Tnnlr) RemoveTunnel

func (t *Tnnlr) RemoveTunnel(tnnlId string) error

Remove a single tunnel Threadsafe Logs errors stopping the process, but continues

func (*Tnnlr) Run

func (t *Tnnlr) Run()

func (*Tnnlr) Save

func (t *Tnnlr) Save(c *gin.Context)

Save set of tunnels to a file

func (*Tnnlr) ShowCommand

func (t *Tnnlr) ShowCommand(c *gin.Context)

func (*Tnnlr) ShowLogs

func (t *Tnnlr) ShowLogs(c *gin.Context)

type Tunnel

type Tunnel struct {
	Id         string `json:"id"`
	Name       string `form:"name" json:"name" binding:"required"`
	DefaultUrl string `form:"defaultUrl" json:"defaultUrl" binding:"required"`
	Host       string `form:"host" json:"host" binding:"required"`
	Username   string `form:"username" json:"userName"` // can be ""
	LocalPort  int32  `form:"localPort" json:"localPort" binding:"required"`
	RemotePort int32  `form:"remotePort" json:"remotePort" binding:"required"`
	Pid        int    `json:"pid"` // not set until after process starts
	// contains filtered or unexported fields
}

Tunnels

func (*Tunnel) IsAlive

func (t *Tunnel) IsAlive() bool

Check if process running the tunnel is alive FIXME: Seems to return true even if process has exited

func (*Tunnel) LogPath

func (t *Tunnel) LogPath() (string, error)

func (*Tunnel) PidPath

func (t *Tunnel) PidPath() (string, error)

func (*Tunnel) PortInUse

func (t *Tunnel) PortInUse() bool

func (*Tunnel) Run

func (t *Tunnel) Run(sshExec string) error

Run the cmd and set the active process

Writes process information into ~/.tnnl/proc/XXX.pid Writes log information into ~/.tnnl/log/XXX.log

func (*Tunnel) Stop

func (t *Tunnel) Stop() error

Stop the tunnel if already running

func (*Tunnel) Validate

func (t *Tunnel) Validate() error

FIXME: Check required fields

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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