]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MINOR] acl: add the "wait_end" acl verb
authorWilly Tarreau <w@1wt.eu>
Sun, 20 Jul 2008 09:18:28 +0000 (11:18 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 20 Jul 2008 09:18:28 +0000 (11:18 +0200)
The new "wait_end" acl delays evaluation of the rule (and the next ones)
to the end of the analysis period. This is intented to be used with TCP
content analysis. A rule referencing such an ACL will not match until
the delay is over. An equivalent default ACL "WAIT_END" has been created.

doc/configuration.txt
src/acl.c
tests/test-inspect-smtp.cfg

index 8e5f707e7393acd51637805c8a3f9d53cdb651cc..e0e6d7e4405df4bde58072201a41ddd63441b0f7 100644 (file)
@@ -3771,6 +3771,29 @@ req_ssl_ver <decimal>
   that TLSv1 is announced as SSL version 3.1. This test was designed to be used
   with TCP request content inspection.
 
+wait_end
+  Waits for the end of the analysis period to return true. This may be used in
+  conjunction with content analysis to avoid returning a wrong verdict early.
+  It may also be used to delay some actions, such as a delayed reject for some
+  special addresses. Since it either stops the rules evaluation or immediately
+  returns true, it is recommended to use this acl as the last one in a rule.
+  Please note that the default ACL "WAIT_END" is always usable without prior
+  declaration. This test was designed to be used with TCP request content
+  inspection.
+
+  Examples :
+     # delay every incoming request by 2 seconds
+     tcp-request inspect-delay 2s
+     tcp-request content accept if WAIT_END
+
+     # don't immediately tell bad guys they are rejected
+     tcp-request inspect-delay 10s
+     acl goodguys src 10.0.0.0/24
+     acl badguys  src 10.0.1.0/24
+     tcp-request content accept if goodguys
+     tcp-request content reject if badguys WAIT_END
+     tcp-request content reject
+
 
 2.3.5.3) Matching at Layer 7
 ----------------------------
@@ -3957,6 +3980,7 @@ HTTP_URL_SLASH   url_beg /                     match URL begining with "/"
 HTTP_URL_STAR    url     *                     match URL equal to "*"
 HTTP_CONTENT     hdr_val(content-length) gt 0  match an existing content-length
 REQ_CONTENT      req_len gt 0                  match data in the request buffer
+WAIT_END         wait_end                      wait for end of content analysis
 ---------------+-----------------------------+---------------------------------
 
 
index e66d502f62c102d27d3a64a54b0a6bb46d47e77f..c02ad70dafa7acea704fdf8b61a852e4748db2be 100644 (file)
--- a/src/acl.c
+++ b/src/acl.c
@@ -39,6 +39,21 @@ acl_fetch_true(struct proxy *px, struct session *l4, void *l7, int dir,
        return 1;
 }
 
+/* wait for more data as long as possible, then return TRUE. This should be
+ * used with content inspection.
+ */
+static int
+acl_fetch_wait_end(struct proxy *px, struct session *l4, void *l7, int dir,
+                  struct acl_expr *expr, struct acl_test *test)
+{
+       if (dir & ACL_PARTIAL) {
+               test->flags |= ACL_TEST_F_MAY_CHANGE;
+               return 0;
+       }
+       test->flags |= ACL_TEST_F_SET_RES_PASS;
+       return 1;
+}
+
 /* force FALSE to be returned at the fetch level */
 static int
 acl_fetch_false(struct proxy *px, struct session *l4, void *l7, int dir,
@@ -772,6 +787,7 @@ const struct {
        { .name = "HTTP_URL_STAR",  .expr = {"url","*",""}},
        { .name = "HTTP_CONTENT",   .expr = {"hdr_val(content-length)","gt","0",""}},
        { .name = "REQ_CONTENT",    .expr = {"req_len","gt","0",""}},
+       { .name = "WAIT_END",       .expr = {"wait_end",""}},
        { .name = NULL, .expr = {""}}
 };
 
@@ -1064,6 +1080,7 @@ int acl_exec_cond(struct acl_cond *cond, struct proxy *px, struct session *l4, v
 static struct acl_kw_list acl_kws = {{ },{
        { "always_true", acl_parse_nothing, acl_fetch_true, acl_match_nothing },
        { "always_false", acl_parse_nothing, acl_fetch_false, acl_match_nothing },
+       { "wait_end", acl_parse_nothing, acl_fetch_wait_end, acl_match_nothing },
 #if 0
        { "time",       acl_parse_time,  acl_fetch_time,   acl_match_time  },
 #endif
index 1c0d46dddc6f96d221816809bd8012699494c14d..5cfc8649f840d6bf2db5c73e4a010b6013fed899 100644 (file)
@@ -3,7 +3,7 @@
 #   - if the address is in the white list, then accept it and forward the
 #     connection to the server (local port 25)
 #   - if the address is in the black list, then immediately drop it
-#   - otherwise, wait up to 3 seconds. If the client talks during this time,
+#   - otherwise, wait up to 35 seconds. If the client talks during this time,
 #     drop the connection.
 #   - then accept the connection if it passes all the tests.
 #
@@ -17,19 +17,28 @@ listen block-fake-mailers
 
        mode tcp
        bind :8025
-       timeout  client 6s
-       timeout  server 6s
-       timeout connect 6s
+       timeout client 60s
+       timeout server 60s
+       timeout queue  60s
+       timeout connect 5s
 
-       tcp-request inspect-delay 4s
+       tcp-request inspect-delay 35s
 
        acl white_list src 127.0.0.2
-       acl black_list src 127.0.0.3
-       acl talkative  req_len gt 0
+       acl black_fast src 127.0.0.3  # those ones are immediately rejected
+       acl black_slow src 127.0.0.4  # those ones are rejected after a delay
 
        tcp-request content accept if white_list
-       tcp-request content reject if black_list
-       tcp-request content reject if talkative
+       tcp-request content reject if black_fast
+       tcp-request content reject if black_slow WAIT_END
+       tcp-request content reject if REQ_CONTENT
+       # note that it is possible to wait for the end of the analysis period
+       # before rejecting undesired contents
+       # tcp-request content reject if REQ_CONTENT WAIT_END
+
+       # on Linux+transparent proxy patch, it's useful to reuse the client'IP
+       # source 0.0.0.0 usesrc clientip
 
        balance roundrobin
        server mail 127.0.0.1:25
+