Jump host/Jump server without the jump, a.k.a Transparent SSH bastion
The original project is no longer being maintained. This fork includes important security fixes, some bugfixes and features but it is on MAINTENANCE mode and only security issues and major bugs will be fixed. You should consider using Teleport instead.
- Installation and usage
- Quick Start
- Features and limitations
- Backup / Restore
- Built-in shell
- Healthcheck
- Portal alias (.ssh/config)
- Under the hood
- Testing
Packaged installation (.deb
& .rpm
) is privileged as it comes with a hardened systemd service and a SELinux module if you have enfored SELinux on your GNU/Linux distribution.
Get the latest version here
Note : by default, your package manager will automatically install sqlite
(recommended dependency)
This installation will install sshportal as a systemd service, configure logrotate to keep 1 year of audit logs and add a systemd timer for session logs management. See packaging
.
If mariadb is selected during the install, it will also automatically create the sshportal
database if it doesn't exist.
Show Debian-based distributions instructions
apt install ./sshportal_x.x.x_xxx.deb
You will be asked if you want to use mariadb
instead of sqlite
(default). Make sure to install mariadb-server
before as the package is not listed as a hard dependency in the control file.
To install SSHportal with mariadb:
apt install --no-install-recommends -y mariadb-server
DEBIAN_FRONTEND=noninteractive SSHPORTAL_MARIADB_SETUP=true apt install --no-install-recommends -y mariadb-server ./sshportal_x.x.x_xxx.deb
If you want to stick with sqlite, you just have to do this:
DEBIAN_FRONTEND=noninteractive apt install -y ./sshportal_x.x.x_xxx.deb
Show RedHat-based distributions instructions
Make sure to install mariadb-server
before if you want to use it as this package is not listed as a hard dependency in the control file.
There is no debconf in RedHat distribution so if you want an automatic mariadb setup you need to install sshportal
with :
dnf install -y --setopt=install_weak_deps=False mariadb-server
SSHPORTAL_MARIADB_SETUP=true dnf install --setopt=install_weak_deps=False ./sshportal_x.x.x_xxx.rpm
If you want to stick with sqlite, you just have to do this:
dnf install -y ./sshportal_x.x.x_xxx.rpm
Docker instructions
An automated build is setup on the Github registry.
# Start a server in background
# mount `pwd` to persist the sqlite database file
docker run -p 2222:2222 -d --name=sshportal -v "$(pwd):$(pwd)" -w "$(pwd)" ghcr.io/alterway/sshportal:latest
# check logs (mandatory on first run to get the administrator invite token)
docker logs -f sshportal
- Get the invite token in stdout or
/var/log/sshportal/audit/audit.log
if installed from a package manager :
2023/09/01 15:03:18 info: system migrated
2023/09/01 15:03:18 info: 'sshportal' user created. Run 'ssh localhost -p 2222 -l invite:6tUguNFYxeOxdx0N' to associate your public key with this account
2023/09/01 15:03:18 info: SSH Server accepting connections on :2222, idle-timout=0s
- Make sure you have a ssh key pair and associate your public key to the bastion
ssh localhost -p 2222 -l invite:xxxxxxx
Welcome sshportal!
Your key is now associated with the user "sshportal@localhost".
- Your first user is the admin. To access to the console, connect like a normal server
ssh sshportal@localhost -p 2222
- Create your first host
config> host create bart@foo.example.org
1
config>
- List hosts
config> host ls
ID | NAME | URL | KEY | PASS | GROUPS | COMMENT
+----+------+-------------------------+---------+------+---------+---------+
1 | foo | bart@foo.example.org:22 | default | | default |
Total: 1 hosts.
config>
- Add the
host
key to the server
config> host ls
ID | NAME | URL | KEY | GROUPS | UPDATED | CREATED | COMMENT | HOP | LOGGING
-----+------+-----+-----+--------+---------+---------+---------+-----+----------
Total: 0 hosts.
config> key ls
ID | NAME | TYPE | LENGTH | HOSTS | UPDATED | CREATED | COMMENT
-----+---------+---------+--------+-------+--------------+--------------+-----------------------
2 | host | ed25519 | 1 | 0 | 1 minute ago | 1 minute ago | created by sshportal
1 | default | ed25519 | 1 | 0 | 1 minute ago | 1 minute ago | created by sshportal
ssh bart@foo.example.org "$(ssh sshportal@localhost -p 2222 key setup host)"
ssh bart@foo.example.org "$(ssh sshportal@localhost -p 2222 key setup host)"
- Profit
ssh localhost -p 2222 -l foo
bart@foo>
- Invite friends
This command doesn't create a user on the remote server, it only creates an account in the sshportal database.
config> user invite bob@example.com
User 2 created.
To associate this account with a key, use the following SSH user: 'invite:NfHK5a84jjJkwzDk'.
- Single autonomous binary (~20Mb) with no runtime dependencies (except glibc)
- Portable / Cross-platform (regularly tested on linux and OSX/darwin)
- Store data in Sqlite3 or MySQL
- Stateless -> horizontally scalable when using MySQL as the backend
- Connect to remote host using key or password
- Admin commands can be run directly or in an interactive shell
- Host management
- User management (invite, group, stats)
- Host Key management (create, remove, update, import)
- Automatic remote host key learning
- User Key management (multiple 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
) - Sensitive data encryption
- Session management (see active connections, history, stats, stop)
- Audit log (logging every user action)
- Record TTY Session (with ttyrec format, use
ttyplay
for replay) - Tunnels logging
- Host Keys verifications shared across users
- Healthcheck user (replying OK to any user)
- SSH compatibility
- ipv4 and ipv6 support
scp
supportrsync
supporttunneling
(local forward, remote forward, dynamic forward) supportsftp
supportssh-agent
supportX11 forwarding
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 support
(Known) limitations
- Does not work with
mosh
- It is not possible for a user to access a host with the same name as the user. This is easily circumvented by changing the user name, especially since the most common use cases does not expose it.
- It is not possible to access a host named
healthcheck
as this is a built-in command.
sshportal embeds built-in backup/restore methods which basically import/export JSON objects:
# Backup
ssh portal config backup > sshportal.bkp
# Restore
ssh portal config restore < sshportal.bkp
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:
# sqlite dump
sqlite3 sshportal.db .dump > sshportal.sql.bkp
# or just the immortal cp
cp sshportal.db sshportal.db.bkp
sshportal
embeds a configuration CLI.
By default, the configuration user is the user starting the server for the first time. It fallbacks to root
.
Each command can be run directly by using this syntax: ssh root@portal.example.org <command> [args]
:
ssh root@portal.example.org host inspect toto
You can enter in interactive mode using this syntax: ssh root@portal.example.org
See Documentation for the list of shell commands.
By default, sshportal
will return OK
to anyone sshing using the healthcheck
user without checking for authentication.
$ ssh healthcheck@localhost -p 2222
OK
the healtcheck
user can be changed using the healthcheck-user
option.
Alternatively, you can run the built-in healthcheck helper (requiring no ssh client nor ssh key):
Usage: sshportal healthcheck [--addr=host:port] [--wait] [--quiet]
$ sshportal healthcheck --addr=localhost:2222; echo $?
0
Wait for sshportal to be healthy, then connect
$ sshportal healthcheck --wait && ssh sshportal -l root
config>
Edit your ~/.ssh/config
file (create it first if needed)
Host portal
User root # or 'sshportal' if you use the packaged binary
User root # or 'sshportal' if you use the packaged sshportal
Port 2222 # portal port
HostName 127.0.0.1 # portal hostname
# you can now run a shell using this:
ssh portal
# instead of this:
ssh localhost -p 2222 -l root
# or connect to hosts using this:
ssh hostname@portal
# instead of this:
ssh localhost -p 2222 -l hostname
sshportal
is stateless but relies on a database to store configuration and logs.
By default, sshportal
uses a local sqlite database which isn't scalable by design.
You can run multiple instances of sshportal
sharing the same MySQL database, using sshportal --db-conn=user:pass@host/dbname?parseTime=true --db-driver=mysql
.
See examples/mysql.
- Docker first (used in dev, tests, by the CI and in production)
- Backed by (see dep graph):
- 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
- SSH
Install golangci-lint and run this in project root:
golangci-lint run
Perform integration tests
cd ./examples/integration && make
Perform unit tests
go test