See also: "rspadd" and section 6 about HTTP header manipulation
-reqallow <search>
-reqiallow <search> (ignore case)
+reqallow <search> [{if | unless} <cond>]
+reqiallow <search> [{if | unless} <cond>] (ignore case)
Definitely allow an HTTP request if a line matches a regular expression
May be used in sections : defaults | frontend | listen | backend
no | yes | yes | yes
"reqallow" keyword strictly matches case while "reqiallow"
ignores case.
+ <cond> is an optional matching condition built from ACLs. It makes it
+ possible to ignore this rule when other conditions are not met.
+
A request containing any line which matches extended regular expression
<search> will mark the request as allowed, even if any later test would
result in a deny. The test applies both to the request line and to request
reqiallow ^Host:\ www\.
reqideny ^Host:\ .*\.local
- See also: "reqdeny", "acl", "block" and section 6 about HTTP header
- manipulation
+ See also: "reqdeny", "block", section 6 about HTTP header manipulation, and
+ section 7 about ACLs.
-reqdel <search>
-reqidel <search> (ignore case)
+reqdel <search> [{if | unless} <cond>]
+reqidel <search> [{if | unless} <cond>] (ignore case)
Delete all headers matching a regular expression in an HTTP request
May be used in sections : defaults | frontend | listen | backend
no | yes | yes | yes
('\'). The pattern applies to a full line at a time. The "reqdel"
keyword strictly matches case while "reqidel" ignores case.
+ <cond> is an optional matching condition built from ACLs. It makes it
+ possible to ignore this rule when other conditions are not met.
+
Any header line matching extended regular expression <search> in the request
will be completely deleted. Most common use of this is to remove unwanted
and/or dangerous headers or cookies from a request before passing it to the
reqidel ^X-Forwarded-For:.*
reqidel ^Cookie:.*SERVER=
- See also: "reqadd", "reqrep", "rspdel" and section 6 about HTTP header
- manipulation
+ See also: "reqadd", "reqrep", "rspdel", section 6 about HTTP header
+ manipulation, and section 7 about ACLs.
-reqdeny <search>
-reqideny <search> (ignore case)
+reqdeny <search> [{if | unless} <cond>]
+reqideny <search> [{if | unless} <cond>] (ignore case)
Deny an HTTP request if a line matches a regular expression
May be used in sections : defaults | frontend | listen | backend
no | yes | yes | yes
"reqdeny" keyword strictly matches case while "reqideny" ignores
case.
+ <cond> is an optional matching condition built from ACLs. It makes it
+ possible to ignore this rule when other conditions are not met.
+
A request containing any line which matches extended regular expression
<search> will mark the request as denied, even if any later test would
result in an allow. The test applies both to the request line and to request
reqideny ^Host:\ .*\.local
reqiallow ^Host:\ www\.
- See also: "reqallow", "rspdeny", "acl", "block" and section 6 about HTTP
- header manipulation
+ See also: "reqallow", "rspdeny", "block", section 6 about HTTP header
+ manipulation, and section 7 about ACLs.
-reqpass <search>
-reqipass <search> (ignore case)
+reqpass <search> [{if | unless} <cond>]
+reqipass <search> [{if | unless} <cond>] (ignore case)
Ignore any HTTP request line matching a regular expression in next rules
May be used in sections : defaults | frontend | listen | backend
no | yes | yes | yes
"reqpass" keyword strictly matches case while "reqipass" ignores
case.
+ <cond> is an optional matching condition built from ACLs. It makes it
+ possible to ignore this rule when other conditions are not met.
+
A request containing any line which matches extended regular expression
<search> will skip next rules, without assigning any deny or allow verdict.
The test applies both to the request line and to request headers. Keep in
reqideny ^Host:\ .*\.local
reqiallow ^Host:\ www\.
- See also: "reqallow", "reqdeny", "acl", "block" and section 6 about HTTP
- header manipulation
+ See also: "reqallow", "reqdeny", "block", section 6 about HTTP header
+ manipulation, and section 7 about ACLs.
-reqrep <search> <string>
-reqirep <search> <string> (ignore case)
+reqrep <search> <string> [{if | unless} <cond>]
+reqirep <search> <string> [{if | unless} <cond>] (ignore case)
Replace a regular expression with a string in an HTTP request line
May be used in sections : defaults | frontend | listen | backend
no | yes | yes | yes
being a single digit between 0 and 9. Please refer to section
6 about HTTP header manipulation for more information.
+ <cond> is an optional matching condition built from ACLs. It makes it
+ possible to ignore this rule when other conditions are not met.
+
Any line matching extended regular expression <search> in the request (both
the request line and header lines) will be completely replaced with <string>.
Most common use of this is to rewrite URLs or domain names in "Host" headers.
# replace "www.mydomain.com" with "www" in the host name.
reqirep ^Host:\ www.mydomain.com Host:\ www
- See also: "reqadd", "reqdel", "rsprep" and section 6 about HTTP header
- manipulation
+ See also: "reqadd", "reqdel", "rsprep", section 6 about HTTP header
+ manipulation, and section 7 about ACLs.
-reqtarpit <search>
-reqitarpit <search> (ignore case)
+reqtarpit <search> [{if | unless} <cond>]
+reqitarpit <search> [{if | unless} <cond>] (ignore case)
Tarpit an HTTP request containing a line matching a regular expression
May be used in sections : defaults | frontend | listen | backend
no | yes | yes | yes
"reqtarpit" keyword strictly matches case while "reqitarpit"
ignores case.
+ <cond> is an optional matching condition built from ACLs. It makes it
+ possible to ignore this rule when other conditions are not met.
+
A request containing any line which matches extended regular expression
<search> will be tarpitted, which means that it will connect to nowhere, will
be kept open for a pre-defined time, then will return an HTTP error 500 so
come. Depending on the environment and attack, it may be particularly
efficient at reducing the load on the network and firewalls.
- Example :
+ Examples :
# ignore user-agents reporting any flavour of "Mozilla" or "MSIE", but
# block all others.
reqipass ^User-Agent:\.*(Mozilla|MSIE)
reqitarpit ^User-Agent:
- See also: "reqallow", "reqdeny", "reqpass", and section 6 about HTTP header
- manipulation
+ # block bad guys
+ acl badguys src 10.1.0.3 172.16.13.20/28
+ reqitarpit . if badguys
+
+ See also: "reqallow", "reqdeny", "reqpass", section 6 about HTTP header
+ manipulation, and section 7 about ACLs.
retries <value>
regex_t *preg = NULL;
const char *err;
int err_code = 0;
+ struct acl_cond *cond = NULL;
if (px == &defproxy) {
Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
err_code |= ERR_WARN;
+ if (cond_start &&
+ (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
+ if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
+ Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
+ file, line, cmd);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto err;
+ }
+ }
+ else if (cond_start && **cond_start) {
+ Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
+ file, line, cmd, *cond_start);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto err;
+ }
+
+ if (dir == ACL_DIR_REQ)
+ err_code |= warnif_cond_requires_resp(cond, file, line);
+
preg = calloc(1, sizeof(regex_t));
if (!preg) {
Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
}
err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
- preg, action, repl ? strdup(repl) : NULL, NULL);
+ preg, action, repl ? strdup(repl) : NULL, cond);
if (repl && err) {
Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
file, line, cmd, *err);
err_code |= create_cond_regex_rule(file, linenum, curproxy,
ACL_DIR_REQ, ACT_REPLACE, 0,
- args[0], args[1], args[2], NULL);
+ args[0], args[1], args[2], (const char **)args+3);
if (err_code & ERR_FATAL)
goto out;
}
else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
err_code |= create_cond_regex_rule(file, linenum, curproxy,
ACL_DIR_REQ, ACT_REMOVE, 0,
- args[0], args[1], NULL, NULL);
+ args[0], args[1], NULL, (const char **)args+2);
if (err_code & ERR_FATAL)
goto out;
}
else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
err_code |= create_cond_regex_rule(file, linenum, curproxy,
ACL_DIR_REQ, ACT_DENY, 0,
- args[0], args[1], NULL, NULL);
+ args[0], args[1], NULL, (const char **)args+2);
if (err_code & ERR_FATAL)
goto out;
}
else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
err_code |= create_cond_regex_rule(file, linenum, curproxy,
ACL_DIR_REQ, ACT_PASS, 0,
- args[0], args[1], NULL, NULL);
+ args[0], args[1], NULL, (const char **)args+2);
if (err_code & ERR_FATAL)
goto out;
}
else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
err_code |= create_cond_regex_rule(file, linenum, curproxy,
ACL_DIR_REQ, ACT_ALLOW, 0,
- args[0], args[1], NULL, NULL);
+ args[0], args[1], NULL, (const char **)args+2);
if (err_code & ERR_FATAL)
goto out;
}
else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
err_code |= create_cond_regex_rule(file, linenum, curproxy,
ACL_DIR_REQ, ACT_TARPIT, 0,
- args[0], args[1], NULL, NULL);
+ args[0], args[1], NULL, (const char **)args+2);
if (err_code & ERR_FATAL)
goto out;
}
else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
err_code |= create_cond_regex_rule(file, linenum, curproxy,
ACL_DIR_REQ, ACT_SETBE, 0,
- args[0], args[1], args[2], NULL);
+ args[0], args[1], args[2], (const char **)args+3);
if (err_code & ERR_FATAL)
goto out;
}
else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
err_code |= create_cond_regex_rule(file, linenum, curproxy,
ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
- args[0], args[1], args[2], NULL);
+ args[0], args[1], args[2], (const char **)args+3);
if (err_code & ERR_FATAL)
goto out;
}
err_code |= create_cond_regex_rule(file, linenum, curproxy,
ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
- args[0], args[1], args[2], NULL);
+ args[0], args[1], args[2], (const char **)args+3);
if (err_code & ERR_FATAL)
goto out;
}
else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
err_code |= create_cond_regex_rule(file, linenum, curproxy,
ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
- args[0], args[1], NULL, NULL);
+ args[0], args[1], NULL, (const char **)args+2);
if (err_code & ERR_FATAL)
goto out;
}
else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
err_code |= create_cond_regex_rule(file, linenum, curproxy,
ACL_DIR_REQ, ACT_DENY, REG_ICASE,
- args[0], args[1], NULL, NULL);
+ args[0], args[1], NULL, (const char **)args+2);
if (err_code & ERR_FATAL)
goto out;
}
else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
err_code |= create_cond_regex_rule(file, linenum, curproxy,
ACL_DIR_REQ, ACT_PASS, REG_ICASE,
- args[0], args[1], NULL, NULL);
+ args[0], args[1], NULL, (const char **)args+2);
if (err_code & ERR_FATAL)
goto out;
}
else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
err_code |= create_cond_regex_rule(file, linenum, curproxy,
ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
- args[0], args[1], NULL, NULL);
+ args[0], args[1], NULL, (const char **)args+2);
if (err_code & ERR_FATAL)
goto out;
}
else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
err_code |= create_cond_regex_rule(file, linenum, curproxy,
ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
- args[0], args[1], NULL, NULL);
+ args[0], args[1], NULL, (const char **)args+2);
if (err_code & ERR_FATAL)
goto out;
}