The SSH protocol and
SSH Applications - Part 1

Martin Stecher June 19, 2025

SSH and SSH Applications from a Security Gateway Perspective

When we developed SSH Gateway, we quickly realized that simply proxying the core SSH protocol wasn’t enough. To effectively filter SSH-transferred data for security purposes—especially within an SSE (Security Service Edge) framework — we needed to implement proxies for various SSH Applications as well.

Part 1: The SSH Core Protocol and SSH Remote Commands

Understanding the difference between the SSH protocol itself and the SSH applications that run over it, can be complex. In this blog article series, we’ll clarify that distinction and explain what an SSH proxy server with security filter focus actually needs to handle.

SSH Stack

Depending on the negotiated algorithms, packet encryption and authentication can vary a lot.

SSH Packets

At its foundation, SSH runs on top of TCP/IP, which ensures packets arrive in order. When an SSH connection is initiated, the client and server first exchange a single plaintext line that indicates the SSH protocol version and the product name. Immediately afterward, the connection switches to a formal packet-based format.

Each SSH packet represents a complete message with a defined length and type. This structure simplifies parsing and ensures that messages are only processed once they're fully received.

The first few packets are used to negotiate which encryption algorithms to use. Once agreed upon, encryption is enabled for all subsequent packets. This flexible design allows for the addition of new encryption algorithms without changing the SSH protocol version - something that has happened frequently over time.

As a result, there is now a (too) large number of available algorithms—some of which are outdated or insecure. For compatibility, SSH clients and servers typically advertise long lists of supported algorithms:

  • One list for session key negotiation,
  • Another for server authentication,
  • Two lists for encryption/decryption (client-to-server and server-to-client),
  • And two more for checksums or MACs in each direction.

Depending on the chosen algorithms, packet characteristics vary: some encrypt packet sizes, others do not; some calculate checksums over encrypted data, others over plaintext; and some integrate the checksum directly into the encryption algorithm. This flexibility increases implementation complexity and can introduce parsing errors or security issues.

SSH Connection Flowchart

The standard flow in an SSH Connection.

SSH Channels

Once the initial handshake is complete, SSH opens channels to transmit data. While some packets are used for global session management (like user authentication), actual data exchange happens through these logical channels. Channels can be initiated from either side, but most commonly they’re opened by the client.

SSH supports full-duplex communication over channels and includes flow control using dynamic receive window sizes. Every SSH connection follows these general steps:

  1. Negotiation of encryption algorithms
  2. Authentication of the server host
  3. Enabling of encryption
  4. User authentication
  5. Channel opening

Only after these steps can DATA messages be sent. These messages always belong to a channel and are subject to flow control. Their meaning depends on the channel type, which in turn defines the specific SSH application in use.

SSH Stack

The layers of the SSH protocol and applications.

SSH Applications

The most well-known SSH application is the remote shell - a way to log in and interact with a remote terminal. But SSH supports many other applications via its channel mechanism, for example:

  • Remote command execution (a single command run on the remote host)
  • Port forwarding / tunneling (transparent TCP relay)
  • SCP and SFTP (file transfer protocols)
  • Git over SSH (used by platforms like GitHub for secure repository access)

Each of these applications introduces different challenges for a security gateway. In this first article of the series, we’ll focus on the simplest use case: remote command execution. In upcoming articles, we’ll explore the more complex SSH Applications.

SSH Remote Command

When a channel is opened to execute a command remotely, the request includes the command string and its arguments - just as if it were typed into a terminal. An SSH security gateway that operates with separate encrypted upstream and downstream connections can parse this request and determine which command is about to be executed.

# Example to execute a remote command:
#   Print the path of the user's working directory
ssh john@www.example.org "pwd"    
/home/johnsmith

Following the example above, the SSH Gateway will receive the SSH packet to open a channel to execute pwd. At this stage, a filtering policy can evaluate the command and decide whether to allow or block it.

Once the command is running, its input and output streams are mapped to SSH DATA messages. If the command doesn’t require further input, filtering is relatively straightforward. However, things become more complex if the command interacts dynamically or implements its own mini-protocol (as is the case with SCP or SFTP). At that point, the gateway must interpret subsequent DATA messages in application-specific ways.

This complexity is exactly why application-level SSH proxies are necessary - and why we’ll explore them individually in the upcoming parts of this series.

The articles in this series

  1. The SSH Core Protocol and the SSH Remote Command [this article]
  2. SSH Remote Shell from a Gateway Perspective
  3. SCP from a Gateway Perspective [upcoming]
  4. SFTP from a Gateway Perspective [upcoming]
  5. Git via SSH from a Gateway Perspective [upcoming]
  6. TCP Tunnels via SSH from a Gateway Perspective [upcoming]

 

For questions and discussion please comment on our LinkedIn post