Arash
Arash

Reputation: 340

haproxy sending 400 Bad request on ssh connect [TCP frontend/backend]

I have setup an SSH server behind haproxy.

haproxy is configured to serve 80/443 ports as L7 load balancer. I have added a TCP frontend to bind on port 22 to handle and route SSH connections.

frontend ssh
    bind *:22
    mode tcp
    option tcplog
    use_backend back_ssh

backend back_ssh
    option tcp-check
    tcp-check expect string SSH-2.0-
    server ssh_server 172.16.2.5:1222 check

the result is as below (400 bad request)

ssh -vvv  foo.bar.com
OpenSSH_7.9p1, LibreSSL 2.7.3
debug1: Reading configuration data /Users/arash/.ssh/config
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Connecting to foo.bar.com port 22.
debug1: Connection established.
debug1: identity file /Users/arash/.ssh/id_rsa type 0
debug1: identity file /Users/arash/.ssh/id_rsa-cert type -1
debug1: identity file /Users/arash/.ssh/id_dsa type -1
debug1: identity file /Users/arash/.ssh/id_dsa-cert type -1
debug1: identity file /Users/arash/.ssh/id_ecdsa type -1
debug1: identity file /Users/arash/.ssh/id_ecdsa-cert type -1
debug1: identity file /Users/arash/.ssh/id_ed25519 type -1
debug1: identity file /Users/arash/.ssh/id_ed25519-cert type -1
debug1: identity file /Users/arash/.ssh/id_xmss type -1
debug1: identity file /Users/arash/.ssh/id_xmss-cert type -1
debug1: Local version string SSH-2.0-OpenSSH_7.9
debug1: ssh_exchange_identification: HTTP/1.0 400 Bad request


debug1: ssh_exchange_identification: Cache-Control: no-cache


debug1: ssh_exchange_identification: Connection: close


debug1: ssh_exchange_identification: Content-Type: text/html


debug1: ssh_exchange_identification: 


debug1: ssh_exchange_identification: <html><body><h1>400 Bad request</h1>

debug1: ssh_exchange_identification: Your browser sent an invalid request.

debug1: ssh_exchange_identification: </body></html>

ssh_exchange_identification: Connection closed by remote host

and when I change config to listen instead of frontend and backend like below, it will work.

listen ssh *:22
    mode tcp
    option tcplog
    option tcp-check
    tcp-check expect string SSH-2.0-
    server ssh_server 172.16.2.5:1222 check

The question is did I miss something on my first configuration and how it's broken? I prefer to have my configuration in frontend/backend format to follow my convention.

Upvotes: 1

Views: 3027

Answers (1)

Michael - sqlbot
Michael - sqlbot

Reputation: 179084

A listen foo proxy declaration is essentially a shorthand for declaring a frontend foo and a backend foo with the same name (foo) and an implicit default_backend foo.

But importantly, it's also applying any relevant configuration directives to both the (implicit) frontend and the backend this construct creates.

This is where your configuration diverges -- you don't have mode tcp -- a directive applicable to both frontends and backends -- in your backend proxy declaration. Since TCP (layer 4 balancing) is the default mode, the HTTP appearing in your protocol stream implies that you must also have a defaults section (not shown) that is setting mode http and putting the backend into http mode.

Upvotes: 2

Related Questions