summaryrefslogtreecommitdiffstats
path: root/reg-tests/connection
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:18:05 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:18:05 +0000
commitb46aad6df449445a9fc4aa7b32bd40005438e3f7 (patch)
tree751aa858ca01f35de800164516b298887382919d /reg-tests/connection
parentInitial commit. (diff)
downloadhaproxy-b46aad6df449445a9fc4aa7b32bd40005438e3f7.tar.xz
haproxy-b46aad6df449445a9fc4aa7b32bd40005438e3f7.zip
Adding upstream version 2.9.5.upstream/2.9.5
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'reg-tests/connection')
l---------reg-tests/connection/ca-auth.crt1
-rw-r--r--reg-tests/connection/cli_src_dst.vtc290
l---------reg-tests/connection/client1.pem1
l---------reg-tests/connection/common.pem1
-rw-r--r--reg-tests/connection/dispatch.vtc42
-rw-r--r--reg-tests/connection/http_reuse_aggressive.vtc45
-rw-r--r--reg-tests/connection/http_reuse_always.vtc43
-rw-r--r--reg-tests/connection/http_reuse_be_transparent.vtc82
-rw-r--r--reg-tests/connection/http_reuse_conn_hash.vtc163
-rw-r--r--reg-tests/connection/http_reuse_dispatch.vtc79
-rw-r--r--reg-tests/connection/http_reuse_never.vtc79
-rw-r--r--reg-tests/connection/http_reuse_safe.vtc78
-rw-r--r--reg-tests/connection/proxy_protocol_random_fail.vtc59
-rw-r--r--reg-tests/connection/proxy_protocol_send_generic.vtc74
-rw-r--r--reg-tests/connection/proxy_protocol_send_unique_id.vtc42
-rw-r--r--reg-tests/connection/proxy_protocol_send_unique_id_alpn.vtc33
-rw-r--r--reg-tests/connection/proxy_protocol_tlv_validation.vtc142
-rw-r--r--reg-tests/connection/reverse_connect_full.vtc70
-rw-r--r--reg-tests/connection/reverse_server.vtc69
-rw-r--r--reg-tests/connection/reverse_server_name.vtc87
-rw-r--r--reg-tests/connection/tcp_to_http_upgrade.vtc169
21 files changed, 1649 insertions, 0 deletions
diff --git a/reg-tests/connection/ca-auth.crt b/reg-tests/connection/ca-auth.crt
new file mode 120000
index 0000000..815a970
--- /dev/null
+++ b/reg-tests/connection/ca-auth.crt
@@ -0,0 +1 @@
+../ssl/ca-auth.crt \ No newline at end of file
diff --git a/reg-tests/connection/cli_src_dst.vtc b/reg-tests/connection/cli_src_dst.vtc
new file mode 100644
index 0000000..6809d39
--- /dev/null
+++ b/reg-tests/connection/cli_src_dst.vtc
@@ -0,0 +1,290 @@
+varnishtest "Test multi-level client source and destination addresses"
+
+feature cmd "$HAPROXY_PROGRAM -cc 'version_atleast(2.5-dev0)'"
+feature ignore_unknown_macro
+
+haproxy h1 -conf {
+ defaults
+ mode http
+ timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
+
+ frontend fe1
+ bind "fd@${fe1}"
+ tcp-request connection set-src ipv4(10.0.0.1)
+ tcp-request connection set-dst ipv4(10.0.0.2)
+
+ tcp-request session set-var(sess.sess_fc_src) fc_src
+ tcp-request session set-var(sess.sess_fc_dst) fc_dst
+ tcp-request session set-var(sess.sess_src) src
+ tcp-request session set-var(sess.sess_dst) dst
+
+ tcp-request inspect-delay 100ms
+ tcp-request content set-var(txn.strm_fc_src) fc_src
+ tcp-request content set-var(txn.strm_fc_dst) fc_dst
+ tcp-request content set-var(txn.strm_src) src
+ tcp-request content set-var(txn.strm_dst) dst
+
+ http-after-response set-header sess-fc-src %[var(sess.sess_fc_src)]
+ http-after-response set-header sess-src %[var(sess.sess_src)]
+ http-after-response set-header sess-fc-dst %[var(sess.sess_fc_dst)]
+ http-after-response set-header sess-dst %[var(sess.sess_dst)]
+ http-after-response set-header strm-fc-src %[var(txn.strm_fc_src)]
+ http-after-response set-header strm-src %[var(txn.strm_src)]
+ http-after-response set-header strm-fc-dst %[var(txn.strm_fc_dst)]
+ http-after-response set-header strm-dst %[var(txn.strm_dst)]
+
+ default_backend be
+
+ frontend fe2
+ bind "fd@${fe2}"
+ tcp-request connection set-src ipv4(10.0.0.1)
+ tcp-request connection set-dst ipv4(10.0.0.2)
+
+ tcp-request session set-src ipv4(10.1.0.1)
+ tcp-request session set-dst ipv4(10.1.0.2)
+ tcp-request session set-var(sess.sess_fc_src) fc_src
+ tcp-request session set-var(sess.sess_fc_dst) fc_dst
+ tcp-request session set-var(sess.sess_src) src
+ tcp-request session set-var(sess.sess_dst) dst
+
+ tcp-request inspect-delay 100ms
+ tcp-request content set-var(txn.strm_fc_src) fc_src
+ tcp-request content set-var(txn.strm_fc_dst) fc_dst
+ tcp-request content set-var(txn.strm_src) src
+ tcp-request content set-var(txn.strm_dst) dst
+
+ http-after-response set-header sess-fc-src %[var(sess.sess_fc_src)]
+ http-after-response set-header sess-src %[var(sess.sess_src)]
+ http-after-response set-header sess-fc-dst %[var(sess.sess_fc_dst)]
+ http-after-response set-header sess-dst %[var(sess.sess_dst)]
+ http-after-response set-header strm-fc-src %[var(txn.strm_fc_src)]
+ http-after-response set-header strm-src %[var(txn.strm_src)]
+ http-after-response set-header strm-fc-dst %[var(txn.strm_fc_dst)]
+ http-after-response set-header strm-dst %[var(txn.strm_dst)]
+
+ default_backend be
+
+ frontend fe3
+ bind "fd@${fe3}"
+ tcp-request connection set-src ipv4(10.0.0.1)
+ tcp-request connection set-dst ipv4(10.0.0.2)
+
+ tcp-request session set-src ipv4(10.1.0.1)
+ tcp-request session set-dst ipv4(10.1.0.2)
+ tcp-request session set-var(sess.sess_fc_src) fc_src
+ tcp-request session set-var(sess.sess_fc_dst) fc_dst
+ tcp-request session set-var(sess.sess_src) src
+ tcp-request session set-var(sess.sess_dst) dst
+
+ tcp-request inspect-delay 100ms
+ tcp-request content set-src ipv4(10.2.0.1)
+ tcp-request content set-dst ipv4(10.2.0.2)
+ tcp-request content set-var(txn.strm_fc_src) fc_src
+ tcp-request content set-var(txn.strm_fc_dst) fc_dst
+ tcp-request content set-var(txn.strm_src) src
+ tcp-request content set-var(txn.strm_dst) dst
+
+ http-after-response set-header sess-fc-src %[var(sess.sess_fc_src)]
+ http-after-response set-header sess-src %[var(sess.sess_src)]
+ http-after-response set-header sess-fc-dst %[var(sess.sess_fc_dst)]
+ http-after-response set-header sess-dst %[var(sess.sess_dst)]
+ http-after-response set-header strm-fc-src %[var(txn.strm_fc_src)]
+ http-after-response set-header strm-src %[var(txn.strm_src)]
+ http-after-response set-header strm-fc-dst %[var(txn.strm_fc_dst)]
+ http-after-response set-header strm-dst %[var(txn.strm_dst)]
+
+
+ frontend fe4
+ bind "fd@${fe4}"
+
+ tcp-request connection set-src ipv4(10.0.0.1)
+ tcp-request connection set-dst ipv4(10.0.0.2)
+
+ tcp-request session set-var(sess.sess_fc_src) fc_src
+ tcp-request session set-var(sess.sess_fc_dst) fc_dst
+ tcp-request session set-var(sess.sess_src) src
+ tcp-request session set-var(sess.sess_dst) dst
+
+ http-request set-src hdr(x-forwarded-for)
+ http-request set-dst hdr(x-original-to)
+ http-request set-var(txn.strm_fc_src) fc_src
+ http-request set-var(txn.strm_fc_dst) fc_dst
+ http-request set-var(txn.strm_src) src
+ http-request set-var(txn.strm_dst) dst
+
+ http-after-response set-header sess-fc-src %[var(sess.sess_fc_src)]
+ http-after-response set-header sess-src %[var(sess.sess_src)]
+ http-after-response set-header sess-fc-dst %[var(sess.sess_fc_dst)]
+ http-after-response set-header sess-dst %[var(sess.sess_dst)]
+ http-after-response set-header strm-fc-src %[var(txn.strm_fc_src)]
+ http-after-response set-header strm-src %[var(txn.strm_src)]
+ http-after-response set-header strm-fc-dst %[var(txn.strm_fc_dst)]
+ http-after-response set-header strm-dst %[var(txn.strm_dst)]
+
+ default_backend be
+
+ backend be
+ http-request return status 200
+
+ listen li1
+ bind "fd@${li1}"
+
+ tcp-request connection set-src ipv4(10.0.0.1)
+ tcp-request connection set-dst ipv4(10.0.0.2)
+
+ http-request set-src ipv4(192.168.0.1)
+ http-request set-dst ipv4(192.168.0.2)
+
+ http-after-response set-header li1-fc-src %[fc_src]
+ http-after-response set-header li1-src %[src]
+ http-after-response set-header li1-fc-dst %[fc_dst]
+ http-after-response set-header li1-dst %[dst]
+
+
+ server srv ${h1_li3_addr}:${h1_li3_port} send-proxy
+
+ listen li2
+ bind "fd@${li2}"
+
+ tcp-request connection set-src ipv4(10.0.0.1)
+ tcp-request connection set-dst ipv4(10.0.0.2)
+
+ http-request set-src ipv4(192.168.0.1)
+ http-request set-dst ipv4(192.168.0.2)
+
+ http-after-response set-header li2-fc-src %[fc_src]
+ http-after-response set-header li2-src %[src]
+ http-after-response set-header li2-fc-dst %[fc_dst]
+ http-after-response set-header li2-dst %[dst]
+
+ server srv ${h1_li3_addr}:${h1_li3_port} send-proxy-v2
+
+ listen li3
+ bind "fd@${li3}" accept-proxy
+
+ tcp-request connection set-src ipv4(10.1.0.1)
+ tcp-request connection set-dst ipv4(10.1.0.2)
+
+ http-after-response set-header li3-fc-src %[fc_src]
+ http-after-response set-header li3-src %[src]
+ http-after-response set-header li3-fc-dst %[fc_dst]
+ http-after-response set-header li3-dst %[dst]
+
+ http-request return status 200
+
+} -start
+
+
+client c1 -connect ${h1_fe1_sock} {
+ txreq
+ rxresp
+ expect resp.http.sess-fc-src == 10.0.0.1
+ expect resp.http.sess-src == 10.0.0.1
+ expect resp.http.strm-fc-src == 10.0.0.1
+ expect resp.http.strm-src == 10.0.0.1
+
+ expect resp.http.sess-fc-dst == 10.0.0.2
+ expect resp.http.sess-dst == 10.0.0.2
+ expect resp.http.strm-fc-dst == 10.0.0.2
+ expect resp.http.strm-dst == 10.0.0.2
+} -run
+
+client c2 -connect ${h1_fe2_sock} {
+ txreq
+ rxresp
+ expect resp.http.sess-fc-src == 10.0.0.1
+ expect resp.http.sess-src == 10.1.0.1
+ expect resp.http.strm-fc-src == 10.0.0.1
+ expect resp.http.strm-src == 10.1.0.1
+
+ expect resp.http.sess-fc-dst == 10.0.0.2
+ expect resp.http.sess-dst == 10.1.0.2
+ expect resp.http.strm-fc-dst == 10.0.0.2
+ expect resp.http.strm-dst == 10.1.0.2
+} -run
+
+client c3 -connect ${h1_fe3_sock} {
+ txreq
+ rxresp
+ expect resp.http.sess-fc-src == 10.0.0.1
+ expect resp.http.sess-src == 10.1.0.1
+ expect resp.http.strm-fc-src == 10.0.0.1
+ expect resp.http.strm-src == 10.2.0.1
+
+ expect resp.http.sess-fc-dst == 10.0.0.2
+ expect resp.http.sess-dst == 10.1.0.2
+ expect resp.http.strm-fc-dst == 10.0.0.2
+ expect resp.http.strm-dst == 10.2.0.2
+} -run
+
+client c4 -connect ${h1_fe4_sock} {
+ txreq \
+ -hdr "x-forwarded-for: 192.168.0.1" \
+ -hdr "x-original-to: 192.168.0.2"
+ rxresp
+ expect resp.http.sess-fc-src == 10.0.0.1
+ expect resp.http.sess-src == 10.0.0.1
+ expect resp.http.strm-fc-src == 10.0.0.1
+ expect resp.http.strm-src == 192.168.0.1
+
+ expect resp.http.sess-fc-dst == 10.0.0.2
+ expect resp.http.sess-dst == 10.0.0.2
+ expect resp.http.strm-fc-dst == 10.0.0.2
+ expect resp.http.strm-dst == 192.168.0.2
+
+ txreq \
+ -hdr "x-forwarded-for: 192.168.1.1" \
+ -hdr "x-original-to: 192.168.1.2"
+ rxresp
+ expect resp.http.sess-fc-src == 10.0.0.1
+ expect resp.http.sess-src == 10.0.0.1
+ expect resp.http.strm-fc-src == 10.0.0.1
+ expect resp.http.strm-src == 192.168.1.1
+
+ expect resp.http.sess-fc-dst == 10.0.0.2
+ expect resp.http.sess-dst == 10.0.0.2
+ expect resp.http.strm-fc-dst == 10.0.0.2
+ expect resp.http.strm-dst == 192.168.1.2
+
+ txreq
+ rxresp
+ expect resp.http.sess-fc-src == 10.0.0.1
+ expect resp.http.sess-src == 10.0.0.1
+ expect resp.http.strm-fc-src == 10.0.0.1
+ expect resp.http.strm-src == 10.0.0.1
+
+ expect resp.http.sess-fc-dst == 10.0.0.2
+ expect resp.http.sess-dst == 10.0.0.2
+ expect resp.http.strm-fc-dst == 10.0.0.2
+ expect resp.http.strm-dst == 10.0.0.2
+} -run
+
+client c5 -connect ${h1_li1_sock} {
+ txreq
+ rxresp
+ expect resp.http.li1-fc-src == 10.0.0.1
+ expect resp.http.li1-src == 192.168.0.1
+ expect resp.http.li1-fc-dst == 10.0.0.2
+ expect resp.http.li1-dst == 192.168.0.2
+
+ expect resp.http.li3-fc-src == 10.1.0.1
+ expect resp.http.li3-src == 192.168.0.1
+ expect resp.http.li3-fc-dst == 10.1.0.2
+ expect resp.http.li3-dst == 192.168.0.2
+} -run
+
+client c6 -connect ${h1_li2_sock} {
+ txreq
+ rxresp
+ expect resp.http.li2-fc-src == 10.0.0.1
+ expect resp.http.li2-src == 192.168.0.1
+ expect resp.http.li2-fc-dst == 10.0.0.2
+ expect resp.http.li2-dst == 192.168.0.2
+
+ expect resp.http.li3-fc-src == 10.1.0.1
+ expect resp.http.li3-src == 192.168.0.1
+ expect resp.http.li3-fc-dst == 10.1.0.2
+ expect resp.http.li3-dst == 192.168.0.2
+} -run
diff --git a/reg-tests/connection/client1.pem b/reg-tests/connection/client1.pem
new file mode 120000
index 0000000..c4d14f0
--- /dev/null
+++ b/reg-tests/connection/client1.pem
@@ -0,0 +1 @@
+../ssl/client1.pem \ No newline at end of file
diff --git a/reg-tests/connection/common.pem b/reg-tests/connection/common.pem
new file mode 120000
index 0000000..a4433d5
--- /dev/null
+++ b/reg-tests/connection/common.pem
@@ -0,0 +1 @@
+../ssl/common.pem \ No newline at end of file
diff --git a/reg-tests/connection/dispatch.vtc b/reg-tests/connection/dispatch.vtc
new file mode 100644
index 0000000..8696b50
--- /dev/null
+++ b/reg-tests/connection/dispatch.vtc
@@ -0,0 +1,42 @@
+varnishtest "Validate proper operation of the 'dispatch' mode"
+feature ignore_unknown_macro
+
+server s1 {
+ rxreq
+ txresp
+} -start
+
+server s2 {
+ rxreq
+ txresp
+} -start
+
+haproxy h1 -conf {
+defaults
+ log global
+ timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
+
+listen fe_tcp
+ bind "fd@${fe_tcp}"
+ mode tcp
+ dispatch ${s1_addr}:${s1_port}
+
+listen fe_http
+ bind "fd@${fe_http}"
+ mode http
+ dispatch ${s2_addr}:${s2_port}
+} -start
+
+client c1 -connect ${h1_fe_tcp_sock} {
+ txreq -url "/"
+ rxresp
+ expect resp.status == 200
+} -run
+
+client c2 -connect ${h1_fe_http_sock} {
+ txreq -url "/"
+ rxresp
+ expect resp.status == 200
+} -run
diff --git a/reg-tests/connection/http_reuse_aggressive.vtc b/reg-tests/connection/http_reuse_aggressive.vtc
new file mode 100644
index 0000000..71f4cee
--- /dev/null
+++ b/reg-tests/connection/http_reuse_aggressive.vtc
@@ -0,0 +1,45 @@
+varnishtest "Test the http-reuse aggressive mode"
+
+#REQUIRE_VERSION=2.2
+
+feature ignore_unknown_macro
+
+haproxy h1 -conf {
+ defaults
+ mode http
+
+ listen sender
+ bind "fd@${feS}"
+ http-reuse aggressive
+ server srv ${h1_feR_addr}:${h1_feR_port}
+
+ listen receiver
+ bind "fd@${feR}"
+ http-request return status 200
+ http-after-response set-header http_first_request %[http_first_req]
+} -start
+
+# bootstrap
+client c1 -connect ${h1_feS_sock} {
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "1"
+} -run
+
+# first request should not be reused as no safe connection for the moment
+client c2 -connect ${h1_feS_sock} {
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "1"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+} -run
+
+# first request must be reused with the safe connection
+client c3 -connect ${h1_feS_sock} {
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+} -run
diff --git a/reg-tests/connection/http_reuse_always.vtc b/reg-tests/connection/http_reuse_always.vtc
new file mode 100644
index 0000000..3dbd7c0
--- /dev/null
+++ b/reg-tests/connection/http_reuse_always.vtc
@@ -0,0 +1,43 @@
+varnishtest "Test the http-reuse always mode"
+
+#REQUIRE_VERSION=2.2
+
+feature ignore_unknown_macro
+
+haproxy h1 -W -conf {
+ defaults
+ mode http
+
+ listen sender
+ bind "fd@${feS}"
+ http-reuse always
+ server srv ${h1_feR_addr}:${h1_feR_port}
+
+ listen receiver
+ bind "fd@${feR}"
+ http-request return status 200
+ http-after-response set-header http_first_request %[http_first_req]
+} -start
+
+# bootstrap
+client c1 -connect ${h1_feS_sock} {
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "1"
+} -run
+
+client c2 -connect ${h1_feS_sock} {
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+} -run
+
+client c3 -connect ${h1_feS_sock} {
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+} -run
diff --git a/reg-tests/connection/http_reuse_be_transparent.vtc b/reg-tests/connection/http_reuse_be_transparent.vtc
new file mode 100644
index 0000000..3fb9e7a
--- /dev/null
+++ b/reg-tests/connection/http_reuse_be_transparent.vtc
@@ -0,0 +1,82 @@
+varnishtest "Test the proper interaction between http-reuse and backend in transparent mode"
+feature cmd "$HAPROXY_PROGRAM -cc 'feature(TPROXY)'"
+
+# If backend is used with the transparent mode, the connection are considered
+# as private and should only be reused for requests of the same session.
+# This is similar to the http-reuse never mode
+
+#REQUIRE_VERSION=2.4
+
+feature ignore_unknown_macro
+
+haproxy h1 -conf {
+ defaults
+ mode http
+
+ listen sender
+ bind "fd@${feS}"
+ http-request set-header client-id %[req.hdr(client-id)] if { req.hdr(client-id) -m found }
+ option transparent
+ http-request set-dst-port int(${h1_feR_port})
+
+ listen receiver
+ bind "fd@${feR}"
+ http-request set-var(sess.client_id) req.hdr(client-id)
+ http-request return status 200
+ http-after-response set-header http_first_request %[http_first_req]
+ http-after-response set-header client-id %[var(sess.client_id)]
+} -start
+
+client c1 -connect ${h1_feS_sock} {
+ txreq \
+ -hdr "client-id: c1"
+ rxresp
+ expect resp.http.http_first_request == "1"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c1"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c1"
+} -run
+
+client c2 -connect ${h1_feS_sock} {
+ txreq \
+ -hdr "client-id: c2"
+ rxresp
+ expect resp.http.http_first_request == "1"
+ expect resp.http.client-id == "c2"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c2"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c2"
+} -run
+
+client c3 -connect ${h1_feS_sock} {
+ txreq \
+ -hdr "client-id: c3"
+ rxresp
+ expect resp.http.http_first_request == "1"
+ expect resp.http.client-id == "c3"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c3"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c3"
+} -run
+
diff --git a/reg-tests/connection/http_reuse_conn_hash.vtc b/reg-tests/connection/http_reuse_conn_hash.vtc
new file mode 100644
index 0000000..991e86f
--- /dev/null
+++ b/reg-tests/connection/http_reuse_conn_hash.vtc
@@ -0,0 +1,163 @@
+varnishtest "Test the http-reuse with special connection parameters"
+#REQUIRE_VERSION=2.4
+#REQUIRE_OPTIONS=OPENSSL
+
+feature ignore_unknown_macro
+
+haproxy h1 -conf {
+ defaults
+ mode http
+
+ # sni
+ listen sender-sni
+ bind "fd@${feS_sni}"
+ server srv2 ${h1_feR_ssl_addr}:${h1_feR_ssl_port} ssl sni "req.hdr(x-sni)" verify none pool-low-conn 2
+
+ # set-dst
+ # specify dst1_addr for server, which should be identical to dst2_addr
+ # port is specified by the client in header x-dst-port
+ listen sender-set-dst
+ bind "fd@${feS_dst}"
+ http-request set-dst-port hdr(x-dst-port)
+ server srv2 ${h1_feR_dst1_addr}:0 pool-low-conn 2
+
+ # proxy protocol
+ # must use reuse always as consecutive requests are from different client
+ listen sender-proxy
+ bind "fd@${feS_proxy}" accept-proxy
+ http-reuse always
+ server srv2 ${h1_feR_proxy_addr}:${h1_feR_proxy_port} send-proxy pool-low-conn 2
+
+ listen receiver
+ bind "fd@${feR_ssl}" ssl crt ${testdir}/common.pem
+ bind "fd@${feR_proxy}" accept-proxy
+ http-request return status 200
+ http-after-response set-header http_first_request %[http_first_req]
+
+ listen receiver-dst1
+ bind "fd@${feR_dst1}"
+ http-request return status 200 hdr "x-dst" "dst1"
+ http-after-response set-header http_first_request %[http_first_req]
+
+ listen receiver-dst2
+ bind "fd@${feR_dst2}"
+ http-request return status 200 hdr "x-dst" "dst2"
+ http-after-response set-header http_first_request %[http_first_req]
+} -start
+
+# http-reuse with sni parameters
+client c_sni -connect ${h1_feS_sni_sock} {
+ # first request
+ txreq \
+ -hdr "x-sni: www.custom.com"
+ rxresp
+ expect resp.http.http_first_request == "1"
+
+ # second request with same sni, connection must be reused
+ txreq \
+ -hdr "x-sni: www.custom.com"
+ rxresp
+ expect resp.http.http_first_request == "0"
+
+ # third request with a different sni, a new connection must be used
+ txreq \
+ -hdr "x-sni: www.custom2.com"
+ rxresp
+ expect resp.http.http_first_request == "1"
+
+ # fourth request, reuse sni2
+ txreq \
+ -hdr "x-sni: www.custom2.com"
+ rxresp
+ expect resp.http.http_first_request == "0"
+} -run
+
+# http-reuse with destination address
+client c_dst1 -connect ${h1_feS_dst_sock} {
+ txreq \
+ -hdr "x-dst-port: ${h1_feR_dst1_port}"
+ rxresp
+ expect resp.status == 200
+ expect resp.http.x-dst == "dst1"
+ expect resp.http.http_first_request == "1"
+
+ txreq \
+ -hdr "x-dst-port: ${h1_feR_dst1_port}"
+ rxresp
+ expect resp.status == 200
+ expect resp.http.x-dst == "dst1"
+ expect resp.http.http_first_request == "0"
+
+ txreq \
+ -hdr "x-dst-port: ${h1_feR_dst2_port}"
+ rxresp
+ expect resp.status == 200
+ expect resp.http.x-dst == "dst2"
+ expect resp.http.http_first_request == "1"
+
+ txreq \
+ -hdr "x-dst-port: ${h1_feR_dst1_port}"
+ rxresp
+ expect resp.status == 200
+ expect resp.http.x-dst == "dst1"
+ expect resp.http.http_first_request == "0"
+
+ txreq \
+ -hdr "x-dst-port: ${h1_feR_dst2_port}"
+ rxresp
+ expect resp.status == 200
+ expect resp.http.x-dst == "dst2"
+ expect resp.http.http_first_request == "0"
+} -run
+
+## first request with proxy protocol
+client c_proxy -connect ${h1_feS_proxy_sock} -proxy1 "127.0.0.1:40000 ${h1_feS_proxy_addr}:${h1_feS_proxy_port}" {
+ txreq
+ rxresp
+ expect resp.status == 200
+ expect resp.http.http_first_request == "1"
+
+ txreq
+ rxresp
+ expect resp.status == 200
+ expect resp.http.http_first_request == "0"
+} -run
+
+## second request with different proxy protocol
+# this have the nice effect to fill the server pool to 2 connection
+# (pool-low-conn value) to allow takeover on multi thread run
+client c_proxy -connect ${h1_feS_proxy_sock} -proxy1 "127.0.0.1:50000 ${h1_feS_proxy_addr}:${h1_feS_proxy_port}" {
+ txreq
+ rxresp
+ expect resp.status == 200
+ expect resp.http.http_first_request == "1"
+} -run
+
+## third request, reuse same proxy protocol entry
+client c_proxy -connect ${h1_feS_proxy_sock} -proxy1 "127.0.0.1:40000 ${h1_feS_proxy_addr}:${h1_feS_proxy_port}" {
+ txreq
+ rxresp
+ expect resp.status == 200
+ expect resp.http.http_first_request == "0"
+} -run
+
+## fourth request with different proxy protocol entry, no reuse
+client c_proxy -connect ${h1_feS_proxy_sock} -proxy1 "127.0.0.1:60000 ${h1_feS_proxy_addr}:${h1_feS_proxy_port}" {
+ txreq
+ rxresp
+ expect resp.status == 200
+ expect resp.http.http_first_request == "1"
+} -run
+
+## fifth request, reuse proxy protocol
+client c_proxy -connect ${h1_feS_proxy_sock} -proxy1 "127.0.0.1:50000 ${h1_feS_proxy_addr}:${h1_feS_proxy_port}" {
+ txreq
+ rxresp
+ expect resp.status == 200
+ expect resp.http.http_first_request == "0"
+
+ txreq
+ rxresp
+ expect resp.status == 200
+ expect resp.http.http_first_request == "0"
+} -run
diff --git a/reg-tests/connection/http_reuse_dispatch.vtc b/reg-tests/connection/http_reuse_dispatch.vtc
new file mode 100644
index 0000000..a419727
--- /dev/null
+++ b/reg-tests/connection/http_reuse_dispatch.vtc
@@ -0,0 +1,79 @@
+varnishtest "Test the proper interaction between http-reuse and dispatch mode"
+
+# With dispatch, the connection are considered as private and should only be
+# reused for requests of the same session
+# This is similar to the http-reuse never mode
+
+#REQUIRE_VERSION=2.4
+
+feature ignore_unknown_macro
+
+haproxy h1 -conf {
+ defaults
+ mode http
+
+ listen sender
+ bind "fd@${feS}"
+ http-request set-header client-id %[req.hdr(client-id)] if { req.hdr(client-id) -m found }
+ dispatch ${h1_feR_addr}:${h1_feR_port}
+
+ listen receiver
+ bind "fd@${feR}"
+ http-request set-var(sess.client_id) req.hdr(client-id)
+ http-request return status 200
+ http-after-response set-header http_first_request %[http_first_req]
+ http-after-response set-header client-id %[var(sess.client_id)]
+} -start
+
+client c1 -connect ${h1_feS_sock} {
+ txreq \
+ -hdr "client-id: c1"
+ rxresp
+ expect resp.http.http_first_request == "1"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c1"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c1"
+} -run
+
+client c2 -connect ${h1_feS_sock} {
+ txreq \
+ -hdr "client-id: c2"
+ rxresp
+ expect resp.http.http_first_request == "1"
+ expect resp.http.client-id == "c2"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c2"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c2"
+} -run
+
+client c3 -connect ${h1_feS_sock} {
+ txreq \
+ -hdr "client-id: c3"
+ rxresp
+ expect resp.http.http_first_request == "1"
+ expect resp.http.client-id == "c3"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c3"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c3"
+} -run
diff --git a/reg-tests/connection/http_reuse_never.vtc b/reg-tests/connection/http_reuse_never.vtc
new file mode 100644
index 0000000..fc74631
--- /dev/null
+++ b/reg-tests/connection/http_reuse_never.vtc
@@ -0,0 +1,79 @@
+varnishtest "Test the http-reuse never mode"
+
+#REQUIRE_VERSION=2.2
+
+feature ignore_unknown_macro
+
+haproxy h1 -conf {
+ defaults
+ mode http
+
+ # limit idle pool to one connection
+ # this is to mirror http-reuse safe test, but in this case to ensure that
+ # connection are never reused as expected
+ listen sender
+ bind "fd@${feS}"
+ http-reuse never
+ http-request set-header client-id %[req.hdr(client-id)] if { req.hdr(client-id) -m found }
+ server srv ${h1_feR_addr}:${h1_feR_port} pool-max-conn 1
+
+ listen receiver
+ bind "fd@${feR}"
+ http-request set-var(sess.client_id) req.hdr(client-id)
+ http-request return status 200
+ http-after-response set-header http_first_request %[http_first_req]
+ http-after-response set-header client-id %[var(sess.client_id)]
+} -start
+
+client c1 -connect ${h1_feS_sock} {
+ txreq \
+ -hdr "client-id: c1"
+ rxresp
+ expect resp.http.http_first_request == "1"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c1"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c1"
+} -run
+
+client c2 -connect ${h1_feS_sock} {
+ txreq \
+ -hdr "client-id: c2"
+ rxresp
+ expect resp.http.http_first_request == "1"
+ expect resp.http.client-id == "c2"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c2"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c2"
+} -run
+
+client c3 -connect ${h1_feS_sock} {
+ txreq \
+ -hdr "client-id: c3"
+ rxresp
+ expect resp.http.http_first_request == "1"
+ expect resp.http.client-id == "c3"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c3"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c3"
+} -run
diff --git a/reg-tests/connection/http_reuse_safe.vtc b/reg-tests/connection/http_reuse_safe.vtc
new file mode 100644
index 0000000..fa00dd4
--- /dev/null
+++ b/reg-tests/connection/http_reuse_safe.vtc
@@ -0,0 +1,78 @@
+varnishtest "Test the http-reuse safe mode"
+
+#REQUIRE_VERSION=2.2
+
+feature ignore_unknown_macro
+
+haproxy h1 -conf {
+ defaults
+ mode http
+
+ # limit idle pool to one connection
+ # this forces connection reuse for the transaction after the first one
+ listen sender
+ bind "fd@${feS}"
+ http-reuse safe
+ http-request set-header client-id %[req.hdr(client-id)] if { req.hdr(client-id) -m found }
+ server srv ${h1_feR_addr}:${h1_feR_port} pool-max-conn 1
+
+ listen receiver
+ bind "fd@${feR}"
+ http-request set-var(sess.client_id) req.hdr(client-id)
+ http-request return status 200
+ http-after-response set-header http_first_request %[http_first_req]
+ http-after-response set-header client-id %[var(sess.client_id)]
+} -start
+
+client c1 -connect ${h1_feS_sock} {
+ txreq \
+ -hdr "client-id: c1"
+ rxresp
+ expect resp.http.http_first_request == "1"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c1"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c1"
+} -run
+
+client c2 -connect ${h1_feS_sock} {
+ txreq \
+ -hdr "client-id: c2"
+ rxresp
+ expect resp.http.http_first_request == "1"
+ expect resp.http.client-id == "c2"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c1"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c1"
+} -run
+
+client c3 -connect ${h1_feS_sock} {
+ txreq \
+ -hdr "client-id: c3"
+ rxresp
+ expect resp.http.http_first_request == "1"
+ expect resp.http.client-id == "c3"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c1"
+
+ txreq
+ rxresp
+ expect resp.http.http_first_request == "0"
+ expect resp.http.client-id == "c1"
+} -run
diff --git a/reg-tests/connection/proxy_protocol_random_fail.vtc b/reg-tests/connection/proxy_protocol_random_fail.vtc
new file mode 100644
index 0000000..1ae33de
--- /dev/null
+++ b/reg-tests/connection/proxy_protocol_random_fail.vtc
@@ -0,0 +1,59 @@
+#commit b406b87
+# BUG/MEDIUM: connection: don't store recv() result into trash.data
+#
+# Cyril Bonté discovered that the proxy protocol randomly fails since
+# commit 843b7cb ("MEDIUM: chunks: make the chunk struct's fields match
+# the buffer struct"). This is because we used to store recv()'s return
+# code into trash.data which is now unsigned, so it never compares as
+# negative against 0. Let's clean this up and test the result itself
+# without storing it first.
+
+varnishtest "PROXY protocol random failures"
+#REQUIRE_OPTIONS=OPENSSL
+
+feature ignore_unknown_macro
+
+#REGTEST_TYPE=broken
+
+syslog Slog_1 -repeat 8 -level info {
+ recv
+ expect ~ "Connect from .* to ${h1_ssl_addr}:${h1_ssl_port}"
+ recv
+ expect ~ "ssl-offload-http/http .* \"POST (https://.*:${h1_ssl_port})?/[1-8] HTTP/(2\\.0|1\\.1)\""
+} -start
+
+haproxy h1 -conf {
+ global
+ tune.ssl.default-dh-param 2048
+ log ${Slog_1_addr}:${Slog_1_port} len 2048 local0 debug err
+
+ defaults
+ mode http
+ timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+ log global
+
+ listen http
+ bind unix@"${tmpdir}/http.socket" accept-proxy name ssl-offload-http
+ option forwardfor
+
+ listen ssl-offload-http
+ option httplog
+ bind "fd@${ssl}" ssl crt ${testdir}/common.pem ssl no-sslv3 alpn h2,http/1.1
+ server http unix@"${tmpdir}/http.socket" send-proxy
+} -start
+
+
+shell {
+ HOST=${h1_ssl_addr}
+ if [ "$HOST" = "::1" ] ; then
+ HOST="\[::1\]"
+ fi
+ for i in 1 2 3 4 5 6 7 8 ; do
+ urls="$urls https://$HOST:${h1_ssl_port}/$i"
+ done
+ curl -i -k -d 'x=x' $urls & wait $!
+}
+
+syslog Slog_1 -wait
diff --git a/reg-tests/connection/proxy_protocol_send_generic.vtc b/reg-tests/connection/proxy_protocol_send_generic.vtc
new file mode 100644
index 0000000..605f38c
--- /dev/null
+++ b/reg-tests/connection/proxy_protocol_send_generic.vtc
@@ -0,0 +1,74 @@
+varnishtest "Check that generic TLV IDs are sent properly"
+
+#REQUIRE_VERSION=2.2
+
+feature ignore_unknown_macro
+
+haproxy h1 -conf {
+ defaults
+ mode http
+ log global
+
+ timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
+
+ listen sender
+ bind "fd@${feS}"
+ server example ${h1_feR_addr}:${h1_feR_port} send-proxy-v2 set-proxy-v2-tlv-fmt(0xE1) %[str("foo")] set-proxy-v2-tlv-fmt(0xE2)
+
+ listen receiver
+ bind "fd@${feR}" accept-proxy
+
+ # Check that the TLV value is set in the backend.
+ http-request set-var(txn.custom_tlv_a) fc_pp_tlv(0xE1)
+ http-after-response set-header proxy_custom_tlv_a %[var(txn.custom_tlv_a)]
+
+ # Check that TLVs without an value are sent out.
+ http-request set-var(txn.custom_tlv_b) fc_pp_tlv(0xE2)
+ http-after-response set-header proxy_custom_tlv_b %[var(txn.custom_tlv_b)]
+
+ # Note that we do not check for an invalid TLV ID as that would result in an
+ # parser error anyway.
+
+ http-request return status 200
+} -start
+
+
+client c1 -connect ${h1_feS_sock} {
+ txreq -url "/"
+ rxresp
+ expect resp.http.proxy_custom_tlv_a == "foo"
+ expect resp.http.proxy_custom_tlv_b == ""
+} -run
+
+# Ensure that we achieve the same via a default-server.
+haproxy h2 -conf {
+ defaults
+ mode http
+ log global
+
+ timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
+
+ listen sender
+ bind "fd@${feS}"
+ default-server send-proxy-v2 set-proxy-v2-tlv-fmt(0xE1) %[str("bar")]
+ server example ${h1_feR_addr}:${h1_feR_port}
+
+ listen receiver
+ bind "fd@${feR}" accept-proxy
+
+ http-request set-var(txn.custom_tlv_a) fc_pp_tlv(0xE1)
+ http-after-response set-header proxy_custom_tlv_a %[var(txn.custom_tlv_a)]
+
+ http-request return status 200
+} -start
+
+
+client c2 -connect ${h2_feS_sock} {
+ txreq -url "/"
+ rxresp
+ expect resp.http.proxy_custom_tlv_a == "bar"
+} -run
diff --git a/reg-tests/connection/proxy_protocol_send_unique_id.vtc b/reg-tests/connection/proxy_protocol_send_unique_id.vtc
new file mode 100644
index 0000000..4f6b848
--- /dev/null
+++ b/reg-tests/connection/proxy_protocol_send_unique_id.vtc
@@ -0,0 +1,42 @@
+varnishtest "Check that the unique ID TLV is properly sent"
+
+#REQUIRE_VERSION=2.2
+
+feature ignore_unknown_macro
+
+haproxy h1 -conf {
+ defaults
+ mode http
+ log global
+ unique-id-format %{+X}o\ TEST-%[req.hdr(in)]
+
+ listen sender
+ bind "fd@${feS}"
+
+ unique-id-header unique_id
+
+ server example ${h1_feR_addr}:${h1_feR_port} send-proxy-v2 proxy-v2-options unique-id
+
+ listen receiver
+ bind "fd@${feR}" accept-proxy
+
+ http-request set-var(txn.http_unique_id) req.hdr(unique_id)
+ http-request set-var(txn.proxy_unique_id) fc_pp_unique_id
+ http-after-response set-header http_unique_id %[var(txn.http_unique_id)]
+ http-after-response set-header proxy_unique_id %[var(txn.proxy_unique_id)]
+ http-request return status 200
+} -start
+
+# Validate that a correct header passes
+client c1 -connect ${h1_feS_sock} {
+ txreq -url "/" \
+ -hdr "in: foo"
+ rxresp
+ expect resp.http.http_unique_id == "TEST-foo"
+ expect resp.http.proxy_unique_id == "TEST-foo"
+ txreq -url "/" \
+ -hdr "in: bar"
+ rxresp
+ expect resp.http.http_unique_id == "TEST-bar"
+ expect resp.http.proxy_unique_id == "TEST-bar"
+} -run
diff --git a/reg-tests/connection/proxy_protocol_send_unique_id_alpn.vtc b/reg-tests/connection/proxy_protocol_send_unique_id_alpn.vtc
new file mode 100644
index 0000000..87e590a
--- /dev/null
+++ b/reg-tests/connection/proxy_protocol_send_unique_id_alpn.vtc
@@ -0,0 +1,33 @@
+varnishtest "Check that the unique ID TLV is properly sent for servers with ALPN option"
+
+#REQUIRE_VERSION=2.2
+#REQUIRE_OPTIONS=OPENSSL
+
+feature ignore_unknown_macro
+
+haproxy h1 -conf {
+ defaults
+ mode http
+ log global
+ unique-id-format %{+X}o\ TEST-%[req.hdr(in)]
+
+ listen sender
+ bind "fd@${feS}"
+
+ server example ${h1_feR_addr}:${h1_feR_port} send-proxy-v2 proxy-v2-options unique-id ssl alpn XXX verify none
+
+ listen receiver
+ bind "fd@${feR}" ssl crt ${testdir}/common.pem accept-proxy
+
+ http-request set-var(txn.proxy_unique_id) fc_pp_unique_id
+ http-after-response set-header proxy_unique_id %[var(txn.proxy_unique_id)]
+ http-request return status 200
+} -start
+
+# Validate that a correct header passes
+client c1 -connect ${h1_feS_sock} {
+ txreq -url "/" \
+ -hdr "in: foo"
+ rxresp
+ expect resp.http.proxy_unique_id == "TEST-foo"
+} -run
diff --git a/reg-tests/connection/proxy_protocol_tlv_validation.vtc b/reg-tests/connection/proxy_protocol_tlv_validation.vtc
new file mode 100644
index 0000000..8c7d734
--- /dev/null
+++ b/reg-tests/connection/proxy_protocol_tlv_validation.vtc
@@ -0,0 +1,142 @@
+varnishtest "Check that the TLVs are properly validated"
+
+#REQUIRE_VERSION=2.4
+
+feature ignore_unknown_macro
+
+# We need one HAProxy for each test, because apparently the connection by
+# the client is reused, leading to connection resets.
+
+haproxy h1 -conf {
+ defaults
+ mode http
+ timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
+
+ frontend a
+ bind "fd@${fe1}" accept-proxy
+ http-after-response set-header echo %[fc_pp_authority,hex]
+ http-request return status 200
+} -start
+
+# Validate that a correct header passes
+client c1 -connect ${h1_fe1_sock} {
+ # PROXY v2 signature
+ sendhex "0d 0a 0d 0a 00 0d 0a 51 55 49 54 0a"
+ # version + PROXY
+ sendhex "21"
+ # TCP4
+ sendhex "11"
+ # length of the address (12) + length of the TLV (8)
+ sendhex "00 14"
+ # 127.0.0.1 42 127.0.0.1 1337
+ sendhex "7F 00 00 01 7F 00 00 01 00 2A 05 39"
+ # PP2_TYPE_AUTHORITY + length of the value + "12345"
+ sendhex "02 00 05 31 32 33 34 35"
+
+ txreq -url "/"
+ rxresp
+ expect resp.http.echo == "3132333435"
+} -run
+
+haproxy h2 -conf {
+ defaults
+ mode http
+ timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
+
+ frontend a
+ bind "fd@${fe1}" accept-proxy
+ http-after-response set-header echo %[fc_pp_authority,hex]
+ http-request return status 200
+} -start
+
+# Validate that a TLV after the end of the PROXYv2 header is not parsed
+# and handle by the HTTP parser, leading to a 400 bad request error
+client c2 -connect ${h2_fe1_sock} {
+ # PROXY v2 signature
+ sendhex "0d 0a 0d 0a 00 0d 0a 51 55 49 54 0a"
+ # version + PROXY
+ sendhex "21"
+ # TCP4
+ sendhex "11"
+ # length of the address (12) + length of the TLV (8)
+ sendhex "00 14"
+ # 127.0.0.1 42 127.0.0.1 1337
+ sendhex "7F 00 00 01 7F 00 00 01 00 2A 05 39"
+ # PP2_TYPE_AUTHORITY + length of the value + "12345"
+ sendhex "02 00 05 31 32 33 34 35"
+ # after the end of the PROXYv2 header: PP2_TYPE_AUTHORITY + length of the value + "54321"
+ sendhex "02 00 05 35 34 33 32 31"
+
+ txreq -url "/"
+ rxresp
+ expect resp.status == 400
+ expect resp.http.echo == <undef>
+} -run
+
+haproxy h3 -conf {
+ defaults
+ mode http
+ timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
+
+ frontend a
+ bind "fd@${fe1}" accept-proxy
+ http-after-response set-header echo %[fc_pp_authority,hex]
+ http-request return status 200
+} -start
+
+# Validate that a TLV length exceeding the PROXYv2 length fails
+client c3 -connect ${h3_fe1_sock} {
+ # PROXY v2 signature
+ sendhex "0d 0a 0d 0a 00 0d 0a 51 55 49 54 0a"
+ # version + PROXY
+ sendhex "21"
+ # TCP4
+ sendhex "11"
+ # length of the address (12) + too small length of the TLV (8)
+ sendhex "00 14"
+ # 127.0.0.1 42 127.0.0.1 1337
+ sendhex "7F 00 00 01 7F 00 00 01 00 2A 05 39"
+ # PP2_TYPE_AUTHORITY + length of the value + "1234512345"
+ sendhex "02 00 0A 31 32 33 34 35 31 32 33 34 35"
+
+ txreq -url "/"
+ expect_close
+} -run
+
+haproxy h4 -conf {
+ defaults
+ mode http
+ timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
+
+ frontend a
+ bind "fd@${fe1}" accept-proxy
+ http-after-response set-header echo %[fc_pp_authority,hex]
+ http-request return status 200
+} -start
+
+# Validate that TLVs not ending with the PROXYv2 header fail
+client c4 -connect ${h4_fe1_sock} {
+ # PROXY v2 signature
+ sendhex "0d 0a 0d 0a 00 0d 0a 51 55 49 54 0a"
+ # version + PROXY
+ sendhex "21"
+ # TCP4
+ sendhex "11"
+ # length of the address (12) + too big length of the TLV (8)
+ sendhex "00 14"
+ # 127.0.0.1 42 127.0.0.1 1337
+ sendhex "7F 00 00 01 7F 00 00 01 00 2A 05 39"
+ # PP2_TYPE_AUTHORITY + length of the value + "1234"
+ sendhex "02 00 04 31 32 33 34"
+
+ txreq -url "/"
+ expect_close
+} -run
diff --git a/reg-tests/connection/reverse_connect_full.vtc b/reg-tests/connection/reverse_connect_full.vtc
new file mode 100644
index 0000000..238831f
--- /dev/null
+++ b/reg-tests/connection/reverse_connect_full.vtc
@@ -0,0 +1,70 @@
+varnishtest "Reverse connect full test"
+feature ignore_unknown_macro
+
+#REQUIRE_VERSION=2.9
+
+server s1 {
+ rxreq
+ txresp
+} -start
+
+haproxy h_edge -conf {
+global
+ expose-experimental-directives
+
+defaults
+ log global
+ timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
+ mode http
+
+frontend pub
+ bind "fd@${pub}"
+ use_backend be-reverse
+
+frontend priv
+ bind "fd@${priv}" proto h2
+ tcp-request session attach-srv be-reverse/dev
+
+backend be-reverse
+ server dev rhttp@
+} -start
+
+haproxy h_dev -conf {
+global
+ expose-experimental-directives
+
+defaults
+ log global
+ timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
+ mode http
+
+frontend fe
+ bind "rhttp@be-pre-connect/srv"
+ use_backend be
+
+backend be-pre-connect
+ server srv ${h_edge_priv_addr}:${h_edge_priv_port} proto h2
+
+backend be
+ server srv ${s1_addr}:${s1_port}
+}
+
+client c1 -connect ${h_edge_pub_sock} {
+ txreq -url "/"
+ rxresp
+ expect resp.status == 503
+} -run
+
+haproxy h_dev -start
+# TODO replace delay by a proper wait
+delay 3
+
+client c1 -connect ${h_edge_pub_sock} {
+ txreq -url "/"
+ rxresp
+ expect resp.status == 200
+} -run
diff --git a/reg-tests/connection/reverse_server.vtc b/reg-tests/connection/reverse_server.vtc
new file mode 100644
index 0000000..50fe8ce
--- /dev/null
+++ b/reg-tests/connection/reverse_server.vtc
@@ -0,0 +1,69 @@
+varnishtest "Reverse server test"
+feature ignore_unknown_macro
+
+#REQUIRE_VERSION=2.9
+
+barrier b1 cond 2
+
+haproxy h_edge -conf {
+global
+ expose-experimental-directives
+
+defaults
+ log global
+ timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
+ mode http
+
+frontend pub
+ bind "fd@${pub}"
+ use_backend be-reverse
+
+backend be-reverse
+ server dev rhttp@
+
+frontend priv
+ bind "fd@${priv}" proto h2
+ tcp-request session attach-srv be-reverse/dev
+} -start
+
+# Run a client through public endpoint
+# Reverse server has no connection available thus a 503 is expected
+client c1 -connect ${h_edge_pub_sock} {
+ txreq -url "/"
+ rxresp
+ expect resp.status == 503
+} -run
+
+# Run a client through private endpoint
+# Connection will be attached to the reverse server
+client c_dev -connect ${h_edge_priv_sock} {
+ txpri
+
+ stream 0 {
+ txsettings
+ rxsettings
+ txsettings -ack
+ rxsettings
+ expect settings.ack == true
+ } -run
+
+ barrier b1 sync
+ stream 1 {
+ rxhdrs
+ } -run
+
+ sendhex "000004 01 05 00000001 88 5c 01 30"
+} -start
+
+# Wait for dev client to be ready to process connection
+barrier b1 sync
+
+# Run a client through public endpoint
+# Reverse server should now be able to proceed with the request
+client c2 -connect ${h_edge_pub_sock} {
+ txreq -url "/"
+ rxresp
+ expect resp.status == 200
+} -run
diff --git a/reg-tests/connection/reverse_server_name.vtc b/reg-tests/connection/reverse_server_name.vtc
new file mode 100644
index 0000000..0fd850f
--- /dev/null
+++ b/reg-tests/connection/reverse_server_name.vtc
@@ -0,0 +1,87 @@
+varnishtest "Reverse server with a name parameter test"
+feature cmd "$HAPROXY_PROGRAM -cc 'feature(OPENSSL)'"
+feature ignore_unknown_macro
+
+#REQUIRE_VERSION=2.9
+
+barrier b1 cond 2
+
+haproxy h_edge -conf {
+global
+ expose-experimental-directives
+
+defaults
+ log global
+ timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
+ mode http
+
+frontend pub
+ bind "fd@${pub}"
+ use_backend be-reverse
+
+backend be-reverse
+ server dev rhttp@ ssl sni hdr(x-name) verify none
+
+frontend priv
+ bind "fd@${priv}" ssl crt ${testdir}/common.pem verify required ca-verify-file ${testdir}/ca-auth.crt alpn h2
+ tcp-request session attach-srv be-reverse/dev name ssl_c_s_dn(CN)
+} -start
+
+# Simple clear <-> SSL bridge between clients and h_edge haproxy
+# Used certificate has the name "client1"
+haproxy h_ssl_bridge -conf {
+defaults
+ log global
+ timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
+ mode tcp
+
+listen li
+ bind "fd@${li}"
+ server h_edge "${h_edge_priv_addr}:${h_edge_priv_port}" ssl crt ${testdir}/client1.pem verify none alpn h2
+} -start
+
+# Run a client through private endpoint
+# Connection will be attached to the reverse server
+client c_dev -connect ${h_ssl_bridge_li_sock} {
+ txpri
+
+ stream 0 {
+ txsettings
+ rxsettings
+ txsettings -ack
+ rxsettings
+ expect settings.ack == true
+ } -run
+
+ barrier b1 sync
+ stream 1 {
+ rxhdrs
+ } -run
+
+ sendhex "000004 01 05 00000001 88 5c 01 30"
+} -start
+
+# Wait for dev client to be ready to process connection
+barrier b1 sync
+
+# Run a client through public endpoint
+# Use a different name than the client certificate thus resulting in a 503
+client c1 -connect ${h_edge_pub_sock} {
+ txreq -url "/" \
+ -hdr "x-name: client99"
+ rxresp
+ expect resp.status == 503
+} -run
+
+# Run a client through public endpoint
+# Use the correct name
+client c2 -connect ${h_edge_pub_sock} {
+ txreq -url "/" \
+ -hdr "x-name: client1"
+ rxresp
+ expect resp.status == 200
+} -run
diff --git a/reg-tests/connection/tcp_to_http_upgrade.vtc b/reg-tests/connection/tcp_to_http_upgrade.vtc
new file mode 100644
index 0000000..48ebeba
--- /dev/null
+++ b/reg-tests/connection/tcp_to_http_upgrade.vtc
@@ -0,0 +1,169 @@
+varnishtest "Test connection upgrades from TCP to HTTP"
+
+#REQUIRE_VERSION=2.4
+
+feature ignore_unknown_macro
+
+server s1 {
+ # TCP > H1 using "switch-mode http"
+ rxreq
+ expect req.http.x-stream-mode == tcp
+ expect req.http.x-name == fe1
+ txresp
+ rxreq
+ expect req.http.x-stream-mode == http
+ expect req.http.x-name == fe1
+ txresp
+
+ accept
+
+ # TCP > H1 using backend mode
+ rxreq
+ expect req.http.x-name == be
+ txresp
+ rxreq
+ expect req.http.x-name == be
+ txresp
+
+ accept
+
+ # TCP > H2 using "switch-mode http"
+ rxreq
+ expect req.http.x-stream-mode == http
+ expect req.http.x-name == fe1
+ txresp
+ rxreq
+ expect req.http.x-stream-mode == http
+ expect req.http.x-name == fe1
+ txresp
+
+ # To be sure no other request was received
+ accept
+ rxreq
+ txresp
+} -start
+
+haproxy h1 -conf {
+ frontend fe1
+ mode tcp
+ bind "fd@${fe1h1}"
+
+ tcp-request inspect-delay 1s
+ tcp-request content set-var(req.stream_mode) internal.strm.is_htx,iif(http,tcp)
+ tcp-request content switch-mode http if HTTP
+ tcp-request content reject # never reached
+
+ http-request set-header x-stream-mode %[var(req.stream_mode)]
+ http-request set-header x-name %[fe_name]
+
+ default_backend be
+
+ frontend fe2
+ mode tcp
+ bind "fd@${fe2h1}"
+ default_backend be
+
+ backend be
+ mode http
+ http-request set-header x-name %[be_name] unless { req.fhdr(x-name) -m found }
+ server s1 ${s1_addr}:${s1_port}
+
+ listen li1
+ mode http
+ bind "fd@${li1h1}"
+ server s1 ${h1_fe1h1_addr}:${h1_fe1h1_port} proto h2
+
+ listen err1
+ mode http
+ bind "fd@${err1h1}" proto h1
+ server s1 ${s1_addr}:${s1_port}
+
+ listen err2
+ mode tcp
+ bind "fd@${err2h1}"
+
+ tcp-request inspect-delay 1s
+ tcp-request content switch-mode http proto h1 if HTTP
+ tcp-request content reject # never reached
+
+ default_backend be
+
+ listen err3
+ mode tcp
+ bind "fd@${err3h1}" proto none
+
+ tcp-request inspect-delay 1s
+ tcp-request content switch-mode http if HTTP
+ tcp-request content reject # never reached
+
+ default_backend be
+} -start
+
+# TCP > H1 using "switch-mode http"
+client c1 -connect ${h1_fe1h1_sock} {
+ txreq
+ rxresp
+ expect resp.status == 200
+
+ txreq
+ rxresp
+ expect resp.status == 200
+} -run
+
+# TCP > H1 using backend mode
+client c2 -connect ${h1_fe2h1_sock} {
+ txreq
+ rxresp
+ expect resp.status == 200
+
+ txreq
+ rxresp
+ expect resp.status == 200
+} -run
+
+
+# TCP > H2 using "switch-mode http"
+client c3 -connect ${h1_li1h1_sock} {
+ txreq
+ rxresp
+ expect resp.status == 200
+
+ txreq
+ rxresp
+ expect resp.status == 200
+} -run
+
+# implicit H1 > H2 upgrade not performed
+client c_err1 -connect ${h1_err1h1_sock} {
+ send "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
+ rxresp
+ expect resp.status == 400
+} -run
+
+
+# TCP > H1 > H2 upgrade not allowed
+client c_err2 -connect ${h1_err2h1_sock} {
+ send "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
+ rxresp
+ expect resp.status == 400
+} -run
+
+
+# TCP > HTTP upgrade not allowed
+client c_err3 -connect ${h1_err3h1_sock} {
+ txreq
+ expect_close
+} -run
+
+# TCP > HTTP upgrade with a parsing error
+client c_err4 -connect ${h1_fe2h1_sock} {
+ send "GET / BAD-VERSION\r\n\r\n"
+ rxresp
+ expect resp.status == 400
+} -run
+
+# To be sure no other request was received by the server
+client c_end -connect ${s1_sock} {
+ txreq
+ rxresp
+} -run