Skip to main content
Version: vNext (upcoming release)

Tunneled SSH Connections

Native SSH Access Available

Pomerium now supports Native SSH Access with OAuth authentication and ephemeral certificates. This provides a more streamlined SSH experience without requiring tunneling or special clients. See the comparison table below to choose the best approach for your use case.

Bad actors are constantly scanning the internet for exposed SSH services. Changing the default port obfuscates, but doesn't protect the service, and implementing and updating advanced SSH authentication can be cumbersome.

By tunneling SSH connections through your Pomerium service:

  • All traffic is encrypted twice (once by the Pomerium TCP connection, once by SSH itself),
  • The SSH service can remain closed to the internet, or even restricted to only accept connections from the Pomerium Proxy service
  • Authentication and authorization is managed by Pomerium, using your IdP for identity, and can be easily managed at scale.
Long-lived connections behavior

When you create a TCP or Websocket connection, Pomerium validates the access policy at the time the connection is made.

Currently, there is no mechanism in place to terminate long-running connections if a policy becomes invalid.

tip

This example assumes you've already created a TCP route for this service.

Basic Connection

  1. Create a TCP tunnel, using either pomerium-cli or the Pomerium Desktop client:

    pomerium-cli tcp aService.corp.example.com:22 --listen :2202
    --listen

    The --listen flag is optional. It lets you define what port the tunnel listens on locally. If not specified, the client will choose a random available port.

  2. Initiate your SSH connection, pointing to localhost:

    ssh user@localhost -p 2202

Tunnel and Connect Simultaneously

The process outlined above requires multiple steps and terminal environments (when using the CLI) or programs (when using the Desktop Client). By invoking pomerium-cli when the connection is made, you can streamline the process into a single connection:

ssh -o ProxyCommand='pomerium-cli tcp --listen - %h:%p' ssh.localhost.pomerium.io

Always Tunnel through Pomerium

Once your SSH service is configured and tested through Pomerium, you can edit your local SSH configuration file to always create a tunnel when connecting to that service:

Host aService.corp.example.com
ProxyCommand /usr/bin/pomerium-cli tcp --listen - %h:%p

You can even configure all SSH connections to your domain space to use the tunnel:

Host *.corp.example.com
ProxyCommand /usr/bin/pomerium-cli tcp --listen - %h:%p

More Resources

Native vs Tunneled SSH

FeatureNative SSH AccessTunneled SSH (this guide)
Client setupNone requiredRequires pomerium-cli
Network architectureDirect SSH connectionHTTP tunnel over CONNECT
SSH featuresFull SSH functionalityFull SSH functionality
PerformanceNative SSH performanceSlight tunnel overhead
Firewall requirementsStandard SSH (port 22 or custom)HTTP/HTTPS (ports 80/443)
AuthenticationOAuthOAuth
AuthorizationPomerium Policy with SSH rulesPomerium Policy with HTTP rules
Key managementEphemeral certificatesTraditional SSH keys
Audit loggingSSH protocol loggingPomerium HTTP tunnel logs
Server configurationRequires User CA trustStandard SSH configuration

When to use Native SSH Access:

  • You want the simplest user experience
  • You want centralized SSH access management and audit logging
  • You prefer ephemeral credentials over static keys

When to use Tunneled SSH:

  • You cannot modify SSH server configuration
  • You're migrating gradually from existing SSH setups

ProxyCommand Resources

For more information on SSH ProxyCommand, see:

Feedback