Trying to add specific routing depending on SSH destination fails.
My haproxy.cfg looks like this:
global
log /dev/log local0 info
log /dev/log local1 info
chroot /var/lib/haproxy
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
tune.ssl.default-dh-param 2048
ssl-default-bind-options no-sslv3 no-tls-tickets
ssl-default-bind-ciphers ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:SRP-DSS-AES-256-CBC-SHA:SRP-RSA-AES-256-CBC-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA
defaults
log global
#mode http
option httplog
option dontlognull
timeout connect 50000
timeout client 500000
timeout server 500000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
frontend ssh
bind *:22 ssl no-sslv3 crt /path/to/cert.pem
mode tcp
option tcplog
log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq dst:%[var(sess.dst)] "
tcp-request content set-var(sess.dst) ssl_fc_sni
tcp-request inspect-delay 5s
acl valid_payload req.payload(0,7) -m str "SSH-2.0"
tcp-request content reject if !valid_payload
tcp-request content accept if { req_ssl_hello_type 1 }
acl gitlab ssl_fc_sni gitlab.contoso.com
# tcp-request content reject if !gitlab
default_backend bck_gitlab_ssh
backend bck_gitlab_ssh
mode tcp
server gitlab a.b.c.d:22 check
frontend http-in
bind *:80
bind *:443 ssl no-sslv3 crt /path/to/cert.pem
mode http
option httplog
[...]
I launched the openssl s_client -connect subdomain.contoso.com:22
with following result:
CONNECTED(00000003)
— Certificate chain 0 s:CN = *.subdomain.contoso.com i:C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN =
Sectigo RSA Domain Validation Secure Server CA 1 s:C = GB, ST =
Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA
Domain Validation Secure Server CA i:C = US, ST = New Jersey, L =
Jersey City, O = The USERTRUST Network, CN = USERTrust RSA
Certification Authority 2 s:C = US, ST = New Jersey, L = Jersey City,
O = The USERTRUST Network, CN = USERTrust RSA Certification Authority
i:C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network,
CN = USERTrust RSA Certification Authority
— Server certificate
-----BEGIN CERTIFICATE----- […]
-----END CERTIFICATE----- subject=CN = *.subdomain.contoso.comissuer=C = GB, ST = Greater Manchester, L = Salford, O = Sectigo
Limited, CN = Sectigo RSA Domain Validation Secure Server CA— No client certificate CA names sent Peer signing digest: SHA256 Peer signature type: RSA-PSS Server Temp Key: X25519, 253 bits
— SSL handshake has read 5242 bytes and written 396 bytes Verification: OK
— New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384 Server public key is 2048 bit Secure Renegotiation IS NOT supported Compression: NONE
Expansion: NONE No ALPN negotiated Early data was not sent Verify
return code: 0 (ok)
— HTTP/1.0 400 Bad request Cache-Control: no-cache Connection: close Content-Type: text/html400 Bad request
Your browser sent an invalid request.— Post-Handshake New Session Ticket arrived: SSL-Session:
Protocol : TLSv1.3
Cipher : TLS_AES_256_GCM_SHA384
Session-ID: FF80D974E787152BE195D533AF095842F2257CD340F8EB40AF5EA8D70D661229
Session-ID-ctx:
Resumption PSK: A4A117A4D8C504590DFBACDB00B46A2D87AA15FDFE4D0AA83CAE9341330AABFE4488C3D7EB73BAE8386EE748240E3514
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 7200 (seconds)
TLS session ticket:
0000 - b4 05 de bd c7 b1 d3 71-53 99 b3 28 6e 46 6d 23 …qS…(nFm#
0010 - a6 fc cc bd c9 a2 c7 86-61 6a 25 f5 80 83 29 33 …aj%…)3Start Time: 1664029485 Timeout : 7200 (sec) Verify return code: 0 (ok) Extended master secret: no Max Early Data: 0
— read R BLOCK
— Post-Handshake New Session Ticket arrived: SSL-Session:
Protocol : TLSv1.3
Cipher : TLS_AES_256_GCM_SHA384
Session-ID: 6AC8A5104001D9DA6A4ACF750352B1429D258452FED10584B4C6398CF6DC740C
Session-ID-ctx:
Resumption PSK: 354465EF5C784F3B021A721FFD739E7F0FB7BBF666B7D165CC324A313C7B446A7FF6E65CB54081E00DE9389F780AC177
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 7200 (seconds)
TLS session ticket:
0000 - 27 2d ca 6c 4d af 6b ce-dc cb 67 39 f3 60 20 3a '-.lM.k…g9.` :
0010 - b0 a5 25 58 6d 4a ef db-7d db 0d 97 5a 54 aa 03 …%XmJ…}…ZT…Start Time: 1664029485 Timeout : 7200 (sec) Verify return code: 0 (ok) Extended master secret: no Max Early Data: 0
— read R BLOCK closed
However when I do a SSH command to subdomain contoso.com it fails with an SSL handshake failure.
Aside note:
- The default works for the http(s) frontend
- If i comment the
ssl no-sslv3 crt
and what is after it works (except that it disables the routing part…)
Any help on this?
My Haproxy version :
HA-Proxy version 1.8.19-1+deb10u3 2020/08/01
Copyright 2000-2019 Willy Tarreau willy@haproxy.orgBuild options :
TARGET = linux2628
CPU = generic
CC = gcc
CFLAGS = -O2 -g -O2 -fdebug-prefix-map=/build/haproxy-OkbS59/haproxy-1.8.19=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fno-strict-aliasing -Wdeclaration-after-statement -fwrapv -Wno-format-truncation -Wno-null-dereference -Wno-unused-label
OPTIONS = USE_GETADDRINFO=1 USE_ZLIB=1 USE_REGPARM=1 USE_OPENSSL=1 USE_LUA=1 USE_SYSTEMD=1 USE_PCRE2=1 USE_PCRE2_JIT=1 USE_NS=1Default settings :
maxconn = 2000, bufsize = 16384, maxrewrite = 1024, maxpollevents = 200Built with OpenSSL version : OpenSSL 1.1.1d 10 Sep 2019
Running on OpenSSL version : OpenSSL 1.1.1n 15 Mar 2022
OpenSSL library supports TLS extensions : yes
OpenSSL library supports SNI : yes
OpenSSL library supports : TLSv1.0 TLSv1.1 TLSv1.2 TLSv1.3
Built with Lua version : Lua 5.3.3
Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT IP_FREEBIND
Encrypted password support via crypt(3): yes
Built with multi-threading support.
Built with PCRE2 version : 10.32 2018-09-10
PCRE2 library supports JIT : yes
Built with zlib version : 1.2.11
Running on zlib version : 1.2.11
Compression algorithms supported : identity(“identity”), deflate(“deflate”), raw-deflate(“deflate”), gzip(“gzip”)
Built with network namespace support.Available polling systems :
epoll : pref=300, test result OK
poll : pref=200, test result OK
select : pref=150, test result OK
Total: 3 (3 usable), will use epoll.Available filters :
[SPOE] spoe
[COMP] compression
[TRACE] trace