mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-10-27 14:41:28 +01:00
Tests with abortonclose showed a bug with this test where the client would close the stream immediately after sending the request, without waiting for the response, causing some random failures on the server side.
178 lines
3.0 KiB
Plaintext
178 lines
3.0 KiB
Plaintext
# This test ensures that h2 requests with invalid pseudo-headers are properly
|
|
# rejected. Also, the host header must be ignored if authority is present. This
|
|
# is necessary to avoid http/2 desync attacks through haproxy as described here
|
|
# https://portswigger.net/research/http2
|
|
|
|
varnishtest "h2 desync attacks"
|
|
feature ignore_unknown_macro
|
|
|
|
server s1 {
|
|
rxreq
|
|
expect req.http.host == "hostname"
|
|
txresp
|
|
} -start
|
|
|
|
# haproxy frontend
|
|
haproxy hap -conf {
|
|
global
|
|
.if feature(THREAD)
|
|
thread-groups 1
|
|
.endif
|
|
|
|
defaults
|
|
timeout client 30s
|
|
timeout server 30s
|
|
timeout connect 30s
|
|
mode http
|
|
|
|
listen feSrvH1
|
|
bind "fd@${feSrvH1}"
|
|
http-request return status 200
|
|
|
|
listen feSrvH2
|
|
bind "fd@${feSrvH2}" proto h2
|
|
http-request return status 200
|
|
|
|
listen fe1
|
|
bind "fd@${fe1}" proto h2
|
|
server srv-hapSrv "${hap_feSrvH1_addr}:${hap_feSrvH1_port}"
|
|
|
|
listen fe2
|
|
bind "fd@${fe2}" proto h2
|
|
server srv-hapSrv "${hap_feSrvH2_addr}:${hap_feSrvH2_port}" proto h2
|
|
|
|
listen fe3
|
|
bind "fd@${fe3}" proto h2
|
|
server s1 "${s1_addr}:${s1_port}"
|
|
} -start
|
|
|
|
# valid request
|
|
client c1 -connect ${hap_fe1_sock} {
|
|
txpri
|
|
stream 0 {
|
|
txsettings
|
|
rxsettings
|
|
txsettings -ack
|
|
rxsettings
|
|
expect settings.ack == true
|
|
} -run
|
|
|
|
stream 1 {
|
|
txreq \
|
|
-method "GET" \
|
|
-scheme "http" \
|
|
-url "/"
|
|
rxresp
|
|
expect resp.status == 200
|
|
} -run
|
|
} -run
|
|
|
|
# valid request
|
|
client c2 -connect ${hap_fe2_sock} {
|
|
txpri
|
|
stream 0 {
|
|
txsettings
|
|
rxsettings
|
|
txsettings -ack
|
|
rxsettings
|
|
expect settings.ack == true
|
|
} -run
|
|
|
|
stream 1 {
|
|
txreq \
|
|
-method "GET" \
|
|
-scheme "http" \
|
|
-url "/"
|
|
rxresp
|
|
expect resp.status == 200
|
|
} -run
|
|
} -run
|
|
|
|
# invalid path
|
|
client c3-path -connect ${hap_fe1_sock} {
|
|
txpri
|
|
stream 0 {
|
|
txsettings
|
|
rxsettings
|
|
txsettings -ack
|
|
rxsettings
|
|
expect settings.ack == true
|
|
} -run
|
|
|
|
stream 1 {
|
|
txreq \
|
|
-method "GET" \
|
|
-scheme "http" \
|
|
-url "hello-world"
|
|
rxrst
|
|
} -run
|
|
} -run
|
|
|
|
# invalid scheme
|
|
client c4-scheme -connect ${hap_fe1_sock} {
|
|
txpri
|
|
stream 0 {
|
|
txsettings
|
|
rxsettings
|
|
txsettings -ack
|
|
rxsettings
|
|
expect settings.ack == true
|
|
} -run
|
|
|
|
stream 1 {
|
|
txreq \
|
|
-method "GET" \
|
|
-scheme "http://localhost/?" \
|
|
-url "/"
|
|
rxresp
|
|
expect resp.status == 400
|
|
} -run
|
|
} -run
|
|
|
|
# invalid method
|
|
client c5-method -connect ${hap_fe2_sock} {
|
|
txpri
|
|
stream 0 {
|
|
txsettings
|
|
rxsettings
|
|
txsettings -ack
|
|
rxsettings
|
|
expect settings.ack == true
|
|
} -run
|
|
|
|
stream 1 {
|
|
txreq \
|
|
-method "GET?" \
|
|
-scheme "http" \
|
|
-url "/"
|
|
rxresp
|
|
expect resp.status == 400
|
|
} -run
|
|
} -run
|
|
|
|
# different authority and host headers
|
|
# in this case, host should be ignored in favor of the authority
|
|
client c6-host-authority -connect ${hap_fe3_sock} {
|
|
txpri
|
|
stream 0 {
|
|
txsettings
|
|
rxsettings
|
|
txsettings -ack
|
|
rxsettings
|
|
expect settings.ack == true
|
|
} -run
|
|
|
|
stream 1 {
|
|
txreq \
|
|
-method "GET" \
|
|
-scheme "http" \
|
|
-url "/" \
|
|
-hdr ":authority" "hostname" \
|
|
-hdr "host" "other_host"
|
|
rxhdrs
|
|
expect resp.status == 200
|
|
} -run
|
|
} -run
|
|
|
|
server s1 -wait
|