]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: quic: implement quic-initial rules
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 18 Jul 2024 16:25:43 +0000 (18:25 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 25 Jul 2024 13:39:39 +0000 (15:39 +0200)
Implement a new set of rules labelled as quic-initial.

These rules as specific to QUIC. They are scheduled to be executed early
on Initial packet parsing, prior a new QUIC connection instantiation.
Contrary to tcp-request connection, this allows to reject traffic
earlier, most notably by avoiding unnecessary QUIC SSL handshake
processing.

A new module quic_rules is created. Its main function
quic_init_exec_rules() is called on Initial packet parsing in function
quic_rx_pkt_retrieve_conn().

For the moment, only "accept" and "dgram-drop" are valid actions. Both
are final. The latter drops silently the Initial packet instead of
allocating a new QUIC connection.

Makefile
doc/configuration.txt
include/haproxy/action-t.h
include/haproxy/cfgparse.h
include/haproxy/proxy-t.h
include/haproxy/quic_rules.h [new file with mode: 0644]
src/cfgparse-listen.c
src/cfgparse-quic.c
src/proxy.c
src/quic_rules.c [new file with mode: 0644]
src/quic_rx.c

index 905481281a8d50daba9ea5274331172ead89cecf..ff1810a87a61a3218fd18cc24784c562195d9074 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -651,7 +651,7 @@ OPTIONS_OBJS += src/quic_rx.o src/mux_quic.o src/h3.o src/quic_tx.o \
                 src/quic_cc_nocc.o src/qpack-dec.o src/quic_cc.o       \
                 src/cfgparse-quic.o src/qmux_trace.o src/qpack-enc.o   \
                 src/qpack-tbl.o src/h3_stats.o src/quic_stats.o                \
-                src/quic_fctl.o src/cbuf.o
+                src/quic_fctl.o src/cbuf.o src/quic_rules.o
 endif
 
 ifneq ($(USE_QUIC_OPENSSL_COMPAT:0=),)
index 43b6c956bd1bc87f850964adbdf4ec6840c8096f..a64320a698986e3a17c598cd0301877934ad6248 100644 (file)
@@ -5405,6 +5405,7 @@ option idle-close-on-response        (*)  X          X         X         -
 external-check command                    X          -         X         X
 external-check path                       X          -         X         X
 persist rdp-cookie                        X          -         X         X
+quic-initial                              X (!)      X         X         -
 rate-limit sessions                       X          X         X         -
 redirect                                  -          X         X         X
 -- keyword -------------------------- defaults - frontend - listen -- backend -
@@ -10980,6 +10981,27 @@ persist rdp-cookie(<name>)
   See also : "balance rdp-cookie", "tcp-request" and the "req.rdp_cookie" ACL.
 
 
+quic-initial <action>
+  Perform an action on an incoming QUIC Initial packet. Contrary to
+  "tcp-request connection", this is executed prior to any connection element
+  instantiation and starting and completion of the SSL handshake, which is more
+  efficient when wanting to reject connections attempts.
+
+  May be used in the following contexts: http
+
+  May be used in sections :   defaults | frontend | listen | backend
+                                yes(!) |    yes   |   yes  |   no
+
+  Arguments :
+    <action>    defines the action to perform if the condition applies. See
+                below.
+
+  This action is executed early during QUIC packet parsing. As such, only a
+  minimal list of actions is supported :
+    - accept
+    - dgram-drop
+
+
 rate-limit sessions <rate>
   Set a limit on the number of new sessions accepted per second on a frontend
 
@@ -14308,6 +14330,7 @@ many actions are usable with many rule sets. The listing in this section will
 indicate for which supported action where it may be used, by ticking the
 corresponding abbreviated entry names among the following rule sets:
 
+  - QUIC  Ini: the action is valid for "quic-initial" rules
   - TCP RqCon: the action is valid for "tcp-request connection" rules
   - TCP RqSes: the action is valid for "tcp-request session" rules
   - TCP RqCnt: the action is valid for "tcp-request content" rules
@@ -14318,83 +14341,83 @@ corresponding abbreviated entry names among the following rule sets:
 
 The same abbreviations are used in the reference section 4.4 below.
 
-
- keyword                TCP: RqCon RqSes RqCnt RsCnt   HTTP: Req Res Aft
-----------------------+-----------+-----+-----+------+----------+---+----
-accept                         X     X     X     X            -   -   -
-add-acl                        -     -     -     -            X   X   -
-add-header                     -     -     -     -            X   X   X
-allow                          -     -     -     -            X   X   X
-attach-srv                     -     X     -     -            -   -   -
-auth                           -     -     -     -            X   -   -
-cache-store                    -     -     -     -            -   X   -
-cache-use                      -     -     -     -            X   -   -
-capture                        -     -     X     -            X   X   X
-close                          -     -     -     X            -   -   -
-del-acl                        -     -     -     -            X   X   -
-del-header                     -     -     -     -            X   X   X
-del-map                        -     -     -     -            X   X   X
-deny                           -     -     -     -            X   X   -
-disable-l7-retry               -     -     -     -            X   -   -
-do-resolve                     -     -     X     -            X   -   -
-early-hint                     -     -     -     -            X   -   -
-expect-netscaler-cip           X     -     -     -            -   -   -
-expect-proxy layer4            X     -     -     -            -   -   -
-normalize-uri                  -     -     -     -            X   -   -
-redirect                       -     -     -     -            X   X   -
-reject                         X     X     X     X            X   -   -
-replace-header                 -     -     -     -            X   X   X
-replace-path                   -     -     -     -            X   -   -
-replace-pathq                  -     -     -     -            X   -   -
-replace-uri                    -     -     -     -            X   -   -
-replace-value                  -     -     -     -            X   X   X
-return                         -     -     -     -            X   X   -
-sc-add-gpc                     X     X     X     X            X   X   X
---keyword---------------TCP--RqCon-RqSes-RqCnt-RsCnt---HTTP--Req-Res-Aft-
-sc-inc-gpc                     X     X     X     X            X   X   X
-sc-inc-gpc0                    X     X     X     X            X   X   X
-sc-inc-gpc1                    X     X     X     X            X   X   X
-sc-set-gpt                     X     X     X     X            X   X   X
-sc-set-gpt0                    X     X     X     X            X   X   X
-send-spoe-group                -     -     X     X            X   X   -
-set-bandwidth-limit            -     -     X     X            X   X   -
-set-bc-mark                    -     -     X     -            X   -   -
-set-bc-tos                     -     -     X     -            X   -   -
-set-dst                        X     X     X     -            X   -   -
-set-dst-port                   X     X     X     -            X   -   -
-set-fc-mark                    X     X     X     X            X   X   -
-set-fc-tos                     X     X     X     X            X   X   -
-set-header                     -     -     -     -            X   X   X
-set-log-level                  -     -     X     X            X   X   X
-set-map                        -     -     -     -            X   X   X
-set-mark (deprecated)          X     X     X     X            X   X   -
-set-method                     -     -     -     -            X   -   -
-set-nice                       -     -     X     X            X   X   -
-set-path                       -     -     -     -            X   -   -
-set-pathq                      -     -     -     -            X   -   -
-set-priority-class             -     -     X     -            X   -   -
-set-priority-offset            -     -     X     -            X   -   -
---keyword---------------TCP--RqCon-RqSes-RqCnt-RsCnt---HTTP--Req-Res-Aft-
-set-query                      -     -     -     -            X   -   -
-set-src                        X     X     X     -            X   -   -
-set-src-port                   X     X     X     -            X   -   -
-set-status                     -     -     -     -            -   X   X
-set-timeout                    -     -     -     -            X   X   -
-set-tos (deprecated)           X     X     X     X            X   X   -
-set-uri                        -     -     -     -            X   -   -
-set-var                        X     X     X     X            X   X   X
-set-var-fmt                    X     X     X     X            X   X   X
-silent-drop                    X     X     X     X            X   X   -
-strict-mode                    -     -     -     -            X   X   X
-switch-mode                    -     -     X     -            -   -   -
-tarpit                         -     -     -     -            X   -   -
-track-sc1                      X     X     X     -            X   X   -
-track-sc2                      X     X     X     -            X   X   -
-unset-var                      X     X     X     X            X   X   X
-use-service                    -     -     X     -            X   -   -
-wait-for-body                  -     -     -     -            X   X   -
-wait-for-handshake             -     -     -     -            X   -   -
---keyword---------------TCP--RqCon-RqSes-RqCnt-RsCnt---HTTP--Req-Res-Aft-
+ keyword                QUIC: Ini   TCP: RqCon RqSes RqCnt RsCnt   HTTP: Req Res Aft
+----------------------+-----------+-----------+-----+-----+------+----------+---+----
+accept                         X           X     X     X     X            -   -   -
+add-acl                        -           -     -     -     -            X   X   -
+add-header                     -           -     -     -     -            X   X   X
+allow                          -           -     -     -     -            X   X   X
+attach-srv                     -           -     X     -     -            -   -   -
+auth                           -           -     -     -     -            X   -   -
+cache-store                    -           -     -     -     -            -   X   -
+cache-use                      -           -     -     -     -            X   -   -
+capture                        -           -     -     X     -            X   X   X
+close                          -           -     -     -     X            -   -   -
+del-acl                        -           -     -     -     -            X   X   -
+del-header                     -           -     -     -     -            X   X   X
+del-map                        -           -     -     -     -            X   X   X
+deny                           -           -     -     -     -            X   X   -
+dgram-drop                     X           -     -     -     -            -   -   -
+disable-l7-retry               -           -     -     -     -            X   -   -
+do-resolve                     -           -     -     X     -            X   -   -
+early-hint                     -           -     -     -     -            X   -   -
+expect-netscaler-cip           -           X     -     -     -            -   -   -
+expect-proxy layer4            -           X     -     -     -            -   -   -
+normalize-uri                  -           -     -     -     -            X   -   -
+redirect                       -           -     -     -     -            X   X   -
+reject                         -           X     X     X     X            X   -   -
+replace-header                 -           -     -     -     -            X   X   X
+replace-path                   -           -     -     -     -            X   -   -
+replace-pathq                  -           -     -     -     -            X   -   -
+replace-uri                    -           -     -     -     -            X   -   -
+replace-value                  -           -     -     -     -            X   X   X
+return                         -           -     -     -     -            X   X   -
+sc-add-gpc                     -           X     X     X     X            X   X   X
+--keyword---------------QUIC--Ini---TCP--RqCon-RqSes-RqCnt-RsCnt---HTTP--Req-Res-Aft-
+sc-inc-gpc                     -           X     X     X     X            X   X   X
+sc-inc-gpc0                    -           X     X     X     X            X   X   X
+sc-inc-gpc1                    -           X     X     X     X            X   X   X
+sc-set-gpt                     -           X     X     X     X            X   X   X
+sc-set-gpt0                    -           X     X     X     X            X   X   X
+send-spoe-group                -           -     -     X     X            X   X   -
+set-bandwidth-limit            -           -     -     X     X            X   X   -
+set-bc-mark                    -           -     -     X     -            X   -   -
+set-bc-tos                     -           -     -     X     -            X   -   -
+set-dst                        -           X     X     X     -            X   -   -
+set-dst-port                   -           X     X     X     -            X   -   -
+set-fc-mark                    -           X     X     X     X            X   X   -
+set-fc-tos                     -           X     X     X     X            X   X   -
+set-header                     -           -     -     -     -            X   X   X
+set-log-level                  -           -     -     X     X            X   X   X
+set-map                        -           -     -     -     -            X   X   X
+set-mark (deprecated)          -           X     X     X     X            X   X   -
+set-method                     -           -     -     -     -            X   -   -
+set-nice                       -           -     -     X     X            X   X   -
+set-path                       -           -     -     -     -            X   -   -
+set-pathq                      -           -     -     -     -            X   -   -
+set-priority-class             -           -     -     X     -            X   -   -
+set-priority-offset            -           -     -     X     -            X   -   -
+--keyword---------------QUIC--Ini---TCP--RqCon-RqSes-RqCnt-RsCnt---HTTP--Req-Res-Aft-
+set-query                      -           -     -     -     -            X   -   -
+set-src                        -           X     X     X     -            X   -   -
+set-src-port                   -           X     X     X     -            X   -   -
+set-status                     -           -     -     -     -            -   X   X
+set-timeout                    -           -     -     -     -            X   X   -
+set-tos (deprecated)           -           X     X     X     X            X   X   -
+set-uri                        -           -     -     -     -            X   -   -
+set-var                        -           X     X     X     X            X   X   X
+set-var-fmt                    -           X     X     X     X            X   X   X
+silent-drop                    -           X     X     X     X            X   X   -
+strict-mode                    -           -     -     -     -            X   X   X
+switch-mode                    -           -     -     X     -            -   -   -
+tarpit                         -           -     -     -     -            X   -   -
+track-sc1                      -           X     X     X     -            X   X   -
+track-sc2                      -           X     X     X     -            X   X   -
+unset-var                      -           X     X     X     X            X   X   X
+use-service                    -           -     -     X     -            X   -   -
+wait-for-body                  -           -     -     -     -            X   X   -
+wait-for-handshake             -           -     -     -     -            X   -   -
+--keyword---------------QUIC--Ini---TCP--RqCon-RqSes-RqCnt-RsCnt---HTTP--Req-Res-Aft-
 
 
 4.4. Alphabetically sorted actions reference
@@ -14405,20 +14428,20 @@ using the same ruleset terminology marking as described in section 4.3 above.
 
 
 accept
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt |   HTTP Req| Res| Aft
-                    X  |   X  |   X  |   X   |         - |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    X |          X  |   X  |   X  |   X  |         - |  - |  -
 
   This stops the evaluation of the rules and lets the request or response pass
   the check. This action is final, i.e. no further rules from the same rule set
   are evaluated for the current section. There is no difference between this
   and the "allow" action except that for historical compatibility, "accept" is
-  used for TCP rules and "allow" for HTTP rules. See also the "allow" action
-  below.
+  used for TCP and QUIC rules and "allow" for HTTP rules. See also the "allow"
+  action below.
 
 
 add-acl(<file-name>) <key fmt>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  X |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  X |  -
 
   This is used to add a new entry into an ACL. The ACL must be loaded from a
   file (even a dummy empty file). The file name of the ACL to be updated is
@@ -14430,8 +14453,8 @@ add-acl(<file-name>) <key fmt>
 
 
 add-header <name> <fmt>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  X |  X
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  X |  X
 
   This appends an HTTP header field whose name is specified in <name> and
   whose value is defined by <fmt> which follows the Custom log format rules
@@ -14444,8 +14467,8 @@ add-header <name> <fmt>
 
 
 allow
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  X |  X
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  X |  X
 
   This stops the evaluation of the rules and lets the request pass the check.
   This action is final, i.e. no further rules from the same rule set are
@@ -14456,8 +14479,8 @@ allow
 
 
 attach-srv <srv> [name <expr>] [ EXPERIMENTAL ]
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   X  |   -  |   -  |          - |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   X  |   -  |   -  |          - |  - |  -
 
   This is used to intercept the connection after proper HTTP/2 establishment.
   The connection is reversed to the backend side and inserted into the idle
@@ -14478,8 +14501,8 @@ attach-srv <srv> [name <expr>] [ EXPERIMENTAL ]
   https://www.ietf.org/archive/id/draft-bt-httpbis-reverse-http-00.html.
 
 auth [realm <realm>]
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  - |  -
 
   This stops the evaluation of the rules and immediately responds with an
   HTTP 401 or 407 error code to invite the user to present a valid user name
@@ -14501,8 +14524,8 @@ auth [realm <realm>]
 
 
 cache-store <name>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          - |  X |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          - |  X |  -
 
   Store an http-response within the cache. The storage of the response headers
   is done at this step, which means you can use others http-response actions
@@ -14513,8 +14536,8 @@ cache-store <name>
 
 
 cache-use <name>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  - |  -
 
   Try to deliver a cached object from the cache <name>. This directive is also
   mandatory to store the cache as it calculates the cache hash. If you want to
@@ -14525,8 +14548,8 @@ cache-use <name>
 
 
 capture <sample> [ len <length> | id <id> ]
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   X  |   -  |          X |  X |  X
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   X  |   -  |          X |  X |  X
 
   This captures sample expression <sample> from the request or response buffer,
   and converts it to a string of at most <len> characters. The resulting string
@@ -14551,8 +14574,8 @@ capture <sample> [ len <length> | id <id> ]
 
 
 close
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   X  |          - |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   X  |          - |  - |  -
 
   This is used to immediately close the connection with the server. No further
   "tcp-response content" rules are evaluated. The main purpose of this action
@@ -14563,8 +14586,8 @@ close
 
 
 del-acl(<file-name>) <key fmt>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  X |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  X |  -
 
   This is used to delete an entry from an ACL. The ACL must be loaded from a
   file (even a dummy empty file). The file name of the ACL to be updated is
@@ -14575,8 +14598,8 @@ del-acl(<file-name>) <key fmt>
 
 
 del-header <name> [ -m <meth> ]
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  X |  X
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  X |  X
 
   This removes all HTTP header fields whose name is specified in <name>. <meth>
   is the matching method, applied on the header name. Supported matching methods
@@ -14586,8 +14609,8 @@ del-header <name> [ -m <meth> ]
 
 
 del-map(<map-name>) <key fmt>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  X |  X
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  X |  X
 
   This is used to delete an entry from a MAP. <map-name> must follow the format
   described in 2.7. about name format for maps and ACLs. The name of the MAP to
@@ -14602,8 +14625,8 @@ deny [ { status | deny_status } <code> ] [ content-type <type> ]
      [ { default-errorfiles | errorfile <file> | errorfiles <name> |
        file <file> | lf-file <file> | string <str> | lf-string <fmt> } ]
      [ hdr <name> <fmt> ]*
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  X |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  X |  -
 
   This stops the evaluation of the rules and immediately rejects the request or
   response. By default an HTTP 403 error is returned for requests, and 502 for
@@ -14617,9 +14640,18 @@ deny [ { status | deny_status } <code> ] [ content-type <type> ]
   syntax.
 
 
+dgram-drop
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    X |          -  |   -  |   -  |   -  |          - |  - |  -
+
+  This silently ignores the reception of a QUIC initial packet which otherwise
+  whould have resulted in a new QUIC connection instantiation and its SSL
+  handshake execution.
+
+
 disable-l7-retry
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  - |  -
 
   This disables any attempt to retry the request if it fails for any other
   reason than a connection failure. This can be useful for example to make
@@ -14627,8 +14659,8 @@ disable-l7-retry
 
 
 do-resolve(<var>,<resolvers>,[ipv4,ipv6]) <expr>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   X  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   X  |   -  |          X |  - |  -
 
   This action performs a DNS resolution of the output of <expr> and stores
   the result in the variable <var>. It uses the DNS resolvers section
@@ -14685,8 +14717,8 @@ do-resolve(<var>,<resolvers>,[ipv4,ipv6]) <expr>
 
 
 early-hint <name> <fmt>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  - |  -
 
   This is used to build an HTTP 103 Early Hints response prior to any other one.
   This appends an HTTP header field to this response whose name is specified in
@@ -14699,8 +14731,8 @@ early-hint <name> <fmt>
 
 
 expect-netscaler-cip layer4
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    X  |   -  |   -  |   -  |          - |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          X  |   -  |   -  |   -  |          - |  - |  -
 
   This configures the client-facing connection to receive a NetScaler Client IP
   insertion protocol header before any byte is read from the socket.  This is
@@ -14712,8 +14744,8 @@ expect-netscaler-cip layer4
 
 
 expect-proxy layer4
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    X  |   -  |   -  |   -  |          - |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          X  |   -  |   -  |   -  |          - |  - |  -
 
   This configures the client-facing connection to receive a PROXY protocol
   header before any byte is read from the socket. This is equivalent to having
@@ -14732,8 +14764,8 @@ normalize-uri path-strip-dotdot [ full ]
 normalize-uri percent-decode-unreserved [ strict ]
 normalize-uri percent-to-uppercase [ strict ]
 normalize-uri query-sort-by-name
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  - |  -
 
   Performs normalization of the request's URI.
 
@@ -14874,8 +14906,8 @@ normalize-uri query-sort-by-name
 
 
 redirect <rule>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  X |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  X |  -
 
   This performs an HTTP redirection based on a redirect rule. This is exactly
   the same as the "redirect" statement except that it inserts a redirect rule
@@ -14890,8 +14922,8 @@ redirect <rule>
 
 
 reject
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    X  |   X  |   X  |   X  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          X  |   X  |   X  |   X  |          X |  - |  -
 
   This stops the evaluation of the rules and immediately closes the connection
   without sending any response. For HTTP rules, it acts similarly to the
@@ -14916,8 +14948,8 @@ reject
 
 
 replace-header <name> <match-regex> <replace-fmt>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  X |  X
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  X |  X
 
   This matches the value of all occurrences of header field <name> against
   <match-regex>. Matching is performed case-sensitively. Matching values are
@@ -14965,8 +14997,8 @@ replace-header <name> <match-regex> <replace-fmt>
 
 
 replace-path <match-regex> <replace-fmt>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  - |  -
 
   This works like "replace-header" except that it works on the request's path
   component instead of a header. The path component starts at the first '/'
@@ -14989,8 +15021,8 @@ replace-path <match-regex> <replace-fmt>
 
 
 replace-pathq <match-regex> <replace-fmt>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  - |  -
 
   This does the same as "http-request replace-path" except that the path
   contains the query-string if any is present. Thus, the path and the
@@ -15002,8 +15034,8 @@ replace-pathq <match-regex> <replace-fmt>
 
 
 replace-uri <match-regex> <replace-fmt>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  - |  -
 
   This works like "replace-header" except that it works on the request's URI part
   instead of a header. The URI part may contain an optional scheme, authority or
@@ -15035,8 +15067,8 @@ replace-uri <match-regex> <replace-fmt>
 
 
 replace-value <name> <match-regex> <replace-fmt>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  X |  X
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  X |  X
 
   This works like "replace-header" except that it matches the regex against
   every comma-delimited value of the header field <name> instead of the
@@ -15067,8 +15099,8 @@ return [ status <code> ] [ content-type <type> ]
        [ { default-errorfiles | errorfile <file> | errorfiles <name> |
          file <file> | lf-file <file> | string <str> | lf-string <fmt> } ]
        [ hdr <name> <fmt> ]*
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  X |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  X |  -
 
   This stops the evaluation of the rules and immediately returns a response. The
   default status code used for the response is 200. It can be optionally
@@ -15141,8 +15173,8 @@ return [ status <code> ] [ content-type <type> ]
 
 
 sc-add-gpc(<idx>,<sc-id>) { <int> | <expr> }
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    X  |   X  |   X  |   X  |          X |  X |  X
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          X  |   X  |   X  |   X  |          X |  X |  X
 
   This action increments the General Purpose Counter at the index <idx> of the
   array associated to the sticky counter designated by <sc-id> by the value of
@@ -15167,8 +15199,8 @@ sc-add-gpc(<idx>,<sc-id>) { <int> | <expr> }
 
 
 sc-inc-gpc(<idx>,<sc-id>)
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    X  |   X  |   X  |   X  |          X |  X |  X
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          X  |   X  |   X  |   X  |          X |  X |  X
 
   This actions increments the General Purpose Counter at the index <idx> of the
   array associated to the sticky counter designated by <sc-id>. If an error
@@ -15181,8 +15213,8 @@ sc-inc-gpc(<idx>,<sc-id>)
 
 sc-inc-gpc0(<sc-id>)
 sc-inc-gpc1(<sc-id>)
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    X  |   X  |   X  |   X  |          X |  X |  X
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          X  |   X  |   X  |   X  |          X |  X |  X
 
   This actions increments the GPC0 or GPC1 counter according with the sticky
   counter designated by <sc-id>. If an error occurs, this action silently fails
@@ -15190,8 +15222,8 @@ sc-inc-gpc1(<sc-id>)
 
 
 sc-set-gpt(<idx>,<sc-id>) { <int> | <expr> }
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    X  |   X  |   X  |   X  |          X |  X |  X
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          X  |   X  |   X  |   X  |          X |  X |  X
 
   This action sets the 32-bit unsigned GPT at the index <idx> of the array
   associated to the sticky counter designated by <sc-id> at the value of
@@ -15207,8 +15239,8 @@ sc-set-gpt(<idx>,<sc-id>) { <int> | <expr> }
 
 
 sc-set-gpt0(<sc-id>) { <int> | <expr> }
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    X  |   X  |   X  |   X  |          X |  X |  X
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          X  |   X  |   X  |   X  |          X |  X |  X
 
   This action sets the 32-bit unsigned GPT0 tag according to the sticky counter
   designated by <sc-id> and the value of <int>/<expr>. The expected result is a
@@ -15218,8 +15250,8 @@ sc-set-gpt0(<sc-id>) { <int> | <expr> }
 
 
 send-spoe-group <engine-name> <group-name>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   X  |   X  |          X |  X |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   X  |   X  |          X |  X |  -
 
   This action is used to trigger sending of a group of SPOE messages. To do so,
   the SPOE engine used to send messages must be defined, as well as the SPOE
@@ -15235,8 +15267,8 @@ send-spoe-group <engine-name> <group-name>
 
 
 set-bandwidth-limit <name> [limit {<expr> | <size>}] [period {<expr> | <time>}]
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   X  |   X  |          X |  X |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   X  |   X  |          X |  X |  -
 
   This action is used to enable the bandwidth limitation filter <name>, either
   on the upload or download direction depending on the filter type. Custom
@@ -15271,8 +15303,8 @@ set-bandwidth-limit <name> [limit {<expr> | <size>}] [period {<expr> | <time>}]
 
 
 set-bc-mark { <mark> | <expr> }
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   X  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   X  |   -  |          X |  - |  -
 
   This is used to set the Netfilter/IPFW MARK on the backend connection (all
   packets sent to the server) to the value passed in <mark> or <expr> on
@@ -15289,8 +15321,8 @@ set-bc-mark { <mark> | <expr> }
 
 
 set-bc-tos { <tos> | <expr> }
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   X  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   X  |   -  |          X |  - |  -
 
   This is used to set the TOS or DSCP field value on the backend connection
   (all packets sent to the server) to the value passed in <tos> or <expr> on
@@ -15307,8 +15339,8 @@ set-bc-tos { <tos> | <expr> }
 
 
 set-dst <expr>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    X  |   X  |   X  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          X  |   X  |   X  |   -  |          X |  - |  -
 
   This is used to set the destination IP address to the value of specified
   expression. Useful when a proxy in front of HAProxy rewrites destination IP,
@@ -15329,8 +15361,8 @@ set-dst <expr>
 
 
 set-dst-port <expr>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    X  |   X  |   X  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          X  |   X  |   X  |   -  |          X |  - |  -
 
   This is used to set the destination port address to the value of specified
   expression. If you want to connect to the new address/port, use '0.0.0.0:0'
@@ -15350,8 +15382,8 @@ set-dst-port <expr>
 
 
 set-fc-mark { <mark> | <expr> }
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    X  |   X  |   X  |   X  |          X |  X |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          X  |   X  |   X  |   X  |          X |  X |  -
 
   This is used to set the Netfilter/IPFW MARK on all packets sent to the client
   to the value passed in <mark> or <expr> on platforms which support it. This
@@ -15367,8 +15399,8 @@ set-fc-mark { <mark> | <expr> }
 
 
 set-fc-tos { <tos | <expr> }
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    X  |   X  |   X  |   X  |          X |  X |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          X  |   X  |   X  |   X  |          X |  X |  -
 
   This is used to set the TOS or DSCP field value of packets sent to the client
   to the value passed in <tos> or <expr> on platforms which support this. This
@@ -15383,8 +15415,8 @@ set-fc-tos { <tos | <expr> }
 
 
 set-header <name> <fmt>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  X |  X
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  X |  X
 
   This does the same as the "add-header" action except that the header is first
   removed if it existed. This is useful when passing security information to
@@ -15406,8 +15438,8 @@ set-header <name> <fmt>
 
 
 set-log-level <level>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   X  |   X  |          X |  X |  X
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   X  |   X  |          X |  X |  X
 
   This is used to change the log level of the current request when a certain
   condition is met. Valid levels are the 8 syslog levels (see the "log"
@@ -15417,8 +15449,8 @@ set-log-level <level>
 
 
 set-map(<map-name>) <key fmt> <value fmt>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  X |  X
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  X |  X
 
   This is used to add a new entry into a map. <map-name> must follow the format
   described in 2.7. about name format for maps and ACLs. The name of the MAP to
@@ -15436,8 +15468,8 @@ set-mark <mark> (deprecated)
 
 
 set-method <fmt>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  - |  -
 
   This rewrites the request method with the result of the evaluation of format
   string <fmt>. There should be very few valid reasons for having to do so as
@@ -15445,8 +15477,8 @@ set-method <fmt>
 
 
 set-nice <nice>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   X  |   X  |          X |  X |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   X  |   X  |          X |  X |  -
 
   This sets the "nice" factor of the current request/response being processed.
   It only has effect against the other requests being processed at the same
@@ -15459,8 +15491,8 @@ set-nice <nice>
 
 
 set-path <fmt>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  - |  -
 
     This rewrites the request path with the result of the evaluation of format
     string <fmt>. The query string, if any, is left intact. If a scheme and
@@ -15475,8 +15507,8 @@ set-path <fmt>
 
 
 set-pathq <fmt>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  - |  -
 
   This does the same as "http-request set-path" except that the query-string is
   also rewritten. It may be used to remove the query-string, including the
@@ -15484,8 +15516,8 @@ set-pathq <fmt>
 
 
 set-priority-class <expr>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   X  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   X  |   -  |          X |  - |  -
 
   This is used to set the queue priority class of the current request.
   The value must be a sample expression which converts to an integer in the
@@ -15495,8 +15527,8 @@ set-priority-class <expr>
 
 
 set-priority-offset <expr>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   X  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   X  |   -  |          X |  - |  -
 
   This is used to set the queue priority timestamp offset of the current
   request. The value must be a sample expression which converts to an integer
@@ -15512,8 +15544,8 @@ set-priority-offset <expr>
 
 
 set-query <fmt>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  - |  -
 
   This rewrites the request's query string which appears after the first
   question mark ("?") with the result of the evaluation of format string <fmt>.
@@ -15531,8 +15563,8 @@ set-query <fmt>
 
 
 set-src <expr>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    X  |   X  |   X  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          X  |   X  |   X  |   -  |          X |  - |  -
 
   This is used to set the source IP address to the value of specified
   expression. Useful when a proxy in front of HAProxy rewrites source IP, but
@@ -15559,8 +15591,8 @@ set-src <expr>
 
 
 set-src-port <expr>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    X  |   X  |   X  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          X  |   X  |   X  |   -  |          X |  - |  -
 
   This is used to set the source port address to the value of specified
   expression.
@@ -15579,8 +15611,8 @@ set-src-port <expr>
 
 
 set-status <status> [reason <str>]
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          - |  X |  X
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          - |  X |  X
 
   This replaces the response status code with <status> which must be an integer
   between 100 and 999. Optionally, a custom reason text can be provided defined
@@ -15596,8 +15628,8 @@ set-status <status> [reason <str>]
 
 
 set-timeout { client | server | tunnel } { <timeout> | <expr> }
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  X |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  X |  -
 
   This action overrides the specified "client", "server" or "tunnel" timeout
   for the current stream only. The timeout can be specified in milliseconds or
@@ -15624,8 +15656,8 @@ set-tos <tos> (deprecated)
 
 
 set-uri <fmt>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  - |  -
 
   This rewrites the request URI with the result of the evaluation of format
   string <fmt>. The scheme, authority, path and query string are all replaced
@@ -15639,8 +15671,8 @@ set-uri <fmt>
 
 set-var(<var-name>[,<cond>...]) <expr>
 set-var-fmt(<var-name>[,<cond>...]) <fmt>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    X  |   X  |   X  |   X  |          X |  X |  X
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          X  |   X  |   X  |   X  |          X |  X |  X
 
   This is used to set the contents of a variable. The variable is declared
   inline.
@@ -15670,8 +15702,8 @@ set-var-fmt(<var-name>[,<cond>...]) <fmt>
 
 
 silent-drop [ rst-ttl <ttl> ]
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    X  |   X  |   X  |   X  |          X |  X |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          X  |   X  |   X  |   X  |          X |  X |  -
 
   This stops the evaluation of the rules and makes the client-facing connection
   suddenly disappear using a system-dependent way that tries to prevent the
@@ -15697,8 +15729,8 @@ silent-drop [ rst-ttl <ttl> ]
 
 
 strict-mode { on | off }
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  X |  X
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  X |  X
 
   This enables or disables the strict rewriting mode for following rules. It
   does not affect rules declared before it and it is only applicable on rules
@@ -15715,8 +15747,8 @@ strict-mode { on | off }
 
 
 switch-mode http [ proto <name> ]
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   X  |   -  |          - |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   X  |   -  |          - |  - |  -
 
   This action is used to perform a connection upgrade. Only HTTP upgrades are
   supported for now. The protocol may optionally be specified. This action is
@@ -15736,8 +15768,8 @@ tarpit [ { status | deny_status } <code>] [content-type <type>]
        [ { default-errorfiles | errorfile <file> | errorfiles <name> |
            file <file> | lf-file <file> | string <str> | lf-string <fmt> } ]
        [ hdr <name> <fmt> ]*
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  - |  -
 
   This stops the evaluation of the rules and immediately blocks the request
   without responding for a delay specified by "timeout tarpit" or
@@ -15764,8 +15796,8 @@ tarpit [ { status | deny_status } <code>] [content-type <type>]
 track-sc0 <key> [table <table>]
 track-sc1 <key> [table <table>]
 track-sc2 <key> [table <table>]
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    X  |   X  |   X  |   -  |          X |  X |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          X  |   X  |   X  |   -  |          X |  X |  -
 
   This enables tracking of sticky counters from current request. These rules do
   not stop evaluation and do not change default action. The number of counters
@@ -15810,8 +15842,8 @@ track-sc2 <key> [table <table>]
 
 
 unset-var(<var-name>)
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    X  |   X  |   X  |   X  |          X |  X |  X
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          X  |   X  |   X  |   X  |          X |  X |  X
 
   This is used to unset a variable. See the "set-var" action for details about
   <var-name>.
@@ -15821,8 +15853,8 @@ unset-var(<var-name>)
 
 
 use-service <service-name>
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   X  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   X  |   -  |          X |  - |  -
 
   This action executes the configured TCP or HTTP service to reply to the
   request, depending on the rule set it's used in. The rule is final, i.e.
@@ -15842,8 +15874,8 @@ use-service <service-name>
 
 
 wait-for-body time <time> [ at-least <bytes> ]
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  X |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  X |  -
 
   This will delay the processing of the request or response until one of the
   following conditions occurs:
@@ -15877,8 +15909,8 @@ wait-for-body time <time> [ at-least <bytes> ]
 
 
 wait-for-handshake
-  Usable in:  TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    -  |   -  |   -  |   -  |          X |  - |  -
+  Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
+                    - |          -  |   -  |   -  |   -  |          X |  - |  -
 
   This will delay the processing of the request until the SSL handshake
   happened. This is mostly useful to delay processing early data until we're
index a61ce72e53a6282fa70c7d2592fccfa793366072..63925a96fc92fda5a2b6a7520baa92579e116865 100644 (file)
@@ -41,6 +41,9 @@ enum act_from {
        ACT_F_TCP_CHK,     /* tcp-check. */
        ACT_F_CFG_PARSER,  /* config parser */
        ACT_F_CLI_PARSER,  /* command line parser */
+#ifdef USE_QUIC
+       ACT_F_QUIC_INIT,   /* quic-initial */
+#endif
 };
 
 enum act_return {
index 32bf186c4d6365bcbe74c59abac273994bbaee1d..5f0fa97e0848fdcc8a6342393a95b3c7ee6b44ed 100644 (file)
@@ -120,6 +120,7 @@ void cfg_restore_sections(struct list *backup_sections);
 int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg);
 int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg);
 int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg);
+int warnif_misplaced_quic_init(struct proxy *proxy, const char *file, int line, const char *arg);
 int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line);
 int warnif_tcp_http_cond(const struct proxy *px, const struct acl_cond *cond);
 int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code);
index 9bafb22e5c0b3492e9d08ed7e64a0c9749414b98..eb6a22427bf19f2228926ace64ec410d1ef93245 100644 (file)
@@ -307,6 +307,9 @@ struct proxy {
                unsigned int inspect_delay;     /* inspection delay */
                struct list inspect_rules;      /* inspection rules */
        } tcp_rep;
+#ifdef USE_QUIC
+       struct list quic_init_rules;            /* quic-initial rules */
+#endif
        struct server *srv, defsrv;             /* known servers; default server configuration */
        struct lbprm lbprm;                     /* load-balancing parameters */
        int srv_act, srv_bck;                   /* # of servers eligible for LB (UP|!checked) AND (enabled+weight!=0) */
diff --git a/include/haproxy/quic_rules.h b/include/haproxy/quic_rules.h
new file mode 100644 (file)
index 0000000..a38ff69
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _HAPROXY_QUIC_RULES_H
+#define _HAPROXY_QUIC_RULES_H
+
+#include <haproxy/action-t.h>
+
+struct listener;
+
+extern struct action_kw_list quic_init_actions_list;
+
+int quic_init_exec_rules(struct listener *li);
+
+struct action_kw *action_quic_init_custom(const char *kw);
+
+#endif /* _HAPROXY_QUIC_RULES_H */
index 2beb9377b079ce8c7fddd86ac23feeeb15f7592a..f710b02799e9049e68e3e192c2856e6001c640b8 100644 (file)
@@ -67,6 +67,19 @@ static const char *common_options[] = {
        NULL /* must be last */
 };
 
+/* Report a warning if a rule is placed after a 'tcp-request connection' rule.
+ * Return 1 if the warning has been emitted, otherwise 0.
+ */
+int warnif_rule_after_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
+{
+       if (!LIST_ISEMPTY(&proxy->tcp_req.l4_rules)) {
+               ha_warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request connection' rule will still be processed before.\n",
+                          file, line, arg);
+               return 1;
+       }
+       return 0;
+}
+
 /* Report a warning if a rule is placed after a 'tcp-request session' rule.
  * Return 1 if the warning has been emitted, otherwise 0.
  */
@@ -200,6 +213,12 @@ int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, c
                warnif_misplaced_tcp_sess(proxy, file, line, arg);
 }
 
+int warnif_misplaced_quic_init(struct proxy *proxy, const char *file, int line, const char *arg)
+{
+       return warnif_rule_after_tcp_conn(proxy, file, line, arg) ||
+              warnif_misplaced_tcp_conn(proxy, file, line, arg);
+}
+
 int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
 {
        static struct proxy *curr_defproxy = NULL;
index 97c515acffdfbd888017690bf78f44be050592a5..6b287e291061c8bf29ec7a11c2be9f8fc99e844b 100644 (file)
@@ -2,13 +2,15 @@
 #include <string.h>
 #include <netinet/udp.h>
 
+#include <haproxy/action.h>
 #include <haproxy/api.h>
 #include <haproxy/cfgparse.h>
 #include <haproxy/errors.h>
 #include <haproxy/global.h>
 #include <haproxy/listener.h>
-#include <haproxy/proxy-t.h>
+#include <haproxy/proxy.h>
 #include <haproxy/quic_cc-t.h>
+#include <haproxy/quic_rules.h>
 #include <haproxy/tools.h>
 
 #define QUIC_CC_NEWRENO_STR "newreno"
@@ -338,3 +340,78 @@ static struct cfg_kw_list cfg_kws = {ILH, {
 }};
 
 INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
+
+static int quic_parse_quic_initial(char **args, int section_type, struct proxy *curpx,
+                                   const struct proxy *defpx, const char *file, int line,
+                                   char **err)
+{
+       struct act_rule *rule;
+       struct action_kw *kw;
+       int arg = 1;
+
+       if (curpx == defpx && strlen(defpx->id) == 0) {
+               memprintf(err, "%s is not allowed in anonymous 'defaults' sections",
+                         args[0]);
+               return -1;
+       }
+
+       if (!(curpx->cap & PR_CAP_FE)) {
+               memprintf(err, "'%s' : proxy '%s' has no frontend capability",
+                         args[0], curpx->id);
+               return -1;
+       }
+
+       if (!(curpx->mode & PR_MODE_HTTP)) {
+               memprintf(err, "'%s' : proxy '%s' does not used HTTP mode",
+                         args[0], curpx->id);
+               return -1;
+       }
+
+       rule = new_act_rule(0, file, line);
+       if (!rule) {
+               memprintf(err, "parsing [%s:%d] : out of memory", file, line);
+               return -1;
+       }
+
+       LIST_INIT(&rule->list);
+       rule->from = ACT_F_QUIC_INIT;
+
+       kw = action_quic_init_custom(args[1]);
+       if (kw) {
+               rule->kw = kw;
+               arg++;
+
+               if (kw->parse((const char **)args, &arg, curpx, rule, err) == ACT_RET_PRS_ERR)
+                       goto err;
+       }
+       else {
+               const char *best = action_suggest(args[1], &quic_init_actions_list.list, NULL);
+
+               action_build_list(&quic_init_actions_list.list, &trash);
+               memprintf(err, "'quic-initial' expects %s, but got '%s'%s.%s%s%s",
+                         trash.area,
+                         args[1], *args[1] ? "" : " (missing argument)",
+                         best ? " Did you mean '" : "",
+                         best ? best : "",
+                         best ? "' maybe ?" : "");
+               goto err;
+       }
+
+       /* the following function directly emits the warning */
+       warnif_misplaced_quic_init(curpx, file, line, args[0]);
+
+       LIST_APPEND(&curpx->quic_init_rules, &rule->list);
+
+       return 0;
+
+ err:
+       free_act_rule(rule);
+       return -1;
+}
+
+static struct cfg_kw_list cfg_kws_li = {ILH, {
+       { CFG_LISTEN, "quic-initial",  quic_parse_quic_initial },
+       { 0, NULL, NULL },
+}};
+
+INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws_li);
index da589a28e1b0f92397f770bf297de56dd9e9e566..b86e4f5b4f886176c693a12a3e1c8571d3fe3bd9 100644 (file)
@@ -236,6 +236,9 @@ static inline void proxy_free_common(struct proxy *px)
        free_act_rules(&px->http_req_rules);
        free_act_rules(&px->http_res_rules);
        free_act_rules(&px->http_after_res_rules);
+#ifdef USE_QUIC
+       free_act_rules(&px->quic_init_rules);
+#endif
 
        lf_expr_deinit(&px->logformat);
        lf_expr_deinit(&px->logformat_sd);
@@ -1386,6 +1389,9 @@ void init_new_proxy(struct proxy *p)
        LIST_INIT(&p->tcp_rep.inspect_rules);
        LIST_INIT(&p->tcp_req.l4_rules);
        LIST_INIT(&p->tcp_req.l5_rules);
+#ifdef USE_QUIC
+       LIST_INIT(&p->quic_init_rules);
+#endif
        MT_LIST_INIT(&p->listener_queue);
        LIST_INIT(&p->loggers);
        LIST_INIT(&p->conf.bind);
diff --git a/src/quic_rules.c b/src/quic_rules.c
new file mode 100644 (file)
index 0000000..909c0a0
--- /dev/null
@@ -0,0 +1,103 @@
+#include <haproxy/quic_rules.h>
+
+#include <haproxy/acl.h>
+#include <haproxy/action.h>
+#include <haproxy/list.h>
+#include <haproxy/listener.h>
+#include <haproxy/proxy-t.h>
+#include <haproxy/sample-t.h>
+
+/* Execute registered quic-initial rules on proxy owning <li> listener. */
+int quic_init_exec_rules(struct listener *li)
+{
+       struct act_rule *rule;
+       enum acl_test_res ret;
+       struct proxy *px;
+       int result = 1;
+
+       px = li->bind_conf->frontend;
+
+       list_for_each_entry(rule, &px->quic_init_rules, list) {
+               ret = ACL_TEST_PASS;
+
+               if (rule->cond) {
+                       ret = acl_exec_cond(rule->cond, px, NULL, NULL, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
+                       ret = acl_pass(ret);
+                       if (rule->cond->pol == ACL_COND_UNLESS)
+                               ret = !ret;
+               }
+
+               if (ret) {
+                       if (rule->action_ptr) {
+                               switch (rule->action_ptr(rule, px, NULL, NULL, 0)) {
+                               case ACT_RET_CONT:
+                                       break;
+                               case ACT_RET_DONE:
+                               case ACT_RET_STOP:
+                                       goto end;
+                               case ACT_RET_ABRT:
+                               case ACT_RET_DENY:
+                               case ACT_RET_ERR:
+                               case ACT_RET_INV:
+                                       result = 0;
+                                       goto end;
+                               default:
+                                       ABORT_NOW("not implemented");
+                               }
+                       }
+                       else if (rule->action == ACT_ACTION_ALLOW) {
+                               goto end;
+                       }
+                       else if (rule->action == ACT_ACTION_DENY) {
+                               result = 0;
+                               goto end;
+                       }
+               }
+       }
+
+ end:
+       return result;
+}
+
+static enum act_parse_ret parse_accept(const char **args, int *orig_arg,
+                                       struct proxy *px,
+                                       struct act_rule *rule, char **err)
+{
+       rule->action = ACT_ACTION_ALLOW;
+       rule->flags |= ACT_FLAG_FINAL;
+       return ACT_RET_PRS_OK;
+}
+
+static enum act_parse_ret parse_dgram_drop(const char **args, int *orig_arg,
+                                           struct proxy *px,
+                                           struct act_rule *rule, char **err)
+{
+       rule->action = ACT_ACTION_DENY;
+       rule->flags |= ACT_FLAG_FINAL;
+       return ACT_RET_PRS_OK;
+}
+
+/* List head of all known action keywords for "quic-initial" */
+struct action_kw_list quic_init_actions_list = {
+       .list = LIST_HEAD_INIT(quic_init_actions_list.list)
+};
+
+void quic_init_actions_register(struct action_kw_list *kw_list)
+{
+       LIST_APPEND(&quic_init_actions_list.list, &kw_list->list);
+}
+
+/* Return the struct quic-initial action associated to a keyword. */
+struct action_kw *action_quic_init_custom(const char *kw)
+{
+       return action_lookup(&quic_init_actions_list.list, kw);
+}
+
+static struct action_kw_list quic_init_actions = { ILH, {
+               { "accept",           parse_accept,            0 },
+               { "dgram-drop",       parse_dgram_drop,        0 },
+               { /* END */ },
+       }
+};
+
+INITCALL1(STG_REGISTER, quic_init_actions_register, &quic_init_actions);
index fa82042a0b75ac447917a962322af0bd3ead0c1f..6bec16dc6563664374c4fcbfb0f9004c1246e0a7 100644 (file)
@@ -22,6 +22,7 @@
 #include <haproxy/quic_cid.h>
 #include <haproxy/quic_retransmit.h>
 #include <haproxy/quic_retry.h>
+#include <haproxy/quic_rules.h>
 #include <haproxy/quic_sock.h>
 #include <haproxy/quic_stream.h>
 #include <haproxy/quic_ssl.h>
@@ -1605,8 +1606,15 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
                                if (!quic_retry_token_check(pkt, dgram, l, qc, &token_odcid))
                                        goto err;
                        }
-                       else if ((l->bind_conf->options & BC_O_QUIC_FORCE_RETRY) ||
-                                HA_ATOMIC_LOAD(&prx_counters->half_open_conn) >= global.tune.quic_retry_threshold) {
+
+                       if (!quic_init_exec_rules(l)) {
+                               TRACE_USER("drop datagram on quic-initial rules", QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
+                               goto err;
+                       }
+
+                       if (!pkt->token_len &&
+                           ((l->bind_conf->options & BC_O_QUIC_FORCE_RETRY) ||
+                            HA_ATOMIC_LOAD(&prx_counters->half_open_conn) >= global.tune.quic_retry_threshold)) {
 
                                TRACE_PROTO("Initial without token, sending retry",
                                            QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);