sshportal/README.md

418 lines
13 KiB
Markdown
Raw Normal View History

2017-11-13 18:11:41 +08:00
# sshportal
2017-12-04 17:39:40 +08:00
[![CircleCI](https://circleci.com/gh/moul/sshportal.svg?style=svg)](https://circleci.com/gh/moul/sshportal)
2017-12-04 23:33:41 +08:00
[![Docker Build Status](https://img.shields.io/docker/build/moul/sshportal.svg)](https://hub.docker.com/r/moul/sshportal/)
[![Go Report Card](https://goreportcard.com/badge/github.com/moul/sshportal)](https://goreportcard.com/report/github.com/moul/sshportal)
2017-12-04 23:33:41 +08:00
[![GoDoc](https://godoc.org/github.com/moul/sshportal?status.svg)](https://godoc.org/github.com/moul/sshportal)
[![License](https://img.shields.io/github/license/moul/sshportal.svg)](https://github.com/moul/sshportal/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/moul/sshportal.svg)](https://github.com/moul/sshportal/releases)
2017-12-16 16:56:09 +08:00
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fmoul%2Fsshportal.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fmoul%2Fsshportal?ref=badge_shield)
2017-12-04 17:39:40 +08:00
2017-11-13 18:11:41 +08:00
Jump host/Jump server without the jump, a.k.a Transparent SSH bastion
2017-12-12 16:33:44 +08:00
![sshportal demo](https://github.com/moul/sshportal/raw/master/.assets/demo.gif)
---
2017-12-16 02:48:47 +08:00
## Overview
![sshportal overview](https://raw.github.com/moul/sshportal/master/.assets/overview.svg?sanitize=true)
2017-11-13 18:11:41 +08:00
## Features
2017-12-13 18:25:21 +08:00
* Single autonomous binary (~10-20Mb) with no runtime dependencies (embeds ssh server and client)
* Portable / Cross-platform (regularly tested on linux and OSX/darwin)
2017-12-16 02:48:47 +08:00
* Store data in [Sqlite3](https://www.sqlite.org/) or [MySQL](https://www.mysql.com) (probably easy to add postgres, mssql thanks to gorm)
* Stateless -> horizontally scalable when using [MySQL](https://www.mysql.com) as the backend
2017-12-13 18:25:21 +08:00
* Connect to remote host using key or password
2017-11-13 18:18:19 +08:00
* Admin commands can be run directly or in an interactive shell
2017-12-13 18:25:21 +08:00
* Host management
* User management (invite, group, stats)
2018-04-03 04:28:10 +08:00
* Host Key management (create, remove, update, import)
* Automatic remote host key learning
2017-12-13 18:25:21 +08:00
* User Key management (multile keys per user)
* ACL management (acl+user-groups+host-groups)
* User roles (admin, trusted, standard, ...)
* User invitations (no more "give me your public ssh key please")
* Easy server installation (generate shell command to setup `authorized_keys`)
2017-11-24 21:29:41 +08:00
* Sensitive data encryption
2017-12-13 18:25:21 +08:00
* Session management (see active connections, history, stats, stop)
* Audit log (logging every user action)
2018-01-05 18:02:13 +08:00
* Record TTY Session
2018-04-03 04:28:10 +08:00
* Tunnels logging
2017-12-02 05:17:44 +08:00
* Host Keys verifications shared across users
2017-12-13 18:25:21 +08:00
* Healthcheck user (replying OK to any user)
2018-01-04 20:29:10 +08:00
* SSH compatibility
* ipv4 and ipv6 support
* [`scp`](https://linux.die.net/man/1/scp) support
* [`rsync`](https://linux.die.net/man/1/rsync) support
* [tunneling](https://www.ssh.com/ssh/tunneling/example) (local forward, remote forward, dynamic forward) support
* [`sftp`](https://www.ssh.com/ssh/sftp/) support
* [`ssh-agent`](https://www.ssh.com/ssh/agent) support
* [`X11 forwarding`](http://en.tldp.org/HOWTO/XDMCP-HOWTO/ssh.html) support
* Git support (can be used to easily use multiple user keys on GitHub, or access your own firewalled gitlab server)
* Do not require any SSH client modification or custom `.ssh/config`, works with every tested SSH programming libraries and every tested SSH clients
* SSH to non-SSH proxy
* [Telnet](https://www.ssh.com/ssh/telnet) support
## (Known) limitations
* Does not work (yet?) with [`mosh`](https://mosh.org/)
2017-11-13 18:11:41 +08:00
## Usage
Start the server
```console
2018-01-01 17:41:21 +08:00
$ sshportal server
2017-11-13 18:11:41 +08:00
2017/11/13 10:58:35 Admin user created, use the user 'invite:BpLnfgDsc2WD8F2q' to associate a public key with this account
2017/11/13 10:58:35 SSH Server accepting connections on :2222
```
Link your SSH key with the admin account
```console
$ ssh localhost -p 2222 -l invite:BpLnfgDsc2WD8F2q
2017-11-29 16:17:19 +08:00
Welcome admin!
2017-11-13 18:11:41 +08:00
Your key is now associated with the user "admin@sshportal".
Shared connection to localhost closed.
$
```
Drop an interactive administrator shell
```console
ssh localhost -p 2222 -l admin
__________ _____ __ __
/ __/ __/ // / _ \___ ____/ /____ _/ /
_\ \_\ \/ _ / ___/ _ \/ __/ __/ _ '/ /
/___/___/_//_/_/ \___/_/ \__/\_,_/_/
config>
```
Create your first host
```console
config> host create bart@foo.example.org
1
config>
```
List hosts
```console
config> host ls
ID | NAME | URL | KEY | PASS | GROUPS | COMMENT
+----+------+-------------------------+---------+------+---------+---------+
1 | foo | bart@foo.example.org:22 | default | | default |
2017-11-13 18:11:41 +08:00
Total: 1 hosts.
config>
```
Add the key to the server
2017-11-13 18:11:41 +08:00
```console
$ ssh bart@foo.example.org "$(ssh localhost -p 2222 -l admin key setup default)"
$
2017-11-13 18:11:41 +08:00
```
Profit
```console
ssh localhost -p 2222 -l foo
bart@foo>
```
2017-11-13 18:18:19 +08:00
Invite friends
2017-12-13 18:25:21 +08:00
*This command doesn't create a user on the remote server, it only creates an account in the sshportal database.*
2017-11-13 18:18:19 +08:00
```console
config> user invite bob@example.com
User 2 created.
2017-12-13 18:25:21 +08:00
To associate this account with a key, use the following SSH user: 'invite:NfHK5a84jjJkwzDk'.
2017-11-13 18:18:19 +08:00
config>
```
2017-12-17 17:08:44 +08:00
## Flow Diagram
![Flow Diagram](https://raw.github.com/moul/sshportal/master/.assets/flow-diagram.svg?sanitize=true)
## built-in shell
2017-11-13 19:21:26 +08:00
`sshportal` embeds a configuration CLI.
2017-11-13 19:21:26 +08:00
By default, the configuration user is `admin`, (can be changed using `--config-user=<value>` when starting the server.
Each commands can be run directly by using this syntax: `ssh admin@portal.example.org <command> [args]`:
```
ssh admin@portal.example.org host inspect toto
```
You can enter in interactive mode using this syntax: `ssh admin@portal.example.org`
### Synopsis
```sh
# acl management
acl help
2017-11-23 17:35:51 +08:00
acl create [-h] [--hostgroup=HOSTGROUP...] [--usergroup=USERGROUP...] [--pattern=<value>] [--comment=<value>] [--action=<value>] [--weight=value]
acl inspect [-h] ACL...
acl ls [-h] [--latest] [--quiet]
2017-11-23 17:35:51 +08:00
acl rm [-h] ACL...
2017-11-23 19:01:17 +08:00
acl update [-h] [--comment=<value>] [--action=<value>] [--weight=<value>] [--assign-hostgroup=HOSTGROUP...] [--unassign-hostgroup=HOSTGROUP...] [--assign-usergroup=USERGROUP...] [--unassign-usergroup=USERGROUP...] ACL...
2017-11-13 19:21:26 +08:00
2017-11-14 03:22:45 +08:00
# config management
config help
2017-11-24 21:29:41 +08:00
config backup [-h] [--indent] [--decrypt]
config restore [-h] [--confirm] [--decrypt]
2017-11-14 03:22:45 +08:00
2017-11-29 16:17:19 +08:00
# event management
event help
event ls [-h] [--latest] [--quiet]
2017-11-29 16:17:19 +08:00
event inspect [-h] EVENT...
2017-11-13 19:21:26 +08:00
# host management
host help
2018-03-01 00:22:59 +08:00
host create [-h] [--name=<value>] [--password=<value>] [--comment=<value>] [--key=KEY] [--group=HOSTGROUP...] [--hop=HOST] <username>[:<password>]@<host>[:<port>]
2017-11-24 21:29:41 +08:00
host inspect [-h] [--decrypt] HOST...
host ls [-h] [--latest] [--quiet]
2017-11-23 17:35:51 +08:00
host rm [-h] HOST...
2018-03-01 00:22:59 +08:00
host update [-h] [--name=<value>] [--comment=<value>] [--key=KEY] [--assign-group=HOSTGROUP...] [--unassign-group=HOSTGROUP...] [--set-hop=HOST] [--unset-hop] HOST...
2017-11-13 19:21:26 +08:00
# hostgroup management
hostgroup help
hostgroup create [-h] [--name=<value>] [--comment=<value>]
2017-11-23 17:35:51 +08:00
hostgroup inspect [-h] HOSTGROUP...
hostgroup ls [-h] [--latest] [--quiet]
2017-11-23 17:35:51 +08:00
hostgroup rm [-h] HOSTGROUP...
2017-11-13 19:21:26 +08:00
# key management
key help
key create [-h] [--name=<value>] [--type=<value>] [--length=<value>] [--comment=<value>]
key import [-h] [--name=<value>] [--comment=<value>]
2017-11-24 21:29:41 +08:00
key inspect [-h] [--decrypt] KEY...
key ls [-h] [--latest] [--quiet]
2017-11-23 17:35:51 +08:00
key rm [-h] KEY...
key setup [-h] KEY
2017-12-06 07:26:58 +08:00
key show [-h] KEY
2017-11-13 19:21:26 +08:00
2017-11-29 16:17:19 +08:00
# session management
session help
session ls [-h] [--latest] [--quiet]
2017-11-29 16:17:19 +08:00
session inspect [-h] SESSION...
2017-11-13 19:21:26 +08:00
# user management
user help
2017-11-23 17:35:51 +08:00
user invite [-h] [--name=<value>] [--comment=<value>] [--group=USERGROUP...] <email>
user inspect [-h] USER...
user ls [-h] [--latest] [--quiet]
2017-11-23 17:35:51 +08:00
user rm [-h] USER...
2017-11-23 18:36:24 +08:00
user update [-h] [--name=<value>] [--email=<value>] [--set-admin] [--unset-admin] [--assign-group=USERGROUP...] [--unassign-group=USERGROUP...] USER...
2017-11-13 19:21:26 +08:00
# usergroup management
usergroup help
hostgroup create [-h] [--name=<value>] [--comment=<value>]
2017-11-23 17:35:51 +08:00
usergroup inspect [-h] USERGROUP...
usergroup ls [-h] [--latest] [--quiet]
2017-11-23 17:35:51 +08:00
usergroup rm [-h] USERGROUP...
2017-11-13 19:21:26 +08:00
# other
2017-11-14 03:08:12 +08:00
exit [-h]
2017-11-13 19:21:26 +08:00
help, h
info [-h]
version [-h]
```
2017-11-14 07:27:12 +08:00
## Docker
2017-11-13 18:11:41 +08:00
2017-11-14 17:12:25 +08:00
Docker is the recommended way to run sshportal.
2017-11-14 07:27:12 +08:00
An [automated build is setup on the Docker Hub](https://hub.docker.com/r/moul/sshportal/tags/).
```console
# Start a server in background
# mount `pwd` to persist the sqlite database file
2018-01-03 07:26:38 +08:00
docker run -p 2222:2222 -d --name=sshportal -v "$(pwd):$(pwd)" -w "$(pwd)" moul/sshportal:v1.7.1
2017-11-14 17:12:25 +08:00
# check logs (mandatory on first run to get the administrator invite token)
docker logs -f sshportal
```
The easier way to upgrade sshportal is to do the following:
```sh
2018-01-03 07:26:38 +08:00
# we consider you were using an old version and you want to use the new version v1.7.1
2017-11-14 17:12:25 +08:00
# stop and rename the last working container + backup the database
docker stop sshportal
docker rename sshportal sshportal_old
cp sshportal.db sshportal.db.bkp
# run the new version
2018-01-03 07:26:38 +08:00
docker run -p 2222:2222 -d --name=sshportal -v "$(pwd):$(pwd)" -w "$(pwd)" moul/sshportal:v1.7.1
2017-11-14 17:12:25 +08:00
# check the logs for migration or cross-version incompabitility errors
docker logs -f sshportal
```
Now you can test ssh-ing to sshportal to check if everything looks OK.
In case of problem, you can rollback to the latest working version with the latest working backup, using:
```sh
docker stop sshportal
docker rm sshportal
cp sshportal.db.bkp sshportal.db
docker rename sshportal_old sshportal
docker start sshportal
docker logs -f sshportal
2017-11-14 07:27:12 +08:00
```
## Manual Install
Get the latest version using GO.
2017-11-13 18:11:41 +08:00
```sh
go get -u github.com/moul/sshportal
```
2017-11-14 07:21:19 +08:00
## portal alias (.ssh/config)
Edit your `~/.ssh/config` file (create it first if needed)
```ini
Host portal
User admin
Port 2222 # portal port
HostName 127.0.0.1 # portal hostname
```
```bash
# you can now run a shell using this:
ssh portal
# instead of this:
ssh localhost -p 2222 -l admin
# or connect to hosts using this:
ssh hostname@portal
# instead of this:
ssh localhost -p 2222 -l hostname
```
2017-11-14 07:21:19 +08:00
## Backup / Restore
sshportal embeds built-in backup/restore methods which basically import/export JSON objects:
```sh
# Backup
ssh portal config backup > sshportal.bkp
2017-11-14 07:21:19 +08:00
# Restore
ssh portal config restore < sshportal.bkp
2017-11-14 07:21:19 +08:00
```
This method is particularly useful as it should be resistant against future DB schema changes (expected during development phase).
I suggest you to be careful during this development phase, and use an additional backup method, for example:
```sh
# sqlite dump
sqlite3 sshportal.db .dump > sshportal.sql.bkp
# or just the immortal cp
cp sshportal.db sshportal.db.bkp
```
## Demo data
The following servers are freely available, without external registration,
it makes it easier to quickly test `sshportal` without configuring your own servers to accept sshportal connections.
```
ssh portal host create new@sdf.org
ssh sdf@portal
ssh portal host create test@whoami.filippo.io
ssh whoami@portal
ssh portal host create test@chat.shazow.net
ssh chat@portal
```
2017-12-04 16:34:52 +08:00
## Healthcheck
By default, `sshportal` will return `OK` to anyone sshing using the `healthcheck` user without checking for authentication.
```console
$ ssh healthcheck@sshportal
OK
$
```
the `healtcheck` user can be changed using the `healthcheck-user` option.
2017-12-12 21:55:50 +08:00
2018-01-01 17:41:21 +08:00
---
Alternatively, you can run the built-in healthcheck helper (requiring no ssh client nor ssh key):
Usage: `sshportal healthcheck [--addr=host:port] [--wait] [--quiet]
2018-01-01 17:41:21 +08:00
```console
$ sshportal healthcheck --addr=localhost:2222; echo $?
$ 0
```
---
Wait for sshportal to be healthy, then connect
```console
$ sshportal healthcheck --wait && ssh sshportal -l admin
config>
```
2017-12-16 02:48:47 +08:00
## Scaling
`sshportal` is stateless but relies on a database to store configuration and logs.
By default, `sshportal` uses a local [sqlite](https://www.sqlite.org/) database which isn't scalable by design.
You can run multiple instances of `sshportal` sharing a same [MySQL](https://www.mysql.com) database, using `sshportal --db-conn=user:pass@host/dbname?parseTime=true --db-driver=mysql`.
![sshportal cluster with MySQL backend](https://raw.github.com/moul/sshportal/master/.assets/cluster-mysql.svg?sanitize=true)
See [examples/mysql](http://github.com/moul/sshportal/tree/master/examples/mysql).
2017-12-13 18:25:21 +08:00
## Under the hood
* Docker first (used in dev, tests, by the CI and in production)
* Backed by (see [dep graph](https://godoc.org/github.com/moul/sshportal?import-graph&hide=2)):
* SSH
* https://github.com/gliderlabs/ssh: SSH server made easy (well-designed golang library to build SSH servers)
* https://godoc.org/golang.org/x/crypto/ssh: both client and server SSH protocol and helpers
* Database
* https://github.com/jinzhu/gorm/: SQL orm
* https://github.com/go-gormigrate/gormigrate: Database migration system
* Built-in shell
* https://github.com/olekukonko/tablewriter: Ascii tables
* https://github.com/asaskevich/govalidator: Valide user inputs
* https://github.com/dustin/go-humanize: Human-friendly representation of technical data (time ago, bytes, ...)
* https://github.com/mgutz/ansi: Terminal color helpers
* https://github.com/urfave/cli: CLI flag parsing with subcommands support
2017-12-16 02:48:47 +08:00
![sshportal data model](https://raw.github.com/moul/sshportal/master/.assets/sql-schema.svg?sanitize=true)
2017-12-14 00:15:43 +08:00
2017-12-13 18:25:21 +08:00
## Note
2017-12-12 21:55:50 +08:00
This is totally experimental for now, so please file issues to let me know what you think about it!
2017-12-16 16:56:09 +08:00
## License
2018-01-01 17:41:21 +08:00
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fmoul%2Fsshportal.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fmoul%2Fsshportal?ref=badge_large)