mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-07 15:47:01 +02:00
MEDIUM: tcp: add 'set-src' to 'tcp-request connection'
The 'set-src' action was not available for tcp actions The action code has been converted into a function in proto_tcp.c to be used for both 'http-request' and 'tcp-request connection' actions. Both http and tcp keywords are registered in proto_tcp.c
This commit is contained in:
parent
bb933468b4
commit
2e785f23cb
@ -8674,6 +8674,21 @@ tcp-request connection <action> [{if | unless} <condition>]
|
||||
an error occurs, this action silently fails and the actions evaluation
|
||||
continues.
|
||||
|
||||
- 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.
|
||||
If you want to provide an IP from a HTTP header use "http-request
|
||||
set-src"
|
||||
|
||||
<expr> Is a standard HAProxy expression formed by a sample-fetch
|
||||
followed by some converters.
|
||||
|
||||
Example:
|
||||
|
||||
tcp-request connection set-src src,ipmask(24)
|
||||
|
||||
When set-src is successful, the source port is set to 0.
|
||||
|
||||
- "silent-drop" :
|
||||
This stops the evaluation of the rules and makes the client-facing
|
||||
connection suddenly disappear using a system-dependant way that tries
|
||||
|
@ -80,7 +80,6 @@ enum act_name {
|
||||
/* http request actions. */
|
||||
ACT_HTTP_REQ_TARPIT,
|
||||
ACT_HTTP_REQ_AUTH,
|
||||
ACT_HTTP_REQ_SET_SRC,
|
||||
|
||||
/* tcp actions */
|
||||
ACT_TCP_EXPECT_PX,
|
||||
|
@ -3554,26 +3554,6 @@ http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct stream
|
||||
}
|
||||
break;
|
||||
|
||||
case ACT_HTTP_REQ_SET_SRC:
|
||||
if ((cli_conn = objt_conn(sess->origin)) && conn_ctrl_ready(cli_conn)) {
|
||||
struct sample *smp;
|
||||
|
||||
smp = sample_fetch_as_type(px, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->arg.expr, SMP_T_ADDR);
|
||||
|
||||
if (smp) {
|
||||
if (smp->data.type == SMP_T_IPV4) {
|
||||
((struct sockaddr_in *)&cli_conn->addr.from)->sin_family = AF_INET;
|
||||
((struct sockaddr_in *)&cli_conn->addr.from)->sin_addr.s_addr = smp->data.u.ipv4.s_addr;
|
||||
((struct sockaddr_in *)&cli_conn->addr.from)->sin_port = 0;
|
||||
} else if (smp->data.type == SMP_T_IPV6) {
|
||||
((struct sockaddr_in6 *)&cli_conn->addr.from)->sin6_family = AF_INET6;
|
||||
memcpy(&((struct sockaddr_in6 *)&cli_conn->addr.from)->sin6_addr, &smp->data.u.ipv6, sizeof(struct in6_addr));
|
||||
((struct sockaddr_in6 *)&cli_conn->addr.from)->sin6_port = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* other flags exists, but normaly, they never be matched. */
|
||||
default:
|
||||
break;
|
||||
@ -9204,39 +9184,6 @@ struct act_rule *parse_http_req_cond(const char **args, const char *file, int li
|
||||
proxy->conf.lfs_line = proxy->conf.args.line;
|
||||
|
||||
cur_arg += 2;
|
||||
} else if (strncmp(args[0], "set-src", 7) == 0) {
|
||||
struct sample_expr *expr;
|
||||
unsigned int where;
|
||||
char *err = NULL;
|
||||
|
||||
cur_arg = 1;
|
||||
proxy->conf.args.ctx = ARGC_HRQ;
|
||||
|
||||
expr = sample_parse_expr((char **)args, &cur_arg, file, linenum, &err, &proxy->conf.args);
|
||||
if (!expr) {
|
||||
Alert("parsing [%s:%d] : error detected in %s '%s' while parsing 'http-request %s' rule : %s.\n",
|
||||
file, linenum, proxy_type_str(proxy), proxy->id, args[0], err);
|
||||
free(err);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
where = 0;
|
||||
if (proxy->cap & PR_CAP_FE)
|
||||
where |= SMP_VAL_FE_HRQ_HDR;
|
||||
if (proxy->cap & PR_CAP_BE)
|
||||
where |= SMP_VAL_BE_HRQ_HDR;
|
||||
|
||||
if (!(expr->fetch->val & where)) {
|
||||
Alert("parsing [%s:%d] : error detected in %s '%s' while parsing 'http-request %s' rule :"
|
||||
" fetch method '%s' extracts information from '%s', none of which is available here.\n",
|
||||
file, linenum, proxy_type_str(proxy), proxy->id, args[0],
|
||||
args[cur_arg-1], sample_src_names(expr->fetch->use));
|
||||
free(expr);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
rule->arg.expr = expr;
|
||||
rule->action = ACT_HTTP_REQ_SET_SRC;
|
||||
} else if (((custom = action_http_req_custom(args[0])) != NULL)) {
|
||||
char *errmsg = NULL;
|
||||
cur_arg = 1;
|
||||
@ -9253,8 +9200,8 @@ struct act_rule *parse_http_req_cond(const char **args, const char *file, int li
|
||||
action_build_list(&http_req_keywords.list, &trash);
|
||||
Alert("parsing [%s:%d]: 'http-request' expects 'allow', 'deny', 'auth', 'redirect', "
|
||||
"'tarpit', 'add-header', 'set-header', 'replace-header', 'replace-value', 'set-nice', "
|
||||
"'set-tos', 'set-mark', 'set-log-level', 'add-acl', 'del-acl', 'del-map', 'set-map', "
|
||||
"'set-src'%s%s, but got '%s'%s.\n",
|
||||
"'set-tos', 'set-mark', 'set-log-level', 'add-acl', 'del-acl', 'del-map', 'set-map'"
|
||||
"%s%s, but got '%s'%s.\n",
|
||||
file, linenum, *trash.str ? ", " : "", trash.str, args[0], *args[0] ? "" : " (missing argument)");
|
||||
goto out_err;
|
||||
}
|
||||
@ -9614,8 +9561,8 @@ struct act_rule *parse_http_res_cond(const char **args, const char *file, int li
|
||||
action_build_list(&http_res_keywords.list, &trash);
|
||||
Alert("parsing [%s:%d]: 'http-response' expects 'allow', 'deny', 'redirect', "
|
||||
"'add-header', 'del-header', 'set-header', 'replace-header', 'replace-value', 'set-nice', "
|
||||
"'set-tos', 'set-mark', 'set-log-level', 'add-acl', 'del-acl', 'del-map', 'set-map', "
|
||||
"'set-src'%s%s, but got '%s'%s.\n",
|
||||
"'set-tos', 'set-mark', 'set-log-level', 'add-acl', 'del-acl', 'del-map', 'set-map'"
|
||||
"%s%s, but got '%s'%s.\n",
|
||||
file, linenum, *trash.str ? ", " : "", trash.str, args[0], *args[0] ? "" : " (missing argument)");
|
||||
goto out_err;
|
||||
}
|
||||
|
@ -1425,6 +1425,33 @@ int tcp_exec_req_rules(struct session *sess)
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute the "set-src" action. May be called from {tcp,http}request
|
||||
*/
|
||||
enum act_return tcp_action_req_set_src(struct act_rule *rule, struct proxy *px,
|
||||
struct session *sess, struct stream *s, int flags)
|
||||
{
|
||||
struct connection *cli_conn;
|
||||
|
||||
if ((cli_conn = objt_conn(sess->origin)) && conn_ctrl_ready(cli_conn)) {
|
||||
struct sample *smp;
|
||||
|
||||
smp = sample_fetch_as_type(px, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->arg.expr, SMP_T_ADDR);
|
||||
if (smp) {
|
||||
if (smp->data.type == SMP_T_IPV4) {
|
||||
((struct sockaddr_in *)&cli_conn->addr.from)->sin_family = AF_INET;
|
||||
((struct sockaddr_in *)&cli_conn->addr.from)->sin_addr.s_addr = smp->data.u.ipv4.s_addr;
|
||||
((struct sockaddr_in *)&cli_conn->addr.from)->sin_port = 0;
|
||||
} else if (smp->data.type == SMP_T_IPV6) {
|
||||
((struct sockaddr_in6 *)&cli_conn->addr.from)->sin6_family = AF_INET6;
|
||||
memcpy(&((struct sockaddr_in6 *)&cli_conn->addr.from)->sin6_addr, &smp->data.u.ipv6, sizeof(struct in6_addr));
|
||||
((struct sockaddr_in6 *)&cli_conn->addr.from)->sin6_port = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ACT_RET_CONT;
|
||||
}
|
||||
|
||||
/* Executes the "silent-drop" action. May be called from {tcp,http}{request,response} */
|
||||
static enum act_return tcp_exec_action_silent_drop(struct act_rule *rule, struct proxy *px, struct session *sess, struct stream *strm, int flags)
|
||||
{
|
||||
@ -2033,6 +2060,46 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* parse "set-src" action */
|
||||
enum act_parse_ret tcp_parse_set_src(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
|
||||
{
|
||||
int cur_arg;
|
||||
struct sample_expr *expr;
|
||||
unsigned int where;
|
||||
|
||||
cur_arg = *orig_arg;
|
||||
expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args);
|
||||
if (!expr)
|
||||
return ACT_RET_PRS_ERR;
|
||||
|
||||
where = 0;
|
||||
if (proxy->cap & PR_CAP_FE)
|
||||
where |= SMP_VAL_FE_HRQ_HDR;
|
||||
if (proxy->cap & PR_CAP_BE)
|
||||
where |= SMP_VAL_BE_HRQ_HDR;
|
||||
|
||||
if (!(expr->fetch->val & where)) {
|
||||
memprintf(err,
|
||||
"fetch method '%s' extracts information from '%s', none of which is available here",
|
||||
args[cur_arg-1], sample_src_names(expr->fetch->use));
|
||||
free(expr);
|
||||
return ACT_RET_PRS_ERR;
|
||||
}
|
||||
rule->arg.expr = expr;
|
||||
rule->action = ACT_CUSTOM;
|
||||
|
||||
if (!strcmp(args[*orig_arg-1], "set-src")) {
|
||||
rule->action_ptr = tcp_action_req_set_src;
|
||||
} else {
|
||||
return ACT_RET_PRS_ERR;
|
||||
}
|
||||
|
||||
(*orig_arg)++;
|
||||
|
||||
return ACT_RET_PRS_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Parse a "silent-drop" action. It takes no argument. It returns ACT_RET_PRS_OK on
|
||||
* success, ACT_RET_PRS_ERR on error.
|
||||
*/
|
||||
@ -2423,7 +2490,8 @@ static struct srv_kw_list srv_kws = { "TCP", { }, {
|
||||
}};
|
||||
|
||||
static struct action_kw_list tcp_req_conn_actions = {ILH, {
|
||||
{ "silent-drop", tcp_parse_silent_drop },
|
||||
{ "silent-drop", tcp_parse_silent_drop },
|
||||
{ "set-src", tcp_parse_set_src },
|
||||
{ /* END */ }
|
||||
}};
|
||||
|
||||
@ -2438,7 +2506,8 @@ static struct action_kw_list tcp_res_cont_actions = {ILH, {
|
||||
}};
|
||||
|
||||
static struct action_kw_list http_req_actions = {ILH, {
|
||||
{ "silent-drop", tcp_parse_silent_drop },
|
||||
{ "silent-drop", tcp_parse_silent_drop },
|
||||
{ "set-src", tcp_parse_set_src },
|
||||
{ /* END */ }
|
||||
}};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user