]> git.kaiwu.me - haproxy.git/commitdiff
REGTESTS: sample_fetches: test the raw TLS hello fetches
authorWilly Tarreau <w@1wt.eu>
Tue, 22 Sep 2026 04:10:31 +0000 (04:10 +0000)
committerWilly Tarreau <w@1wt.eu>
Wed, 30 Sep 2026 15:19:30 +0000 (17:19 +0200)
req.ssl_hello_type, req.ssl_ver, req.ssl_ec_ext, req.ssl_st_ext and
res.ssl_hello_type had no coverage, nor had the deprecated
req_ssl_hello_type, req_ssl_ver, req_ssl_sni and rep_ssl_hello_type
aliases. They parse the raw buffer of a TCP proxy without any SSL data
layer, so the handshake messages are crafted by hand with sendhex the
same way the other ClientHello tests do, and a server answers each of
them with a ServerHello so that the response side is covered too.

Three ClientHellos are used: one carrying server_name, supported_groups
and an empty session ticket, one carrying a session ticket with data
and no supported_groups, and one carrying a single unrelated extension
so that req.ssl_st_ext reports its documented zero.

reg-tests/sample_fetches/ssl_hello_type.vtc [new file with mode: 0644]

diff --git a/reg-tests/sample_fetches/ssl_hello_type.vtc b/reg-tests/sample_fetches/ssl_hello_type.vtc
new file mode 100644 (file)
index 0000000..8256baa
--- /dev/null
@@ -0,0 +1,103 @@
+varnishtest "Test the raw TLS hello fetches of the TCP rule sets"
+
+# req.ssl_hello_type, req.ssl_ver, req.ssl_ec_ext, req.ssl_st_ext and
+# res.ssl_hello_type had no coverage, nor had the deprecated
+# 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.
+
+feature ignore_unknown_macro
+
+# the server answers every ClientHello with the same ServerHello
+server s1 -repeat 3 {
+       recv 47
+       sendhex "16030300 2c 02000028 0303 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 00 1302 00 0000"
+} -start
+
+syslog S1 -level info {
+       # supported_groups and an empty session ticket extension
+       recv
+       expect ~ "type=1 ver=196611 ec=1 st=1 sni=www.example.com dtype=1 dver=196611 dsni=www.example.com rtype=2 drtype=2 bytes=[0-9]+$"
+       # a session ticket carrying data, and no supported_groups
+       recv
+       expect ~ "type=1 ver=196611 ec=0 st=2 sni=- dtype=1 dver=196611 dsni=- rtype=2 drtype=2 bytes=[0-9]+$"
+       # 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]+$"
+} -start
+
+haproxy h1 -conf {
+    global
+    .if feature(THREAD)
+        thread-groups 1
+    .endif
+        chroot /
+       nbthread 1
+
+    defaults
+       mode tcp
+       timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+       timeout client  "${HAPROXY_TEST_TIMEOUT-5s}"
+       timeout server  "${HAPROXY_TEST_TIMEOUT-5s}"
+
+    frontend fe1
+       bind "fd@${fe1}"
+       log ${S1_addr}:${S1_port} local0
+       # %B is only there to delay the message until the response rules
+       # have run
+       log-format "type=%[var(txn.t)] ver=%[var(txn.v)] ec=%[var(txn.e)] st=%[var(txn.s)] sni=%[var(txn.n)] dtype=%[var(txn.dt)] dver=%[var(txn.dv)] dsni=%[var(txn.dn)] rtype=%[var(txn.rt)] drtype=%[var(txn.drt)] bytes=%B"
+
+       tcp-request inspect-delay 100ms
+       tcp-request content set-var(txn.t)  req.ssl_hello_type
+       tcp-request content set-var(txn.v)  req.ssl_ver
+       tcp-request content set-var(txn.e)  req.ssl_ec_ext
+       tcp-request content set-var(txn.s)  req.ssl_st_ext
+       tcp-request content set-var(txn.n)  req.ssl_sni
+       # the deprecated spellings must report the same values
+       tcp-request content set-var(txn.dt) req_ssl_hello_type
+       tcp-request content set-var(txn.dv) req_ssl_ver
+       tcp-request content set-var(txn.dn) req_ssl_sni
+       tcp-request content accept if { req.ssl_hello_type 1 }
+
+       default_backend be
+
+    backend be
+       tcp-response inspect-delay 100ms
+       tcp-response content set-var(txn.rt)  res.ssl_hello_type
+       tcp-response content set-var(txn.drt) rep_ssl_hello_type
+       tcp-response content accept if { res.ssl_hello_type 2 }
+       server s1 ${s1_addr}:${s1_port}
+} -start
+
+# The ClientHellos share the 43-byte body of the other ClientHello tests:
+#   16 03 01 LL LL    TLS record: handshake, TLSv1.0
+#   01 00 00 LL       Handshake: ClientHello
+#   03 03             client_version, TLSv1.2
+#   00 .. 1f          Random[32]
+#   00                session_id_len = 0
+#   00 02 13 02       cipher_len = 2, one cipher suite
+#   01 00             compression_len = 1, method 0
+#   LL LL             extensions_len
+# and only differ by the extensions which follow.
+
+# server_name, supported_groups and an empty session_ticket (0023)
+client c1 -connect ${h1_fe1_sock} {
+       sendhex "160301 0055 01000051 0303 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 00 00021302 0100 0026 00000014001200000f 7777772e6578616d706c652e636f6d 000a00060004001d0017 00230000"
+       recv 49
+} -run
+
+# a session_ticket holding four bytes, and no supported_groups
+client c2 -connect ${h1_fe1_sock} {
+       sendhex "160301 0037 01000033 0303 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 00 00021302 0100 0008 0023 0004 aabbccdd"
+       recv 49
+} -run
+
+# a single unrelated extension (renegotiation_info). Note that an empty
+# extension block is not accepted by the parser, which requires at least
+# two bytes past the extension list length.
+client c3 -connect ${h1_fe1_sock} {
+       sendhex "160301 0034 01000030 0303 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 00 00021302 0100 0005 ff01000100"
+       recv 49
+} -run
+
+syslog S1 -wait