haproxy/reg-tests/ssl/ssl-0rtt.vtci
Willy Tarreau 40687ebc64 REGTESTS: ssl: also verify that 0-rtt properly advertises early-data:1
This patch completes the 0-rtt test to verify that early-data:1 is
properly emitted to the server in the relevant situations. We carefully
compare it with the expected values that are computed based on the TLS
version, the client and listener's support for 0-rtt and the resumption
status. A response header "x-early-data-test" is set to OK on success,
or KO on failure and the client tests this. The previous test is kept
as well. This was tested with quictls-1.1.1 and quictls-3.0.1 for TCP,
as well as aws-lc for QUIC.
2025-11-19 22:30:31 +01:00

263 lines
9.8 KiB
Plaintext

# Uses VTC_SOCK_TYPE (quic / stream) TLSV (TLSv1.2 / TLSv1.3)
feature ignore_unknown_macro
haproxy h1 -conf {
global
.if streq("$VTC_SOCK_TYPE",quic)
# required for backend connections
expose-experimental-directives
.endif
.if feature(THREAD)
thread-groups 1
.endif
.if streq("$TLSV",TLSv1.3)
setenv ZRTT_SUPP 1
.else
setenv ZRTT_SUPP 0
.endif
# forced to 1 here, because there is a cached session per thread
nbthread 1
defaults
mode http
option httplog
option logasap
log stderr local0 debug err
option httpclose
timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
# combinations: cl_{1r,0r}_{sf,st}_{1r,0r}
# sf/st: stateful/stateless tickets
# 1r/0r: 1rtt/0rtt, left: client, right: server
# we force ALPN to "$ALPN" because the next layer's SSL listener needs it.
listen cl_1r_sf_1r
bind "fd@${cl_1r_sf_1r}"
retry-on 0rtt-rejected
http-request add-header x-from %[be_name]
server s1 "${VTC_SOCK_TYPE}+${h1_sv_sf_1r_sock}" ssl verify none alpn "${ALPN}" sni str(www.test1.com)
http-response add-header x-early-rcvd-test OK if !{ ssl_bc_is_resumed } { res.hdr(x-ssl-early-rcvd) 0 }
http-response add-header x-early-rcvd-test OK if { ssl_bc_is_resumed } { res.hdr(x-ssl-early-rcvd) 0 }
listen cl_1r_sl_1r
bind "fd@${cl_1r_sl_1r}"
retry-on 0rtt-rejected
http-request add-header x-from %[be_name]
server s1 "${VTC_SOCK_TYPE}+${h1_sv_sl_1r_sock}" ssl verify none alpn "${ALPN}" sni str(www.test1.com)
http-response add-header x-early-rcvd-test OK if !{ ssl_bc_is_resumed } { res.hdr(x-ssl-early-rcvd) 0 }
http-response add-header x-early-rcvd-test OK if { ssl_bc_is_resumed } { res.hdr(x-ssl-early-rcvd) 0 }
listen cl_1r_sf_0r
bind "fd@${cl_1r_sf_0r}"
retry-on 0rtt-rejected
http-request add-header x-from %[be_name]
server s1 "${VTC_SOCK_TYPE}+${h1_sv_sf_0r_sock}" ssl verify none alpn "${ALPN}" sni str(www.test1.com)
http-response add-header x-early-rcvd-test OK if !{ ssl_bc_is_resumed } { res.hdr(x-ssl-early-rcvd) 0 }
http-response add-header x-early-rcvd-test OK if { ssl_bc_is_resumed } { res.hdr(x-ssl-early-rcvd) 0 }
listen cl_1r_sl_0r
bind "fd@${cl_1r_sl_0r}"
retry-on 0rtt-rejected
http-request add-header x-from %[be_name]
server s1 "${VTC_SOCK_TYPE}+${h1_sv_sl_0r_sock}" ssl verify none alpn "${ALPN}" sni str(www.test1.com)
http-response add-header x-early-rcvd-test OK if !{ ssl_bc_is_resumed } { res.hdr(x-ssl-early-rcvd) 0 }
http-response add-header x-early-rcvd-test OK if { ssl_bc_is_resumed } { res.hdr(x-ssl-early-rcvd) 0 }
listen cl_0r_sf_1r
bind "fd@${cl_0r_sf_1r}"
retry-on 0rtt-rejected
http-request add-header x-from %[be_name]
server s1 "${VTC_SOCK_TYPE}+${h1_sv_sf_1r_sock}" ssl verify none alpn "${ALPN}" sni str(www.test1.com) allow-0rtt
http-response add-header x-early-rcvd-test OK if !{ ssl_bc_is_resumed } { res.hdr(x-ssl-early-rcvd) 0 }
http-response add-header x-early-rcvd-test OK if { ssl_bc_is_resumed } { res.hdr(x-ssl-early-rcvd) 0 }
listen cl_0r_sl_1r
bind "fd@${cl_0r_sl_1r}"
retry-on 0rtt-rejected
http-request add-header x-from %[be_name]
server s1 "${VTC_SOCK_TYPE}+${h1_sv_sl_1r_sock}" ssl verify none alpn "${ALPN}" sni str(www.test1.com) allow-0rtt
http-response add-header x-early-rcvd-test OK if !{ ssl_bc_is_resumed } { res.hdr(x-ssl-early-rcvd) 0 }
http-response add-header x-early-rcvd-test OK if { ssl_bc_is_resumed } { res.hdr(x-ssl-early-rcvd) 0 }
listen cl_0r_sf_0r
bind "fd@${cl_0r_sf_0r}"
retry-on 0rtt-rejected
http-request add-header x-from %[be_name]
server s1 "${VTC_SOCK_TYPE}+${h1_sv_sf_0r_sock}" ssl verify none alpn "${ALPN}" sni str(www.test1.com) allow-0rtt
http-response add-header x-early-rcvd-test OK if !{ ssl_bc_is_resumed } { res.hdr(x-ssl-early-rcvd) 0 }
http-response add-header x-early-rcvd-test OK if { ssl_bc_is_resumed } { res.hdr(x-ssl-early-rcvd) "$ZRTT_SUPP" }
listen cl_0r_sl_0r
bind "fd@${cl_0r_sl_0r}"
retry-on 0rtt-rejected
http-request add-header x-from %[be_name]
server s1 "${VTC_SOCK_TYPE}+${h1_sv_sl_0r_sock}" ssl verify none alpn "${ALPN}" sni str(www.test1.com) allow-0rtt
http-response add-header x-early-rcvd-test OK if !{ ssl_bc_is_resumed } { res.hdr(x-ssl-early-rcvd) 0 }
http-response add-header x-early-rcvd-test OK if { ssl_bc_is_resumed } { res.hdr(x-ssl-early-rcvd) "$ZRTT_SUPP" }
listen ssl
# socket names indicate their capabilities and are used below in regex
# (0r means 0rtt OK, 1r means 0rtt not accepted)
bind "${VTC_SOCK_TYPE}+fd@${sv_sf_1r}" name sf_1r ssl crt ${testdir}/common.pem ssl-min-ver "${TLSV}" ssl-max-ver "${TLSV}"
bind "${VTC_SOCK_TYPE}+fd@${sv_sl_1r}" name sl_1r ssl crt ${testdir}/common.pem ssl-min-ver "${TLSV}" ssl-max-ver "${TLSV}" no-tls-tickets
bind "${VTC_SOCK_TYPE}+fd@${sv_sf_0r}" name sf_0r ssl crt ${testdir}/common.pem ssl-min-ver "${TLSV}" ssl-max-ver "${TLSV}" allow-0rtt
bind "${VTC_SOCK_TYPE}+fd@${sv_sl_0r}" name sl_0r ssl crt ${testdir}/common.pem ssl-min-ver "${TLSV}" ssl-max-ver "${TLSV}" allow-0rtt no-tls-tickets
# expect early-data TLS version supports it and both the client and the listener support it
http-request add-header x-expect-early 1 if { int("$ZRTT_SUPP") eq 1 } { ssl_fc_is_resumed } { req.hdr(x-from) -m reg '^cl_0r' } { so_name -m reg '0r$' }
# this is the application server behind us
server s1 ${h1_srv_sock}
# this one is only set for debugging
http-response add-header x-ssl-early-rcvd %[ssl_fc_early_rcvd]
frontend srv
bind "fd@${srv}"
# set txn.test to OK if early-data matches x-expected-early, otherwise KO,
# then send it as header "x-early-data-test" in the response.
http-request set-var(txn.test) str(OK) if { req.hdr(x-expect-early) 1 } { req.hdr(early-data) 1 }
http-request set-var(txn.test) str(OK) if !{ req.hdr(x-expect-early) -m found } !{ req.hdr(early-data) -m found }
http-request set-var(txn.test,ifempty) str(KO)
http-request return status 200 hdr x-early-data-test %[var(txn.test)]
} -start
# 1r -> 1r
client cl_1r_sf_1r -connect ${h1_cl_1r_sf_1r_sock} {
txreq
rxresp
expect resp.status == 200
expect resp.http.x-early-rcvd-test == OK
expect resp.http.x-early-data-test == OK
} -run
client cl_1r_sf_1r -connect ${h1_cl_1r_sf_1r_sock} -repeat 10 {
txreq
rxresp
expect resp.status == 200
expect resp.http.x-early-rcvd-test == OK
expect resp.http.x-early-data-test == OK
} -run
client cl_1r_sl_1r -connect ${h1_cl_1r_sl_1r_sock} {
txreq
rxresp
expect resp.status == 200
expect resp.http.x-early-rcvd-test == OK
expect resp.http.x-early-data-test == OK
} -run
client cl_1r_sl_1r -connect ${h1_cl_1r_sl_1r_sock} -repeat 10 {
txreq
rxresp
expect resp.status == 200
expect resp.http.x-early-rcvd-test == OK
expect resp.http.x-early-data-test == OK
} -run
# 1r -> 0r
client cl_1r_sf_0r -connect ${h1_cl_1r_sf_0r_sock} {
txreq
rxresp
expect resp.status == 200
expect resp.http.x-early-rcvd-test == OK
expect resp.http.x-early-data-test == OK
} -run
client cl_1r_sf_0r -connect ${h1_cl_1r_sf_0r_sock} -repeat 10 {
txreq
rxresp
expect resp.status == 200
expect resp.http.x-early-rcvd-test == OK
expect resp.http.x-early-data-test == OK
} -run
client cl_1r_sl_0r -connect ${h1_cl_1r_sl_0r_sock} {
txreq
rxresp
expect resp.status == 200
expect resp.http.x-early-rcvd-test == OK
expect resp.http.x-early-data-test == OK
} -run
client cl_1r_sl_0r -connect ${h1_cl_1r_sl_0r_sock} -repeat 10 {
txreq
rxresp
expect resp.status == 200
expect resp.http.x-early-rcvd-test == OK
expect resp.http.x-early-data-test == OK
} -run
# 0r -> 1r
client cl_0r_sf_1r -connect ${h1_cl_0r_sf_1r_sock} {
txreq
rxresp
expect resp.status == 200
expect resp.http.x-early-rcvd-test == OK
expect resp.http.x-early-data-test == OK
} -run
client cl_0r_sf_1r -connect ${h1_cl_0r_sf_1r_sock} -repeat 10 {
txreq
rxresp
expect resp.status == 200
expect resp.http.x-early-rcvd-test == OK
expect resp.http.x-early-data-test == OK
} -run
client cl_0r_sl_1r -connect ${h1_cl_0r_sl_1r_sock} {
txreq
rxresp
expect resp.status == 200
expect resp.http.x-early-rcvd-test == OK
expect resp.http.x-early-data-test == OK
} -run
client cl_0r_sl_1r -connect ${h1_cl_0r_sl_1r_sock} -repeat 10 {
txreq
rxresp
expect resp.status == 200
expect resp.http.x-early-rcvd-test == OK
expect resp.http.x-early-data-test == OK
} -run
# 0r -> 0r: must work for TLSv1.3
client cl_0r_sf_0r -connect ${h1_cl_0r_sf_0r_sock} {
txreq
rxresp
expect resp.status == 200
expect resp.http.x-early-rcvd-test == OK
expect resp.http.x-early-data-test == OK
} -run
client cl_0r_sf_0r -connect ${h1_cl_0r_sf_0r_sock} -repeat 10 {
txreq
rxresp
expect resp.status == 200
expect resp.http.x-early-rcvd-test == OK
expect resp.http.x-early-data-test == OK
} -run
client cl_0r_sl_0r -connect ${h1_cl_0r_sl_0r_sock} {
txreq
rxresp
expect resp.status == 200
expect resp.http.x-early-rcvd-test == OK
expect resp.http.x-early-data-test == OK
} -run
client cl_0r_sl_0r -connect ${h1_cl_0r_sl_0r_sock} -repeat 10 {
txreq
rxresp
expect resp.status == 200
expect resp.http.x-early-rcvd-test == OK
expect resp.http.x-early-data-test == OK
} -run