Table of Contents

Задача

Нужно запустить на одном порту 443 сервер SSH и HTTPS SSL. На первый взгляд - невозможно. Но на самом деле есть же прекрасный балансировщик haproxy.

Первый вариант

Haproxy позволяет проверить, является-ли полученный запрос SSL-запросом или нет и есть нет, то отправляем его на сервер SSH.

defaults
  timeout connect 5s
  timeout client 50s
  timeout server 20s

listen ssl :443
  tcp-request inspect-delay 2s
  acl is_ssl req_ssl_ver 2:3.1
  tcp-request content accept if is_ssl
  use_backend ssh if !is_ssl
  server www-ssl :444
  timeout client 2h

backend ssh
  mode tcp
  server ssh :22
  timeout server 2h

Тут строка acl is_ssl req_ssl_ver 2:3.1 проверяет запрос SSL или нет.
а если не SSL, то строка use_backend ssh if !is_ssl отправляет на бекенд с SSH.

Второй вариант

Описан тут: https://blog.chmd.fr/ssh-over-ssl-episode-4-a-haproxy-based-configuration.html
В данном случае - на фронтэнде проверяется содержимое запроса клиента, и если он начинается с SSH-2.0 (в hex-представлении - 5353482d322e30, конвертировать ТУТ ), то сессия направляется на SSH-сервер.

backend secure_http
    reqadd X-Forwarded-Proto:\ https
    rspadd Strict-Transport-Security:\ max-age=31536000
    mode http
    option httplog
    option forwardfor
    server local_http_server 127.0.0.1:80

backend ssh
    mode tcp
    option tcplog
    server ssh 127.0.0.1:22
    timeout server 2h

frontend ssl
    bind X.X.X.X:443 ssl crt /etc/ssl/private/certs.pem no-sslv3
    mode tcp
    option tcplog
    tcp-request inspect-delay 5s
    tcp-request content accept if HTTP

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

    use_backend ssh if !HTTP
    use_backend ssh if client_attempts_ssh
    use_backend secure_http if HTTP