Secure private tunnels as a service 🔐
Use Docker Compose to easily spin up a local Passage installation that you can use to try it out.
$ docker compose up
passage is a service for programmatically creating and managing SSH tunnels. The primary use case is to serve as a secure bridge between SaaS providers and services that need to be accessed within customer networks. Passage acts both as a management API, and as a daemon which maintains the tunnels themselves.
With Normal tunnels, Passage acts as an SSH client, opening an SSH connection to an internet-facing remote bastion server, then from there opening an upstream connection to a private service within the remote network.
With Reverse tunnels, Passage acts as an SSH server, allowing remote clients to forward a local port from a hidden server to a dedicated port on the Passage instance, therefore achieving a tunnel without requiring a remote bastion server to be exposed to inbound traffic from the internet.
- Postgres 11 or later
- A keystore to securely store and retrieve public and private keys.
- Passage supports Postgres or S3 (default is a table in the same Postgres database)
- Passage does not handle encryption of keys at rest.
Passage can read its configuration from disk (YAML or JSON), or from environment variables. Passage's config keys are paths in a configuration object, so the dot notation is used to indicate hierarchy.
To use environment variables, replace the dot with an underscore and prefix the variable with PASSAGE_
.
For example, tunnel.normal.ssh_user
becomes PASSAGE_TUNNEL_NORMAL_SSH_USER
.
The following are required config options that you must set to quickstart with Passage. A full configuration reference is available at docs/config.md.
Key | Description | Required | Alias |
---|---|---|---|
tunnel.bind.host | Bind host for internal tunnel ports. | True | 0.0.0.0 |
tunnel.reverse.host.key | Base64 encoded host key for the reverse tunnel SSH server. | True, if reverse enabled. | |
postgres.uri | Postgres connection string. | False | |
postgres.host | See PGHOST |
True | PGHOST |
postgres.port | See PGPORT |
True | PGPORT |
postgres.user | See PGUSER |
True | PGUSER |
postgres.pass | See PGPASS |
True | PGPASS |
postgres.dbname | See PGDBNAME |
True | PGDBNAME |
postgres.sslmode | See PGSSLMODE |
True | PGSSLMODE |
passage exposes parts of your private network to the Internet. Therefore, its important to secure the network that passage operates in.
Passage opens two kinds of ports on machines that it runs on: (1) tunnel ports, and (2) sshd
ports. Tunnel ports forward packets to the exposed, remote customer port (what your services will talk to).
sshd
ports are used for reverse tunnels. These ports host SSH servers that remote clients will connect to with their remote port forwarding requests. These ports need to be exposed to the public Internet.
An appropriate network configuration begins with Passage instances completely locked down. The following ingress openings should be made in your firewall:
- Expose tunnel ports to internal services
- Port range
49152 - 57343
- Port range
- Expose
sshd
ports to public internet- Port range
57344 - 65535
- Port range
- Of course, any other ingress you need (load balancers, internal tools, etc.)
Go unit tests can be run with make test
.
There is an end-to-end test of both Normal and Reverse tunnels, using Docker networks to simulate network isolation, and docker compose for orchestration, that can be run with make test-e2e
.