]> git.kaiwu.me - haproxy.git/commitdiff
REGTESTS: sample_fetches: test req.ssl_ver on an SSLv2 CLIENT-HELLO
authorWilly Tarreau <w@1wt.eu>
Tue, 22 Sep 2026 06:37:48 +0000 (06:37 +0000)
committerWilly Tarreau <w@1wt.eu>
Wed, 30 Sep 2026 15:25:37 +0000 (17:25 +0200)
req.ssl_ver is the only fetch of the family which accepts the SSLv2
record format in addition to the SSLv3 one, and that second half of
smp_fetch_req_ssl_ver() was not reached by the ClientHellos of the
first frontend. It is also the only one whose ACL parses its pattern
in dotted notation, which was not covered either.

A second frontend, which rejects everything and only reports the
fetches in its log, receives an SSLv2 CLIENT-HELLO with the short
record header announcing SSLv3.0, another one with the long record
header, its padding length, two ciphers and a 32-byte challenge,
announcing TLSv1.0, and finally a plain HTTP request which is neither.
The version is checked both as a number and through the "3.0" and
"gt 3.0" patterns of the two ACL spellings, while req.ssl_hello_type
and req.ssl_sni, which only know the SSLv3 record, return nothing.

reg-tests/sample_fetches/ssl_hello_type.vtc

index 8256baae4da46245de227d8816522ef6aa51c1a1..10295354ee9820730cb9bf038fcfa0dcb4774723 100644 (file)
@@ -5,6 +5,10 @@ varnishtest "Test the raw TLS hello fetches of the TCP rule sets"
 # req_ssl_hello_type, req_ssl_ver, req_ssl_sni and rep_ssl_hello_type
 # aliases. They all parse the raw buffer of a TCP proxy, without any SSL
 # data layer, so the handshake messages are crafted by hand here.
+#
+# The second frontend covers the other format req.ssl_ver understands,
+# the SSLv2 CLIENT-HELLO, which none of the other fetches parses, and
+# the dotted notation their ACLs accept as a pattern.
 
 feature ignore_unknown_macro
 
@@ -24,6 +28,15 @@ syslog S1 -level info {
        # one unrelated extension: no supported_groups and no session ticket
        recv
        expect ~ "type=1 ver=196611 ec=0 st=0 sni=- dtype=1 dver=196611 dsni=- rtype=2 drtype=2 bytes=[0-9]+$"
+       # an SSLv2 CLIENT-HELLO announcing SSLv3.0, short record header
+       recv
+       expect ~ "sslv2 ver=196608 dver=196608 type=- sni=- eq30=1 gt30=-$"
+       # an SSLv2 CLIENT-HELLO announcing TLSv1.0, long record header
+       recv
+       expect ~ "sslv2 ver=196609 dver=196609 type=- sni=- eq30=- gt30=1$"
+       # not SSL at all
+       recv
+       expect ~ "sslv2 ver=- dver=- type=- sni=- eq30=- gt30=-$"
 } -start
 
 haproxy h1 -conf {
@@ -61,6 +74,25 @@ haproxy h1 -conf {
 
        default_backend be
 
+    # req.ssl_ver is the only one of the family which also parses the
+    # SSLv2 CLIENT-HELLO record format, where the version is not at the
+    # same place at all. This frontend rejects everything, the fetches
+    # are only reported in the log.
+    frontend fe2
+       bind "fd@${fe2}"
+       log ${S1_addr}:${S1_port} local0
+       log-format "sslv2 ver=%[var(txn.v)] dver=%[var(txn.dv)] type=%[var(txn.t)] sni=%[var(txn.n)] eq30=%[var(txn.eq)] gt30=%[var(txn.gt)]"
+
+       tcp-request inspect-delay 100ms
+       tcp-request content set-var(txn.v)  req.ssl_ver
+       tcp-request content set-var(txn.dv) req_ssl_ver
+       tcp-request content set-var(txn.t)  req.ssl_hello_type
+       tcp-request content set-var(txn.n)  req.ssl_sni
+       # both spellings of the ACL parse their pattern in dotted notation
+       tcp-request content set-var(txn.eq) int(1) if { req.ssl_ver 3.0 }
+       tcp-request content set-var(txn.gt) int(1) if { req_ssl_ver gt 3.0 }
+       tcp-request content reject
+
     backend be
        tcp-response inspect-delay 100ms
        tcp-response content set-var(txn.rt)  res.ssl_hello_type
@@ -100,4 +132,31 @@ client c3 -connect ${h1_fe1_sock} {
        recv 49
 } -run
 
+# SSLv2 CLIENT-HELLO with the short record header:
+#   80 1c                 length = 28, no padding
+#   01                    msg_type = CLIENT-HELLO
+#   03 00                 version = SSLv3.0
+#   00 03                 cipher_len, a multiple of 3
+#   00 00                 session_id_len, 0 or 16
+#   00 10                 challenge_len, 16 to 32
+#   010080                one cipher
+#   11 .. 20              challenge[16]
+client c4 -connect ${h1_fe2_sock} {
+       sendhex "801c 01 0300 0003 0000 0010 010080 1112131415161718191a1b1c1d1e1f20"
+       expect_close
+} -run
+
+# same with the long record header, which carries a padding length, two
+# ciphers, a 32-byte challenge and announces TLSv1.0
+client c5 -connect ${h1_fe2_sock} {
+       sendhex "002f 02 01 0301 0006 0000 0020 010080020080 1112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30 aabb"
+       expect_close
+} -run
+
+# a plain HTTP request is neither an SSLv3 record nor an SSLv2 hello
+client c6 -connect ${h1_fe2_sock} {
+       send "GET / HTTP/1.0\r\n\r\n"
+       expect_close
+} -run
+
 syslog S1 -wait