mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-05-08 02:40:24 +00:00
MINOR: http-act/tcp-act: Add "set-mark" and "set-tos" for tcp content rules
It is now possible to set the Netfilter MARK and the TOS field value in all packets sent to the client from any tcp-request rulesets or the "tcp-response content" one. To do so, the parsing of "set-mark" and "set-tos" actions are moved in tcp_act.c and the actions evaluation is handled in dedicated functions. This patch may be backported as far as 2.2 if necessary.
This commit is contained in:
parent
1da374af2f
commit
469c06c30e
@ -11897,6 +11897,16 @@ tcp-request connection <action> [{if | unless} <condition>]
|
||||
expected result is a boolean. If an error occurs, this action silently
|
||||
fails and the actions evaluation continues.
|
||||
|
||||
- set-mark <mark>:
|
||||
Is used to set the Netfilter MARK in all packets sent to the client to
|
||||
the value passed in <mark> on platforms which support it. This value is
|
||||
an unsigned 32 bit value which can be matched by netfilter and by the
|
||||
routing table. It can be expressed both in decimal or hexadecimal format
|
||||
(prefixed by "0x"). This can be useful to force certain packets to take a
|
||||
different route (for example a cheaper network path for bulk
|
||||
downloads). This works on Linux kernels 2.6.32 and above and requires
|
||||
admin privileges.
|
||||
|
||||
- set-src <expr> :
|
||||
Is used to set the source IP address to the value of specified
|
||||
expression. Useful if you want to mask source IP for privacy.
|
||||
@ -11963,6 +11973,17 @@ tcp-request connection <action> [{if | unless} <condition>]
|
||||
long as the address family supports a port, otherwise it forces the
|
||||
destination address to IPv4 "0.0.0.0" before rewriting the port.
|
||||
|
||||
- set-tos <tos>:
|
||||
Is used to set the TOS or DSCP field value of packets sent to the client
|
||||
to the value passed in <tos> on platforms which support this. This value
|
||||
represents the whole 8 bits of the IP TOS field, and can be expressed
|
||||
both in decimal or hexadecimal format (prefixed by "0x"). Note that only
|
||||
the 6 higher bits are used in DSCP or TOS, and the two lower bits are
|
||||
always 0. This can be used to adjust some routing behavior on border
|
||||
routers based on some information from the request.
|
||||
|
||||
See RFC 2474, 2597, 3260 and 4594 for more information.
|
||||
|
||||
- "silent-drop" :
|
||||
This stops the evaluation of the rules and makes the client-facing
|
||||
connection suddenly disappear using a system-dependent way that tries
|
||||
@ -12057,9 +12078,11 @@ tcp-request content <action> [{if | unless} <condition>]
|
||||
- set-dst <expr>
|
||||
- set-dst-port <expr>
|
||||
- set-log-level <level>
|
||||
- set-mark <mark>
|
||||
- set-nice <nice>
|
||||
- set-src <expr>
|
||||
- set-src-port <expr>
|
||||
- set-tos <tos>
|
||||
- set-var(<var-name>) <expr>
|
||||
- switch-mode http [ proto <name> ]
|
||||
- unset-var(<var-name>)
|
||||
@ -12113,12 +12136,18 @@ tcp-request content <action> [{if | unless} <condition>]
|
||||
The "set-log-level" is used to set the log level of the current session. More
|
||||
information on how to use it at "http-request set-log-level".
|
||||
|
||||
The "set-mark" is used to set the Netfilter MARK in all packets sent to the
|
||||
client. More information on how to use it at "http-request set-mark".
|
||||
|
||||
The "set-nice" is used to set the "nice" factor of the current session. More
|
||||
information on how to use it at "http-request set-nice".
|
||||
|
||||
The "set-src" and "set-src-port" are used to set respectively the source IP
|
||||
and port. More information on how to use it at "http-request set-src".
|
||||
|
||||
The "set-tos" is used to set the TOS or DSCP field value of packets sent to
|
||||
the client. More information on how to use it at "http-request set-tos".
|
||||
|
||||
The "set-var" is used to set the content of a variable. The variable is
|
||||
declared inline. For "tcp-request session" rules, only session-level
|
||||
variables can be used, without any layer7 contents.
|
||||
@ -12363,11 +12392,21 @@ tcp-response content <action> [{if | unless} <condition>]
|
||||
session. More information on how to use it at "http-response
|
||||
set-log-level".
|
||||
|
||||
- set-mark <mark>
|
||||
The "set-mark" is used to set the Netfilter MARK in all packets sent to
|
||||
the client. More information on how to use it at "http-response
|
||||
set-mark".
|
||||
|
||||
- set-nice <nice>
|
||||
The "set-nice" is used to set the "nice" factor of the current
|
||||
session. More information on how to use it at "http-response
|
||||
set-nice".
|
||||
|
||||
- set-tos <tos>
|
||||
The "set-tos" is used to set the TOS or DSCP field value of packets
|
||||
sent to the client. More information on how to use it at "http-response
|
||||
set-tos".
|
||||
|
||||
- set-var(<var-name>) <expr>
|
||||
Sets a variable.
|
||||
|
||||
@ -12510,10 +12549,12 @@ tcp-request session <action> [{if | unless} <condition>]
|
||||
- sc-inc-gpc0(<sc-id>)
|
||||
- sc-inc-gpc1(<sc-id>)
|
||||
- sc-set-gpt0(<sc-id>) { <int> | <expr> }
|
||||
- set-mark <mark>
|
||||
- set-dst <expr>
|
||||
- set-dst-port <expr>
|
||||
- set-src <expr>
|
||||
- set-src-port <expr>
|
||||
- set-tos <tos>
|
||||
- set-var(<var-name>) <expr>
|
||||
- unset-var(<var-name>)
|
||||
- silent-drop
|
||||
|
@ -81,8 +81,6 @@ enum act_name {
|
||||
|
||||
/* common http actions .*/
|
||||
ACT_HTTP_REDIR,
|
||||
ACT_HTTP_SET_TOS,
|
||||
ACT_HTTP_SET_MARK,
|
||||
|
||||
/* http request actions. */
|
||||
ACT_HTTP_REQ_TARPIT,
|
||||
|
@ -1315,71 +1315,6 @@ static enum act_parse_ret parse_http_auth(const char **args, int *orig_arg, stru
|
||||
return ACT_RET_PRS_OK;
|
||||
}
|
||||
|
||||
/* Parse a "set-tos" action. It takes the TOS value as argument. It returns
|
||||
* ACT_RET_PRS_OK on success, ACT_RET_PRS_ERR on error.
|
||||
*/
|
||||
static enum act_parse_ret parse_http_set_tos(const char **args, int *orig_arg, struct proxy *px,
|
||||
struct act_rule *rule, char **err)
|
||||
{
|
||||
#ifdef IP_TOS
|
||||
char *endp;
|
||||
int cur_arg;
|
||||
|
||||
rule->action = ACT_HTTP_SET_TOS;
|
||||
|
||||
cur_arg = *orig_arg;
|
||||
if (!*args[cur_arg]) {
|
||||
memprintf(err, "expects exactly 1 argument (integer/hex value)");
|
||||
return ACT_RET_PRS_ERR;
|
||||
}
|
||||
rule->arg.http.i = strtol(args[cur_arg], &endp, 0);
|
||||
if (endp && *endp != '\0') {
|
||||
memprintf(err, "invalid character starting at '%s' (integer/hex value expected)", endp);
|
||||
return ACT_RET_PRS_ERR;
|
||||
}
|
||||
|
||||
LIST_INIT(&rule->arg.http.fmt);
|
||||
*orig_arg = cur_arg + 1;
|
||||
return ACT_RET_PRS_OK;
|
||||
#else
|
||||
memprintf(err, "not supported on this platform (IP_TOS undefined)");
|
||||
return ACT_RET_PRS_ERR;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Parse a "set-mark" action. It takes the MARK value as argument. It returns
|
||||
* ACT_RET_PRS_OK on success, ACT_RET_PRS_ERR on error.
|
||||
*/
|
||||
static enum act_parse_ret parse_http_set_mark(const char **args, int *orig_arg, struct proxy *px,
|
||||
struct act_rule *rule, char **err)
|
||||
{
|
||||
#ifdef SO_MARK
|
||||
char *endp;
|
||||
int cur_arg;
|
||||
|
||||
rule->action = ACT_HTTP_SET_MARK;
|
||||
|
||||
cur_arg = *orig_arg;
|
||||
if (!*args[cur_arg]) {
|
||||
memprintf(err, "expects exactly 1 argument (integer/hex value)");
|
||||
return ACT_RET_PRS_ERR;
|
||||
}
|
||||
rule->arg.http.i = strtoul(args[cur_arg], &endp, 0);
|
||||
if (endp && *endp != '\0') {
|
||||
memprintf(err, "invalid character starting at '%s' (integer/hex value expected)", endp);
|
||||
return ACT_RET_PRS_ERR;
|
||||
}
|
||||
|
||||
LIST_INIT(&rule->arg.http.fmt);
|
||||
*orig_arg = cur_arg + 1;
|
||||
global.last_checks |= LSTCHK_NETADM;
|
||||
return ACT_RET_PRS_OK;
|
||||
#else
|
||||
memprintf(err, "not supported on this platform (SO_MARK undefined)");
|
||||
return ACT_RET_PRS_ERR;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This function executes a early-hint action. It adds an HTTP Early Hint HTTP
|
||||
* 103 response header with <.arg.http.str> name and with a value built
|
||||
* according to <.arg.http.fmt> log line format. If it is the first early-hint
|
||||
@ -2458,11 +2393,9 @@ static struct action_kw_list http_req_actions = {
|
||||
{ "set-header", parse_http_set_header, 0 },
|
||||
{ "set-map", parse_http_set_map, KWF_MATCH_PREFIX },
|
||||
{ "set-method", parse_set_req_line, 0 },
|
||||
{ "set-mark", parse_http_set_mark, 0 },
|
||||
{ "set-path", parse_set_req_line, 0 },
|
||||
{ "set-pathq", parse_set_req_line, 0 },
|
||||
{ "set-query", parse_set_req_line, 0 },
|
||||
{ "set-tos", parse_http_set_tos, 0 },
|
||||
{ "set-uri", parse_set_req_line, 0 },
|
||||
{ "strict-mode", parse_http_strict_mode, 0 },
|
||||
{ "tarpit", parse_http_deny, 0 },
|
||||
@ -2491,9 +2424,7 @@ static struct action_kw_list http_res_actions = {
|
||||
{ "return", parse_http_return, 0 },
|
||||
{ "set-header", parse_http_set_header, 0 },
|
||||
{ "set-map", parse_http_set_map, KWF_MATCH_PREFIX },
|
||||
{ "set-mark", parse_http_set_mark, 0 },
|
||||
{ "set-status", parse_http_set_status, 0 },
|
||||
{ "set-tos", parse_http_set_tos, 0 },
|
||||
{ "strict-mode", parse_http_strict_mode, 0 },
|
||||
{ "track-sc", parse_http_track_sc, KWF_MATCH_PREFIX },
|
||||
{ "wait-for-body", parse_http_wait_for_body, 0 },
|
||||
|
@ -2831,14 +2831,6 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
|
||||
rule_ret = HTTP_RULE_RES_ERROR;
|
||||
goto end;
|
||||
|
||||
case ACT_HTTP_SET_TOS:
|
||||
conn_set_tos(objt_conn(sess->origin), rule->arg.http.i);
|
||||
break;
|
||||
|
||||
case ACT_HTTP_SET_MARK:
|
||||
conn_set_mark(objt_conn(sess->origin), rule->arg.http.i);
|
||||
break;
|
||||
|
||||
/* other flags exists, but normally, they never be matched. */
|
||||
default:
|
||||
break;
|
||||
@ -2958,14 +2950,6 @@ resume_execution:
|
||||
rule_ret = HTTP_RULE_RES_DENY;
|
||||
goto end;
|
||||
|
||||
case ACT_HTTP_SET_TOS:
|
||||
conn_set_tos(objt_conn(sess->origin), rule->arg.http.i);
|
||||
break;
|
||||
|
||||
case ACT_HTTP_SET_MARK:
|
||||
conn_set_mark(objt_conn(sess->origin), rule->arg.http.i);
|
||||
break;
|
||||
|
||||
case ACT_HTTP_REDIR:
|
||||
rule_ret = HTTP_RULE_RES_ABRT;
|
||||
if (!http_apply_redirect_rule(rule->arg.redir, s, txn))
|
||||
|
@ -236,6 +236,22 @@ static enum act_return tcp_exec_action_silent_drop(struct act_rule *rule, struct
|
||||
return ACT_RET_ABRT;
|
||||
}
|
||||
|
||||
|
||||
static enum act_return tcp_action_set_mark(struct act_rule *rule, struct proxy *px,
|
||||
struct session *sess, struct stream *s, int flags)
|
||||
{
|
||||
conn_set_mark(objt_conn(sess->origin), (uintptr_t)rule->arg.act.p[0]);
|
||||
return ACT_RET_CONT;
|
||||
}
|
||||
|
||||
static enum act_return tcp_action_set_tos(struct act_rule *rule, struct proxy *px,
|
||||
struct session *sess, struct stream *s, int flags)
|
||||
{
|
||||
conn_set_tos(objt_conn(sess->origin), (uintptr_t)rule->arg.act.p[0]);
|
||||
return ACT_RET_CONT;
|
||||
}
|
||||
|
||||
|
||||
/* parse "set-{src,dst}[-port]" action */
|
||||
static enum act_parse_ret tcp_parse_set_src_dst(const char **args, int *orig_arg, struct proxy *px,
|
||||
struct act_rule *rule, char **err)
|
||||
@ -283,6 +299,75 @@ static enum act_parse_ret tcp_parse_set_src_dst(const char **args, int *orig_arg
|
||||
}
|
||||
|
||||
|
||||
/* Parse a "set-mark" action. It takes the MARK value as argument. It returns
|
||||
* ACT_RET_PRS_OK on success, ACT_RET_PRS_ERR on error.
|
||||
*/
|
||||
static enum act_parse_ret tcp_parse_set_mark(const char **args, int *cur_arg, struct proxy *px,
|
||||
struct act_rule *rule, char **err)
|
||||
{
|
||||
#ifdef SO_MARK
|
||||
char *endp;
|
||||
unsigned int mark;
|
||||
|
||||
if (!*args[*cur_arg]) {
|
||||
memprintf(err, "expects exactly 1 argument (integer/hex value)");
|
||||
return ACT_RET_PRS_ERR;
|
||||
}
|
||||
mark = strtoul(args[*cur_arg], &endp, 0);
|
||||
if (endp && *endp != '\0') {
|
||||
memprintf(err, "invalid character starting at '%s' (integer/hex value expected)", endp);
|
||||
return ACT_RET_PRS_ERR;
|
||||
}
|
||||
|
||||
(*cur_arg)++;
|
||||
|
||||
/* Register processing function. */
|
||||
rule->action_ptr = tcp_action_set_mark;
|
||||
rule->action = ACT_CUSTOM;
|
||||
rule->arg.act.p[0] = (void *)(uintptr_t)mark;
|
||||
global.last_checks |= LSTCHK_NETADM;
|
||||
return ACT_RET_PRS_OK;
|
||||
#else
|
||||
memprintf(err, "not supported on this platform (SO_MARK undefined)");
|
||||
return ACT_RET_PRS_ERR;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Parse a "set-tos" action. It takes the TOS value as argument. It returns
|
||||
* ACT_RET_PRS_OK on success, ACT_RET_PRS_ERR on error.
|
||||
*/
|
||||
static enum act_parse_ret tcp_parse_set_tos(const char **args, int *cur_arg, struct proxy *px,
|
||||
struct act_rule *rule, char **err)
|
||||
{
|
||||
#ifdef IP_TOS
|
||||
char *endp;
|
||||
int tos;
|
||||
|
||||
if (!*args[*cur_arg]) {
|
||||
memprintf(err, "expects exactly 1 argument (integer/hex value)");
|
||||
return ACT_RET_PRS_ERR;
|
||||
}
|
||||
tos = strtol(args[*cur_arg], &endp, 0);
|
||||
if (endp && *endp != '\0') {
|
||||
memprintf(err, "invalid character starting at '%s' (integer/hex value expected)", endp);
|
||||
return ACT_RET_PRS_ERR;
|
||||
}
|
||||
|
||||
(*cur_arg)++;
|
||||
|
||||
/* Register processing function. */
|
||||
rule->action_ptr = tcp_action_set_tos;
|
||||
rule->action = ACT_CUSTOM;
|
||||
rule->arg.act.p[0] = (void *)(uintptr_t)tos;
|
||||
return ACT_RET_PRS_OK;
|
||||
#else
|
||||
memprintf(err, "not supported on this platform (IP_TOS undefined)");
|
||||
return ACT_RET_PRS_ERR;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Parse a "silent-drop" action. It takes no argument. It returns ACT_RET_PRS_OK on
|
||||
* success, ACT_RET_PRS_ERR on error.
|
||||
*/
|
||||
@ -296,10 +381,12 @@ static enum act_parse_ret tcp_parse_silent_drop(const char **args, int *orig_arg
|
||||
|
||||
|
||||
static struct action_kw_list tcp_req_conn_actions = {ILH, {
|
||||
{ "set-mark", tcp_parse_set_mark },
|
||||
{ "set-src", tcp_parse_set_src_dst },
|
||||
{ "set-src-port", tcp_parse_set_src_dst },
|
||||
{ "set-dst" , tcp_parse_set_src_dst },
|
||||
{ "set-dst-port", tcp_parse_set_src_dst },
|
||||
{ "set-tos", tcp_parse_set_tos },
|
||||
{ "silent-drop", tcp_parse_silent_drop },
|
||||
{ /* END */ }
|
||||
}};
|
||||
@ -307,10 +394,12 @@ static struct action_kw_list tcp_req_conn_actions = {ILH, {
|
||||
INITCALL1(STG_REGISTER, tcp_req_conn_keywords_register, &tcp_req_conn_actions);
|
||||
|
||||
static struct action_kw_list tcp_req_sess_actions = {ILH, {
|
||||
{ "set-mark", tcp_parse_set_mark },
|
||||
{ "set-src", tcp_parse_set_src_dst },
|
||||
{ "set-src-port", tcp_parse_set_src_dst },
|
||||
{ "set-dst" , tcp_parse_set_src_dst },
|
||||
{ "set-dst-port", tcp_parse_set_src_dst },
|
||||
{ "set-tos", tcp_parse_set_tos },
|
||||
{ "silent-drop", tcp_parse_silent_drop },
|
||||
{ /* END */ }
|
||||
}};
|
||||
@ -318,10 +407,12 @@ static struct action_kw_list tcp_req_sess_actions = {ILH, {
|
||||
INITCALL1(STG_REGISTER, tcp_req_sess_keywords_register, &tcp_req_sess_actions);
|
||||
|
||||
static struct action_kw_list tcp_req_cont_actions = {ILH, {
|
||||
{ "set-mark", tcp_parse_set_mark },
|
||||
{ "set-src", tcp_parse_set_src_dst },
|
||||
{ "set-src-port", tcp_parse_set_src_dst },
|
||||
{ "set-dst" , tcp_parse_set_src_dst },
|
||||
{ "set-dst-port", tcp_parse_set_src_dst },
|
||||
{ "set-tos", tcp_parse_set_tos },
|
||||
{ "silent-drop", tcp_parse_silent_drop },
|
||||
{ /* END */ }
|
||||
}};
|
||||
@ -329,6 +420,8 @@ static struct action_kw_list tcp_req_cont_actions = {ILH, {
|
||||
INITCALL1(STG_REGISTER, tcp_req_cont_keywords_register, &tcp_req_cont_actions);
|
||||
|
||||
static struct action_kw_list tcp_res_cont_actions = {ILH, {
|
||||
{ "set-mark", tcp_parse_set_mark },
|
||||
{ "set-tos", tcp_parse_set_tos },
|
||||
{ "silent-drop", tcp_parse_silent_drop },
|
||||
{ /* END */ }
|
||||
}};
|
||||
@ -336,17 +429,21 @@ static struct action_kw_list tcp_res_cont_actions = {ILH, {
|
||||
INITCALL1(STG_REGISTER, tcp_res_cont_keywords_register, &tcp_res_cont_actions);
|
||||
|
||||
static struct action_kw_list http_req_actions = {ILH, {
|
||||
{ "set-mark", tcp_parse_set_mark },
|
||||
{ "silent-drop", tcp_parse_silent_drop },
|
||||
{ "set-src", tcp_parse_set_src_dst },
|
||||
{ "set-src-port", tcp_parse_set_src_dst },
|
||||
{ "set-dst", tcp_parse_set_src_dst },
|
||||
{ "set-dst-port", tcp_parse_set_src_dst },
|
||||
{ "set-tos", tcp_parse_set_tos },
|
||||
{ /* END */ }
|
||||
}};
|
||||
|
||||
INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
|
||||
|
||||
static struct action_kw_list http_res_actions = {ILH, {
|
||||
{ "set-mark", tcp_parse_set_mark },
|
||||
{ "set-tos", tcp_parse_set_tos },
|
||||
{ "silent-drop", tcp_parse_silent_drop },
|
||||
{ /* END */ }
|
||||
}};
|
||||
|
Loading…
Reference in New Issue
Block a user