MEDIUM: http-rules: Rely on http reply for http deny/tarpit rules
"http-request deny", "http-request tarpit" and "http-response deny" rules now use the same syntax than http return rules and internally rely on the http replies. The behaviour is not the same when no argument is specified (or only the status code). For http replies, a dummy response is produced, with no payload. For old deny/tarpit rules, the proxy's error messages are used. Thus, to be compatible with existing configuration, the "default-errorfiles" parameter is implied. For instance : http-request deny deny_status 404 is now an alias of http-request deny status 404 default-errorfiles
This commit is contained in:
parent
0e2ad61315
commit
5cb513abeb
@ -4991,18 +4991,22 @@ http-request del-map(<file-name>) <key fmt> [ { if | unless } <condition> ]
|
||||
It takes one argument: "file name" It is the equivalent of the "del map"
|
||||
command from the stats socket, but can be triggered by an HTTP request.
|
||||
|
||||
http-request deny [deny_status <status>] [ { errorfile | errorfiles } <err> ]
|
||||
[ { if | unless } <condition> ]
|
||||
http-request deny [deny_status <status>] [ { if | unless } <condition> ]
|
||||
http-request 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> ]*
|
||||
[ { if | unless } <condition> ]
|
||||
|
||||
This stops the evaluation of the rules and immediately rejects the request
|
||||
and emits an HTTP 403 error, or optionally the status code specified as an
|
||||
argument to "deny_status". The list of permitted status codes is limited to
|
||||
those that can be overridden by the "errorfile" directive. A specific error
|
||||
message may be specified. It may be an error file, using the "errorfile"
|
||||
keyword followed by the file containing the full HTTP response. It may also
|
||||
be an error from an http-errors section, using the "errorfiles" keyword
|
||||
followed by the section name.
|
||||
This stops the evaluation of the rules and immediately rejects the request.
|
||||
By default an HTTP 403 error is returned. But the response may be customized
|
||||
using same syntax than "http-request return" rules. Thus, see "http-request
|
||||
return" for details. For compatiblity purpose, when no argument is defined,
|
||||
or only "deny_status", the argument "default-errorfiles" is implied. It means
|
||||
"http-request deny [deny_status <status>]" is an alias of
|
||||
"http-request deny [status <status>] default-errorfiles".
|
||||
No further "http-request" rules are evaluated.
|
||||
See also "http-request return".
|
||||
|
||||
http-request disable-l7-retry [ { if | unless } <condition> ]
|
||||
This disables any attempt to retry the request if it fails for any other
|
||||
@ -5576,26 +5580,32 @@ http-request strict-mode { on | off }
|
||||
the frontend, the default mode is restored when HAProxy starts the backend
|
||||
rules evaluation.
|
||||
|
||||
http-request tarpit [deny_status <status>] [ { errorfile | errorfiles } <err> ]
|
||||
[ { if | unless } <condition> ]
|
||||
http-request tarpit [deny_status <status>] [ { if | unless } <condition> ]
|
||||
http-request 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> ]*
|
||||
[ { if | unless } <condition> ]
|
||||
|
||||
This stops the evaluation of the rules and immediately blocks the request
|
||||
without responding for a delay specified by "timeout tarpit" or
|
||||
"timeout connect" if the former is not set. After that delay, if the client
|
||||
is still connected, an HTTP error 500 (or optionally the status code
|
||||
specified as an argument to "deny_status") is returned so that the client
|
||||
does not suspect it has been tarpitted. Logs will report the flags "PT".
|
||||
The goal of the tarpit rule is to slow down robots during an attack when
|
||||
they're limited on the number of concurrent requests. It can be very
|
||||
efficient against very dumb robots, and will significantly reduce the load
|
||||
on firewalls compared to a "deny" rule. But when facing "correctly"
|
||||
developed robots, it can make things worse by forcing haproxy and the front
|
||||
firewall to support insane number of concurrent connections. A specific error
|
||||
message may be specified. It may be an error file, using the "errorfile"
|
||||
keyword followed by the file containing the full HTTP response. It may also
|
||||
be an error from an http-errors section, using the "errorfiles" keyword
|
||||
followed by the section name.
|
||||
See also the "silent-drop" action.
|
||||
is still connected, a response is returned so that the client does not
|
||||
suspect it has been tarpitted. Logs will report the flags "PT". The goal of
|
||||
the tarpit rule is to slow down robots during an attack when they're limited
|
||||
on the number of concurrent requests. It can be very efficient against very
|
||||
dumb robots, and will significantly reduce the load on firewalls compared to
|
||||
a "deny" rule. But when facing "correctly" developed robots, it can make
|
||||
things worse by forcing haproxy and the front firewall to support insane
|
||||
number of concurrent connections. By default an HTTP error 500 is returned.
|
||||
But the response may be customized using same syntax than
|
||||
"http-request return" rules. Thus, see "http-request return" for details.
|
||||
For compatiblity purpose, when no argument is defined, or only "deny_status",
|
||||
the argument "default-errorfiles" is implied. It means
|
||||
"http-request tarpit [deny_status <status>]" is an alias of
|
||||
"http-request tarpit [status <status>] default-errorfiles".
|
||||
No further "http-request" rules are evaluated.
|
||||
See also "http-request return" and "http-request silent-drop".
|
||||
|
||||
http-request track-sc0 <key> [table <table>] [ { if | unless } <condition> ]
|
||||
http-request track-sc1 <key> [table <table>] [ { if | unless } <condition> ]
|
||||
@ -5779,18 +5789,22 @@ http-response del-map(<file-name>) <key fmt> [ { if | unless } <condition> ]
|
||||
It takes one argument: "file name" It is the equivalent of the "del map"
|
||||
command from the stats socket, but can be triggered by an HTTP response.
|
||||
|
||||
http-response deny [deny_status <status>] [ { errorfile | errorfiles } <err> ]
|
||||
[ { if | unless } <condition> ]
|
||||
http-response deny [deny_status <status>] [ { if | unless } <condition> ]
|
||||
http-response 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> ]*
|
||||
[ { if | unless } <condition> ]
|
||||
|
||||
This stops the evaluation of the rules and immediately rejects the response
|
||||
and emits an HTTP 502 error, or optionally the status code specified as an
|
||||
argument to "deny_status". The list of permitted status codes is limited to
|
||||
those that can be overridden by the "errorfile" directive. A specific error
|
||||
message may be specified. It may be an error file, using the "errorfile"
|
||||
keyword followed by the file containing the full HTTP response. It may also
|
||||
be an error from an http-errors section, using the "errorfiles" keyword
|
||||
followed by the section name.
|
||||
This stops the evaluation of the rules and immediately rejects the response.
|
||||
By default an HTTP 502 error is returned. But the response may be customized
|
||||
using same syntax than "http-response return" rules. Thus, see
|
||||
"http-response return" for details. For compatiblity purpose, when no
|
||||
argument is defined, or only "deny_status", the argument "default-errorfiles"
|
||||
is implied. It means "http-response deny [deny_status <status>]" is an alias
|
||||
of "http-response deny [status <status>] default-errorfiles".
|
||||
No further "http-response" rules are evaluated.
|
||||
See also "http-response return".
|
||||
|
||||
http-response redirect <rule> [ { if | unless } <condition> ]
|
||||
|
||||
|
@ -125,11 +125,7 @@ struct act_rule {
|
||||
struct list fmt; /* log-format compatible expression */
|
||||
struct my_regex *re; /* used by replace-header/value/uri/path */
|
||||
} http; /* args used by some HTTP rules */
|
||||
struct {
|
||||
int status; /* status code */
|
||||
struct buffer *errmsg; /* HTTP error message, may be NULL */
|
||||
} http_deny; /* args used by HTTP deny rules */
|
||||
struct http_reply *http_reply; /* HTTP response to be used by return rules */
|
||||
struct http_reply *http_reply; /* HTTP response to be used by return/deny/tarpit rules */
|
||||
struct redirect_rule *redir; /* redirect rule or "http-request redirect" */
|
||||
struct {
|
||||
char *ref; /* MAP or ACL file name to update */
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <common/http.h>
|
||||
|
||||
#include <types/channel.h>
|
||||
#include <types/http_htx.h>
|
||||
|
||||
/* These are the flags that are found in txn->flags */
|
||||
|
||||
@ -174,6 +175,7 @@ struct http_txn {
|
||||
/* 1 unused byte here */
|
||||
short status; /* HTTP status from the server, negative if from proxy */
|
||||
struct buffer *errmsg; /* custom HTTP error message to use as reply */
|
||||
struct http_reply *http_reply; /* The HTTP reply to use as reply */
|
||||
|
||||
char cache_hash[20]; /* Store the cache hash */
|
||||
char *uri; /* first line if log needed, NULL otherwise */
|
||||
|
1
reg-tests/http-errorfiles/errors/lf-403.txt
Normal file
1
reg-tests/http-errorfiles/errors/lf-403.txt
Normal file
@ -0,0 +1 @@
|
||||
The path "%[path]" is forbidden
|
@ -27,6 +27,9 @@ haproxy h1 -conf {
|
||||
http-request deny deny_status 500 errorfile /dev/null if { path /500-1 }
|
||||
http-request deny deny_status 500 errorfiles errors-1 if { path /500-2 }
|
||||
|
||||
http-request deny status 500 hdr x-err-info "path=%[path]" content-type "text/plain" string "Internal Error" if { path /int-err }
|
||||
http-request deny status 403 hdr x-err-info "path=%[path]" content-type "text/plain" lf-file ${testdir}/errors/lf-403.txt if { path /forbidden }
|
||||
|
||||
} -start
|
||||
|
||||
client c1r1 -connect ${h1_fe1_sock} {
|
||||
@ -55,3 +58,20 @@ client c1r5 -connect ${h1_fe1_sock} {
|
||||
txreq -req GET -url /500-2
|
||||
expect_close
|
||||
} -run
|
||||
client c1r6 -connect ${h1_fe1_sock} {
|
||||
txreq -req GET -url /int-err
|
||||
rxresp
|
||||
expect resp.status == 500
|
||||
expect resp.http.x-err-info == "path=/int-err"
|
||||
expect resp.http.content-type == "text/plain"
|
||||
expect resp.http.content-length == 14
|
||||
expect resp.body == "Internal Error"
|
||||
} -run
|
||||
client c1r7 -connect ${h1_fe1_sock} {
|
||||
txreq -req GET -url /forbidden
|
||||
rxresp
|
||||
expect resp.status == 403
|
||||
expect resp.http.x-err-info == "path=/forbidden"
|
||||
expect resp.http.content-type == "text/plain"
|
||||
expect resp.body == "The path \"/forbidden\" is forbidden\n"
|
||||
} -run
|
||||
|
172
src/http_act.c
172
src/http_act.c
@ -58,6 +58,30 @@ static void release_http_action(struct act_rule *rule)
|
||||
}
|
||||
}
|
||||
|
||||
/* Release memory allocated by HTTP actions relying on an http reply. Concretly,
|
||||
* it releases <.arg.http_reply>
|
||||
*/
|
||||
static void release_act_http_reply(struct act_rule *rule)
|
||||
{
|
||||
release_http_reply(rule->arg.http_reply);
|
||||
rule->arg.http_reply = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Check function for HTTP actions relying on an http reply. The function
|
||||
* returns 1 in success case, otherwise, it returns 0 and err is filled.
|
||||
*/
|
||||
static int check_act_http_reply(struct act_rule *rule, struct proxy *px, char **err)
|
||||
{
|
||||
struct http_reply *reply = rule->arg.http_reply;
|
||||
|
||||
if (!http_check_http_reply(reply, px, err)) {
|
||||
release_act_http_reply(rule);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* This function executes one of the set-{method,path,query,uri} actions. It
|
||||
* builds a string in the trash from the specified format string. It finds
|
||||
@ -797,119 +821,66 @@ static enum act_parse_ret parse_http_allow(const char **args, int *orig_arg, str
|
||||
return ACT_RET_PRS_OK;
|
||||
}
|
||||
|
||||
/* Check an "http-request deny" action when an http-errors section is referenced.
|
||||
*
|
||||
* The function returns 1 in success case, otherwise, it returns 0 and err is
|
||||
* filled.
|
||||
*/
|
||||
static int check_http_deny_action(struct act_rule *rule, struct proxy *px, char **err)
|
||||
{
|
||||
struct http_errors *http_errs;
|
||||
int status = (intptr_t)(rule->arg.act.p[0]);
|
||||
int ret = 1;
|
||||
|
||||
list_for_each_entry(http_errs, &http_errors_list, list) {
|
||||
if (strcmp(http_errs->id, (char *)rule->arg.act.p[1]) == 0) {
|
||||
free(rule->arg.act.p[1]);
|
||||
rule->arg.http_deny.status = status;
|
||||
rule->arg.http_deny.errmsg = http_errs->errmsg[http_get_status_idx(status)];
|
||||
if (!rule->arg.http_deny.errmsg)
|
||||
ha_warning("Proxy '%s': status '%d' referenced by http deny rule "
|
||||
"not declared in http-errors section '%s'.\n",
|
||||
px->id, status, http_errs->id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (&http_errs->list == &http_errors_list) {
|
||||
memprintf(err, "unknown http-errors section '%s' referenced by http deny rule",
|
||||
(char *)rule->arg.act.p[1]);
|
||||
free(rule->arg.act.p[1]);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Parse "deny" or "tarpit" actions for a request rule or "deny" action for a
|
||||
* response rule. It may take optional arguments to define the status code, the
|
||||
* error file or the http-errors section to use. It returns ACT_RET_PRS_OK on
|
||||
* success, ACT_RET_PRS_ERR on error.
|
||||
* response rule. It returns ACT_RET_PRS_OK on success, ACT_RET_PRS_ERR on
|
||||
* error. It relies on http_parse_http_reply() to set
|
||||
* <.arg.http_reply>.
|
||||
*/
|
||||
static enum act_parse_ret parse_http_deny(const char **args, int *orig_arg, struct proxy *px,
|
||||
struct act_rule *rule, char **err)
|
||||
{
|
||||
int default_status, status, hc, cur_arg;
|
||||
|
||||
int default_status;
|
||||
int cur_arg, arg = 0;
|
||||
|
||||
cur_arg = *orig_arg;
|
||||
if (rule->from == ACT_F_HTTP_REQ) {
|
||||
if (!strcmp(args[cur_arg-1], "tarpit")) {
|
||||
rule->action = ACT_HTTP_REQ_TARPIT;
|
||||
default_status = status = 500;
|
||||
default_status = 500;
|
||||
}
|
||||
else {
|
||||
rule->action = ACT_ACTION_DENY;
|
||||
default_status = status = 403;
|
||||
default_status = 403;
|
||||
}
|
||||
}
|
||||
else {
|
||||
rule->action = ACT_ACTION_DENY;
|
||||
default_status = status = 502;
|
||||
default_status = 502;
|
||||
}
|
||||
|
||||
/* If no args or only a deny_status specified, fallback on the legacy
|
||||
* mode and use default error files despite the fact that
|
||||
* default-errorfiles is not used. Otherwise, parse an http reply.
|
||||
*/
|
||||
|
||||
/* Prepare parsing of log-format strings */
|
||||
px->conf.args.ctx = ((rule->from == ACT_F_HTTP_REQ) ? ARGC_HRQ : ARGC_HRS);
|
||||
|
||||
if (!*(args[cur_arg])) {
|
||||
rule->arg.http_reply = http_parse_http_reply((const char *[]){"default-errorfiles", ""}, &arg, px, default_status, err);
|
||||
goto end;
|
||||
}
|
||||
rule->flags |= ACT_FLAG_FINAL;
|
||||
|
||||
if (strcmp(args[cur_arg], "deny_status") == 0) {
|
||||
cur_arg++;
|
||||
if (!*args[cur_arg]) {
|
||||
memprintf(err, "'%s' expects <status_code> as argument", args[cur_arg-1]);
|
||||
return ACT_RET_PRS_ERR;
|
||||
}
|
||||
|
||||
status = atol(args[cur_arg]);
|
||||
cur_arg++;
|
||||
for (hc = 0; hc < HTTP_ERR_SIZE; hc++) {
|
||||
if (http_err_codes[hc] == status)
|
||||
break;
|
||||
}
|
||||
if (hc >= HTTP_ERR_SIZE) {
|
||||
memprintf(err, "status code '%d' not handled, using default code '%d'",
|
||||
status, default_status);
|
||||
status = default_status;
|
||||
hc = http_get_status_idx(status);
|
||||
if (!*(args[cur_arg+2]) ||
|
||||
(strcmp(args[cur_arg+2], "errorfile") != 0 && strcmp(args[cur_arg+2], "errorfiles") != 0)) {
|
||||
rule->arg.http_reply = http_parse_http_reply((const char *[]){"status", args[cur_arg+1], "default-errorfiles", ""},
|
||||
&arg, px, default_status, err);
|
||||
*orig_arg += 2;
|
||||
goto end;
|
||||
}
|
||||
args[cur_arg] += 5; /* skip "deny_" for the parsing */
|
||||
}
|
||||
|
||||
if (strcmp(args[cur_arg], "errorfile") == 0) {
|
||||
cur_arg++;
|
||||
if (!*args[cur_arg]) {
|
||||
memprintf(err, "'%s' expects <file> as argument", args[cur_arg-1]);
|
||||
return ACT_RET_PRS_ERR;
|
||||
}
|
||||
rule->arg.http_reply = http_parse_http_reply(args, orig_arg, px, default_status, err);
|
||||
|
||||
rule->arg.http_deny.errmsg = http_load_errorfile(args[cur_arg], err);
|
||||
if (!rule->arg.http_deny.errmsg)
|
||||
return ACT_RET_PRS_ERR;
|
||||
cur_arg++;
|
||||
}
|
||||
else if (strcmp(args[cur_arg], "errorfiles") == 0) {
|
||||
cur_arg++;
|
||||
if (!*args[cur_arg]) {
|
||||
memprintf(err, "'%s' expects <http_errors_name> as argument", args[cur_arg-1]);
|
||||
return ACT_RET_PRS_ERR;
|
||||
}
|
||||
/* Must be resolved during the config validity check */
|
||||
rule->arg.act.p[0] = (void *)((intptr_t)status);
|
||||
rule->arg.act.p[1] = strdup(args[cur_arg]);
|
||||
rule->check_ptr = check_http_deny_action;
|
||||
cur_arg++;
|
||||
goto out;
|
||||
}
|
||||
end:
|
||||
if (!rule->arg.http_reply)
|
||||
return ACT_RET_PRS_ERR;
|
||||
|
||||
rule->arg.http_deny.status = status;
|
||||
|
||||
out:
|
||||
*orig_arg = cur_arg;
|
||||
rule->flags |= ACT_FLAG_FINAL;
|
||||
rule->check_ptr = check_act_http_reply;
|
||||
rule->release_ptr = release_act_http_reply;
|
||||
return ACT_RET_PRS_OK;
|
||||
}
|
||||
|
||||
@ -1802,13 +1773,6 @@ static enum act_parse_ret parse_http_strict_mode(const char **args, int *orig_ar
|
||||
return ACT_RET_PRS_OK;
|
||||
}
|
||||
|
||||
/* Release <.arg.http_reply> */
|
||||
static void release_http_return(struct act_rule *rule)
|
||||
{
|
||||
release_http_reply(rule->arg.http_reply);
|
||||
rule->arg.http_reply = NULL;
|
||||
}
|
||||
|
||||
/* This function executes a return action. It builds an HTX message from an
|
||||
* errorfile, an raw file or a log-format string, depending on <.action>
|
||||
* value. On success, it returns ACT_RET_ABRT. If an error occurs ACT_RET_ERR is
|
||||
@ -1839,20 +1803,6 @@ static enum act_return http_action_return(struct act_rule *rule, struct proxy *p
|
||||
return ACT_RET_ABRT;
|
||||
}
|
||||
|
||||
/* Check an "http-request return" action. The function returns 1 in success
|
||||
* case, otherwise, it returns 0 and err is filled.
|
||||
*/
|
||||
static int check_http_return_action(struct act_rule *rule, struct proxy *px, char **err)
|
||||
{
|
||||
struct http_reply *reply = rule->arg.http_reply;
|
||||
|
||||
if (!http_check_http_reply(reply, px, err)) {
|
||||
release_http_return(rule);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Parse a "return" action. It returns ACT_RET_PRS_OK on success,
|
||||
* ACT_RET_PRS_ERR on error. It relies on http_parse_http_reply() to set
|
||||
* <.arg.http_reply>.
|
||||
@ -1868,9 +1818,9 @@ static enum act_parse_ret parse_http_return(const char **args, int *orig_arg, st
|
||||
|
||||
rule->flags |= ACT_FLAG_FINAL;
|
||||
rule->action = ACT_CUSTOM;
|
||||
rule->check_ptr = check_http_return_action;
|
||||
rule->check_ptr = check_act_http_reply;
|
||||
rule->action_ptr = http_action_return;
|
||||
rule->release_ptr = release_http_return;
|
||||
rule->release_ptr = release_act_http_reply;
|
||||
return ACT_RET_PRS_OK;
|
||||
}
|
||||
|
||||
|
@ -672,6 +672,12 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s
|
||||
_HA_ATOMIC_ADD(&s->be->be_counters.denied_req, 1);
|
||||
if (sess->listener->counters)
|
||||
_HA_ATOMIC_ADD(&sess->listener->counters->denied_req, 1);
|
||||
|
||||
if (txn->http_reply) {
|
||||
if (http_reply_message(s, txn->http_reply) == -1)
|
||||
goto return_int_err;
|
||||
goto return_prx_cond;
|
||||
}
|
||||
goto return_prx_err;
|
||||
|
||||
return_int_err:
|
||||
@ -1002,8 +1008,28 @@ int http_process_tarpit(struct stream *s, struct channel *req, int an_bit)
|
||||
*/
|
||||
s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
|
||||
|
||||
http_reply_and_close(s, txn->status, (!(req->flags & CF_READ_ERROR) ? http_error_message(s) : NULL));
|
||||
if (req->flags & CF_READ_ERROR) {
|
||||
http_reply_and_close(s, txn->status, NULL);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (txn->http_reply) {
|
||||
if (!http_reply_message(s, txn->http_reply))
|
||||
goto end;
|
||||
|
||||
txn->status = 500;
|
||||
if (!(s->flags & SF_ERR_MASK))
|
||||
s->flags |= SF_ERR_INTERNAL;
|
||||
_HA_ATOMIC_ADD(&s->sess->fe->fe_counters.internal_errors, 1);
|
||||
if (s->flags & SF_BE_ASSIGNED)
|
||||
_HA_ATOMIC_ADD(&s->be->be_counters.internal_errors, 1);
|
||||
if (s->sess->listener->counters)
|
||||
_HA_ATOMIC_ADD(&s->sess->listener->counters->internal_errors, 1);
|
||||
}
|
||||
|
||||
http_reply_and_close(s, txn->status, http_error_message(s));
|
||||
|
||||
end:
|
||||
req->analysers &= AN_REQ_FLT_END;
|
||||
req->analyse_exp = TICK_ETERNITY;
|
||||
|
||||
@ -2159,6 +2185,12 @@ int http_process_res_common(struct stream *s, struct channel *rep, int an_bit, s
|
||||
_HA_ATOMIC_ADD(&sess->listener->counters->denied_resp, 1);
|
||||
if (objt_server(s->target))
|
||||
_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.denied_resp, 1);
|
||||
|
||||
if (txn->http_reply) {
|
||||
if (http_reply_message(s, txn->http_reply) == -1)
|
||||
goto return_int_err;
|
||||
goto return_prx_cond;
|
||||
}
|
||||
goto return_prx_err;
|
||||
|
||||
return_int_err:
|
||||
@ -2907,17 +2939,15 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
|
||||
goto end;
|
||||
|
||||
case ACT_ACTION_DENY:
|
||||
txn->status = rule->arg.http_deny.status;
|
||||
if (rule->arg.http_deny.errmsg)
|
||||
txn->errmsg = rule->arg.http_deny.errmsg;
|
||||
txn->status = rule->arg.http_reply->status;
|
||||
txn->http_reply = rule->arg.http_reply;
|
||||
rule_ret = HTTP_RULE_RES_DENY;
|
||||
goto end;
|
||||
|
||||
case ACT_HTTP_REQ_TARPIT:
|
||||
txn->flags |= TX_CLTARPIT;
|
||||
txn->status = rule->arg.http_deny.status;
|
||||
if (rule->arg.http_deny.errmsg)
|
||||
txn->errmsg = rule->arg.http_deny.errmsg;
|
||||
txn->status = rule->arg.http_reply->status;
|
||||
txn->http_reply = rule->arg.http_reply;
|
||||
rule_ret = HTTP_RULE_RES_DENY;
|
||||
goto end;
|
||||
|
||||
@ -3085,9 +3115,8 @@ resume_execution:
|
||||
goto end;
|
||||
|
||||
case ACT_ACTION_DENY:
|
||||
txn->status = rule->arg.http_deny.status;
|
||||
if (rule->arg.http_deny.errmsg)
|
||||
txn->errmsg = rule->arg.http_deny.errmsg;
|
||||
txn->status = rule->arg.http_reply->status;
|
||||
txn->http_reply = rule->arg.http_reply;
|
||||
rule_ret = HTTP_RULE_RES_DENY;
|
||||
goto end;
|
||||
|
||||
@ -4688,9 +4717,7 @@ int http_reply_message(struct stream *s, struct http_reply *reply)
|
||||
/* get default error message */
|
||||
errmsg = http_error_message(s);
|
||||
}
|
||||
if (b_is_null(errmsg))
|
||||
goto leave;
|
||||
if (!channel_htx_copy_msg(res, htx, errmsg))
|
||||
if (!b_is_null(errmsg) && !channel_htx_copy_msg(res, htx, errmsg))
|
||||
goto fail;
|
||||
}
|
||||
else {
|
||||
@ -5178,6 +5205,7 @@ void http_init_txn(struct stream *s)
|
||||
: 0);
|
||||
txn->status = -1;
|
||||
txn->errmsg = NULL;
|
||||
txn->http_reply = NULL;
|
||||
write_u32(txn->cache_hash, 0);
|
||||
|
||||
txn->cookie_first_date = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user