]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: tcp: add 'set-src' to 'tcp-request connection'
authorWilliam Lallemand <wlallemand@irq6.net>
Tue, 24 May 2016 23:48:42 +0000 (01:48 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 1 Jun 2016 09:44:11 +0000 (11:44 +0200)
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

doc/configuration.txt
include/types/action.h
src/proto_http.c
src/proto_tcp.c

index c4df56eef6c836f2bfd88e913ebdb353c7776bcc..f94885f2c23513583566224b4642abbe2cdfbb36 100644 (file)
@@ -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
index b97f9bf9a4588e95e79dec187dd903ea21f84d55..742252e1096540b37b20a2ececb340c51d85fb72 100644 (file)
@@ -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,
index d79a7821936863abb34c7d402284cb7754e8b881..668663179cf23c8ffcb7742880038857cccea52d 100644 (file)
@@ -3554,26 +3554,6 @@ resume_execution:
                        }
                        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;
        }
index bbe12e2d4c0d9eaa1db9e67b0b789e52fb815cae..b283db4fe4cf20d1cfc2567b56ee2d89c06d1602 100644 (file)
@@ -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 */ }
 }};