SSH Host Header

This page contains code for adding an HTTP Host header to SSH communication. This idea may seem contradictory since HTTP and SSH are two different protocols. The goal of this software is for the communication to maintain compliance with the SSH protocol while looking just similar enough to HTTP that it will work through a frontend which dispatches connections to backends based on the Host header.

The primary use case

The primary use case for this software is to allow SSH connections through this IPv4 frontend.

Choosing between the versions

There are two distinct implementations which work in slightly different ways. For both the aim is to embed an HTTP Host header into the SSH communication. One implementation is a patch for the OpenSSH client and will require a recompilation of the client. Another implementation uses a ProxyCommand which can work with the stock ssh client but has lower performance and a minor quirk.

The ProxyCommand

This implementation consists of a single file. It is used by adding the following argument to the ssh command line.

-o ProxyCommand='ssh-sni-proxy-command.py %h %p'

It works by inserting the HTTP Host header into the padding of the first SSH protocol message. Due to the limit on padding length, this will break if the hostname is very long. Inserting a separate protocol message into the communication wouldn't work since the packet count will be authenticated later in the communication. But padding on messages exchanged prior to encryption being negotiated is not authenticated and thus can be modified by this ProxyCommand.

One additional quirk is that the ProxyCommand uses two separate TCP connections to the server because it needs to sent the first message in order to receive the server banner. Communication may fail if the server responds with different banners on the two connections.

The OpenSSH client patch

This implementation consists of a patch for the OpenSSH client. Getting it working with the most recent OpenSSH version is left as an excercise for the reader :-)

Since the client itself is modified it is possible to insert an additional SSH protocol message without breaking authentication. The patch modifies the communication in two ways.

The client banner is extended with an HTTP protocol specification. SSH will treat that part as a comment. This modification is not required by the IPv4 frontend linked above, but it may improve compatibility with other software.

A single SSH2_MSG_IGNORE message is sent after the client banner but before any negotiation starts. The contents of this message is the HTTP Host header. The IPv4 frontend will interpret it as an HTTP Host header. The SSH server will simply ignore it.

The client must be configured to only support SSH protocol version 2. That should already be the default on any modern install. If support for the obsolete SSH protocol version 1 is enabled on the client, the communication will deadlock during protocol version negotiation. The client will be waiting for a server banner while the proxy will wait for the client to tell it which server to connect to.

No other changes needed

The code provided here only requires client side modifications. The communication is designed to look sufficiently like HTTP that the IPv4 frontend will see it as HTTP and thus is able to process it without any changes needed on the frontend. No promises are made about compatibility with other HTTP software.

Since the communication remains compliant with the SSH protocol and only modifies data to be ignored by the server, it will also work without server side changes.