Deployment guide

SSHPiper

Overview

SSHPiper is a reverse proxy for sshd: a single static Go binary (sshpiperd) that presents one SSH entry point and routes each incoming connection to an upstream SSH host based on the login username, using a pluggable router. Acting as a bastion, it centralizes access to a fleet of backend servers behind one gateway, with per-user mapping and no agent or change required on the upstream hosts.

This SecureAnyCloud image deploys SSHPiper on Ubuntu 24.04 on Azure. It ships with zero keys and zero credentials. On the first boot of every VM, it generates the SSHPiper host key, an upstream key pair and a demo client key pair, and it stands up a working demo pipe so you can see the routing immediately. The demo pipe routes the downstream user demo (authenticated with the per-VM demo client key) to the upstream account demobackend on the local SSH server, using a per-VM key that SSHPiper holds.

The gateway details and the path to the demo client key are written to /root/sshpiper-credentials.txt (mode 0600, root-only). No shared secret and no default login ever ships inside the image.

What you get:

  • SSHPiper (sshpiperd) pinned to a specific release and verified by SHA-256 at build time, run as the unprivileged sshpiper system user. The exact version and checksum are recorded in /opt/sshpiper/VERSION.
  • sshpiperd running under systemd in a hardened unit (NoNewPrivileges, ProtectSystem=strict, PrivateTmp) with the sshpiper service account
  • The SSH reverse proxy gateway on port 2222, routing each connection to an upstream host by login username via the yaml router
  • The system OpenSSH server on port 22 for administration, unchanged
  • A working demo pipe generated on first boot (demo -> demobackend@127.0.0.1:22) that proves the proxy routes and remaps the username, ready to be replaced with your own pipes
  • Every key generated uniquely per VM on first boot: the SSHPiper host key, the upstream key pair and the demo client key, with nothing secret baked into the image
  • Per-VM gateway details and demo client key path in /root/sshpiper-credentials.txt (0600), with no shared secret and no default login
  • Ubuntu 24.04 LTS base with the latest security patches applied at build time
  • Azure Linux Agent for cloud integration and SSH key injection
  • 24/7 SecureAnyCloud support with a 24-hour response SLA

Prerequisites

Before you deploy, make sure you have:

  • An active Azure subscription, an SSH public key, and a VNet with a subnet in the target region
  • A subscription to the SSHPiper listing on Azure Marketplace
  • One or more upstream SSH servers that you want to route connections to. The image ships with a local demo upstream, so you can try it immediately.

Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) is ample for a gateway that proxies many concurrent SSH sessions. Larger fleets can use Standard_D2s_v5 or larger. SSHPiper relays SSH sessions only, and it holds no data plane state.

1

Deploy from the Azure portal

Search Azure Marketplace for SSHPiper, select the SecureAnyCloud publisher and click Create. Configure the network security group (NSG) to allow TCP 22 (administration) and TCP 2222 (the SSH gateway) from the networks your users connect from.

2

Deploy from the Azure CLI

Accept the Marketplace terms once per subscription, create the VM and open ports 22 and 2222:

RG="sshpiper-prod"; LOCATION="eastus"; VM_NAME="sshpiper-01" IMAGE_URN="sac1647283583153:sshpiper-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION"
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:sshpiper-ubuntu-24-04:default:latest
az vm create \
  --resource-group "$RG" --name "$VM_NAME" \
  --image "$IMAGE_URN" \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values "$SSH_KEY" \
  --public-ip-sku Standard
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 22 --priority 1001
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 2222 --priority 1002
3

Confirm the gateway is running

Connect over SSH on port 22 as azureuser for administration. The SSHPiper gateway runs as the sshpiper service and listens on port 2222. The system SSH server continues to listen on port 22.

sudo systemctl status sshpiper --no-pager | head -14 ss -tln | grep -E ':2222|:22 '

The output shows sshpiper.service active (running), the gateway listening on :2222 and the system SSH server on :22.

4

Retrieve the per-VM gateway details

First boot generates the gateway details, the demo pipe mapping and the path to the per-VM demo client key, and stores them in a root-only file. Read the file over SSH:

sudo cat /root/sshpiper-credentials.txt

The file records the gateway host and port, the demo downstream username (demo), the upstream account it maps to (demobackend) and the path to the per-VM demo client private key (/root/sshpiper-demo-key). The active routing rule lives in the yaml router config:

sudo cat /etc/sshpiper/sshpiperd.yaml
5

Try the demo pipe (a real proxied SSH hop)

The demo pipe proves the reverse proxy end to end. Connect to the gateway on port 2222 as the downstream user demo, authenticated with the per-VM demo client key. The session is routed to the upstream account demobackend on the local SSH server. whoami on the far side therefore returns demobackend, not demo, because SSHPiper remapped the username and connected to the upstream on your behalf:

sudo ssh -p 2222 -i /root/sshpiper-demo-key \
  -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
  demo@127.0.0.1 whoami

The gateway rejects an unmapped username because it has no pipe:

sudo ssh -p 2222 -i /root/sshpiper-demo-key \
  -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
  -o ConnectTimeout=10 nosuchpipe@127.0.0.1 whoami 2>&1 | tail -1 || true

The first command prints demobackend. The second is refused because no pipe matches that username.

Connect from your workstation

To reach the gateway from your own machine, first copy the per-VM demo client key off the VM. Then connect to the gateway host on port 2222. Run the commands below on your workstation, not on the VM:

# from your workstation (replace <public-ip> with your VM public IP) scp azureuser@<public-ip>:/root/sshpiper-demo-key ~/sshpiper-demo-key
# copy the key (run the cp as root on the VM first if needed)
chmod 600 ~/sshpiper-demo-key ssh -p 2222 -i ~/sshpiper-demo-key demo@<public-ip> whoami
6

Add your own pipe

SSHPiper routes by the downstream login username using the yaml router at /etc/sshpiper/sshpiperd.yaml. Each pipe has a from block (which downstream username to match and which public keys to accept) and a to block (the upstream host, the username to log in as, and the private key SSHPiper should use).

To route a new username alice to your own upstream, add a pipe like this:

version: "1.0" pipes: - from: - username: "alice" authorized_keys: - /var/lib/sshpiper/alice/authorized_keys
# alice's public key(s) to: host: 10.0.0.20:22 # your upstream host username: appuser # the account to log in as upstream ignore_hostkey: true # or set known_hosts for strict checking private_key: /var/lib/sshpiper/alice/upstream_key # key SSHPiper uses upstream

After you edit the router config, restart the gateway to apply it:

sudo systemctl restart sshpiper
sudo systemctl is-active sshpiper

You can also match usernames by regular expression, accept passwords, or pin upstream host keys with known_hosts for strict verification. See the SSHPiper project documentation for the full router reference.

The exact pinned SSHPiper release and its SHA-256 are recorded in /opt/sshpiper/VERSION, which makes the image reproducible and auditable. Print the file:

cat /opt/sshpiper/VERSION
7

Server components

The image contains the following components:

  • Gateway: SSHPiper sshpiperd (pinned and SHA-256 verified, see /opt/sshpiper/VERSION)
  • Gateway port: 2222 (SSH reverse proxy, routes by username)
  • Router: yaml router plugin at /etc/sshpiper/sshpiperd.yaml (0600)
  • Admin SSH: system OpenSSH server on port 22 (unchanged)
  • Service account: sshpiper (unprivileged system user, hardened unit)
  • Per-VM keys: host key, upstream key and demo client key, all generated on first boot
  • Demo pipe: demo -> demobackend@127.0.0.1:22 (replace with your own pipes)
  • Credentials: per-VM gateway details and demo key path, in /root/sshpiper-credentials.txt (0600)
  • Operating system: Ubuntu 24.04 LTS (patched at build)
  • License: MIT (SSHPiper, Copyright (c) 2014 Boshi Lian)
8

Manage the SSHPiper service

Check that the gateway is running and enabled at boot:

sudo systemctl is-active sshpiper
sudo systemctl is-enabled sshpiper

Use sudo systemctl restart sshpiper to apply router config changes and sudo systemctl status sshpiper for the full unit state. Use sudo journalctl -u sshpiper -f to follow the live logs. Each rejected connection to an unmapped username is logged there, which is normal for a public gateway.

The router config and per-VM keys live under /etc/sshpiper and /var/lib/sshpiper and persist across service restarts and VM reboots.

9

Security recommendations

  • Restrict the NSG. Allow TCP 2222 (and 22 for administration) only from the networks your users connect from. The gateway does not need to be reachable from the whole internet unless your users are.
  • Replace the demo pipe with your own. The demo pipe exists to prove the proxy works. Remove it from /etc/sshpiper/sshpiperd.yaml and add your own pipes that map real users to your upstream hosts.
  • Pin upstream host keys. Set known_hosts on each to block instead of ignore_hostkey: true, so SSHPiper verifies the upstream server identity.
  • Prefer key-based downstream authentication. Give each pipe its own authorized_keys so only the intended user's key is accepted, and rotate keys when people leave.
  • Keep the OS patched. Unattended security upgrades remain enabled on the running VM.
  • Back up your configuration. Back up /etc/sshpiper and /var/lib/sshpiper to preserve your router config and keys.

Deploy on Azure

Launch SSHPiper on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure