# Tunneled SSH Connections

Pomerium now supports [**Native SSH Access**](https://www.pomerium.com/docs/capabilities/native-ssh-access.md) with OAuth authentication and ephemeral certificates. This provides a more streamlined SSH experience without requiring tunneling or special clients. See the [comparison table](#native-vs-tunneled-ssh) 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.

This example assumes you've already [created a TCP route](https://www.pomerium.com/docs/capabilities/non-http/tcp.md#configure-tcp-routes) for this service.

If clients can only reach outbound port 443 or Pomerium sits behind an L4 edge, see [SSH over port 443 through an L4 edge](https://www.pomerium.com/docs/guides/ssh-tcp-l4-passthrough.md).

## Basic Connection

1. Create a TCP tunnel, using either [`pomerium-cli`](https://www.pomerium.com/docs/deploy/clients.md) or the Pomerium Desktop client:

**pomerium-cli:**

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

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.

**Pomerium Desktop:**

\[An example connection to an SSH service from Pomerium Desktop]

The **Local Address** field is optional. Using it defines what port the tunnel listens on locally. If not specified, Pomerium Desktop will choose a random available port.

1. Initiate your SSH connection, pointing to `localhost`:

   ```bash
   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:

```bash
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:

```bash
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:

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

## More Resources

### Native vs Tunneled SSH

| Feature | Native SSH Access | Tunneled SSH (this guide) |
|---------|------------------|---------------------------|
| **Client setup** | None required | Requires pomerium-cli |
| **Network architecture** | Direct SSH connection | HTTP tunnel over CONNECT |
| **SSH features** | Full SSH functionality | Full SSH functionality |
| **Performance** | Native SSH performance | Slight tunnel overhead |
| **Firewall requirements** | Standard SSH (port 22 or custom) | HTTP/HTTPS (ports 80/443) |
| **Authentication** | OAuth | OAuth |
| **Authorization** | Pomerium Policy with SSH rules | Pomerium Policy with HTTP rules |
| **Key management** | Ephemeral certificates | Traditional SSH keys |
| **Audit logging** | SSH protocol logging | Pomerium HTTP tunnel logs |
| **Server configuration** | Requires User CA trust | Standard 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:

- [ProxyCommand (SSH man page)](https://man.openbsd.org/ssh_config.5#ProxyCommand)
- [SSH to remote hosts though a proxy or bastion with ProxyJump (RedHat blog)](https://www.redhat.com/sysadmin/ssh-proxy-bastion-proxyjump)
