🔗HTTPS and SSH on the same port

Using HAProxy to server SSH and SSL available on the same port:

    maxconn 1000000
    spread-checks 3
    log /var/run/log local0 notice
    tune.ssl.default-dh-param 2048

    mode http
    balance roundrobin
    option http-server-close
    option abortonclose
    option dontlognull
    option redispatch

    timeout check           3s
    timeout client          30s  # Client and server timeout must match the longest
    timeout connect         5s
    timeout http-keep-alive 5s
    timeout http-request    10s  # A complete request may never take that long.
    timeout queue           1m   # Don't queue requests too long if saturated.
    timeout server          10s  # Time we may wait for a response from the server.

    retries 3
    log global

# ----------------------------------------------------------------------------
# stats
# ----------------------------------------------------------------------------
listen stats
    bind *:81
    stats enable
    stats uri /
    stats show-node
    stats show-legends
    stats refresh 5s

# ------------------------------------------------------------------------------
#  https + ssh
# ------------------------------------------------------------------------------
frontend ssl
    mode tcp
    bind *:443 ssl crt /usr/local/etc/haproxy/your.cert
    option tcplog
    tcp-request inspect-delay 5s
    tcp-request content accept if HTTP

    # 5353482d322e30 is the binary representation of the string 'SSH-2.0'
    acl client_attempts_ssh payload(0,7) -m bin 5353482d322e30

    use_backend ssh if !HTTP
    use_backend ssh if client_attempts_ssh
    use_backend http if HTTP

backend http
    mode http
    http-request set-header X-Forwarded-Port %[dst_port]
    server www maxconn 50 check

backend ssh
    mode tcp
    option tcplog
    server ssh
    timeout server 2h

🔗Connecting from an SSH client

To connect throught the HAProxy on port 443 edit the ~/.ssh/config:

Host ssh-over-https
    ProxyCommand openssl s_client -connect your.haproxy.com:443 -quiet

🔗how does this work ?

The RFC 4253, section 4.2 states that clients must send a string that starts with 'SSH-2.0':

4.2.  Protocol Version Exchange

   When the connection has been established, both sides MUST send an
   identification string.  This identification string MUST be

      SSH-protoversion-softwareversion SP comments CR LF

   Since the protocol being defined in this set of documents is version
   2.0, the 'protoversion' MUST be "2.0".
>>> "5353482d322e30".decode("hex")

5353482d322e30 is the binary representation of the string 'SSH-2.0'. So everything boils down to this line:

acl client_attempts_ssh payload(0,7) -m bin 5353482d322e30

When a new connection is made on the port 443, HAproxy decrypts the SSL layer, and checks whether the stream of data sent by the client starts with this string.

src: http://blog.chmd.fr/ssh-over-ssl-episode-4-a-haproxy-based-configuration.html