On Sun, Jan 03, 2021 at 11:40:42AM +0100, Denis Fondras wrote: > Le Fri, Dec 11, 2020 at 10:53:56AM +0000, Olivier Cherrier a écrit : > > > > Hello tech@, > > > > Is there any interest for this feature to be commited? > > I find it very useful. Thank you Denis! > > > > Here is an up to date diff, looking for OKs. >
Hi Denis, I like this feature. For example it would be useful for using relayd as a reverse-proxy to forward it to an internal network running a httpd with some service. Then the path can be stripped without having to touch this service configuration. Like: https://example.com/myservice/ -> http://192.168.0.2/ . I've noticed a small thing while testing the patch. When the path is "/" and "strip 1" is used it becomes "", the request becomes: "GET HTTP/1.0". Maybe this should be instead: "/". The same thing happens with a "strip number" higher than the amount of sub paths. It could be worked-around by prefiltering with a match rule, but maybe it is more obvious to make the root "/" ? The way the function server_root_strip() is used by OpenBSD httpd is that it first does a filesystem path check/open(2). My test config: Command: printf 'GET / HTTP/1.0\r\nConnection: Close\r\nHost: 127.0.0.1\r\n\r\n' | \ nc -v 127.0.0.1 80 relayd.conf: table <service> { 127.0.0.1 } table <service2> { 127.0.0.1 } http protocol "t" { tcp { nodelay } return error match tag "notag" match path strip 1 tag "ok" block tagged "notag" } relay "r" { listen on "127.0.0.1" port 80 protocol "t" forward to <service> port 8080 } Netcat (fake server): nc -k -v -l 127.0.0.1 8080 The incoming request is then: Connection received on localhost 45510 GET HTTP/1.0 Connection: Close Host: 127.0.0.1 I made no changes to the diff below. > Index: parse.y > =================================================================== > RCS file: /cvs/src/usr.sbin/relayd/parse.y,v > retrieving revision 1.250 > diff -u -p -r1.250 parse.y > --- parse.y 29 Dec 2020 19:48:06 -0000 1.250 > +++ parse.y 3 Jan 2021 10:38:26 -0000 > @@ -175,7 +175,7 @@ typedef struct { > %token LOOKUP METHOD MODE NAT NO DESTINATION NODELAY NOTHING ON PARENT > PATH > %token PFTAG PORT PREFORK PRIORITY PROTO QUERYSTR REAL REDIRECT RELAY > REMOVE > %token REQUEST RESPONSE RETRY QUICK RETURN ROUNDROBIN ROUTE SACK > SCRIPT SEND > -%token SESSION SOCKET SPLICE SSL STICKYADDR STYLE TABLE TAG TAGGED TCP > +%token SESSION SOCKET SPLICE SSL STICKYADDR STRIP STYLE TABLE TAG > TAGGED TCP > %token TIMEOUT TLS TO ROUTER RTLABEL TRANSPARENT URL WITH TTL RTABLE > %token MATCH PARAMS RANDOM LEASTSTATES SRCHASH KEY CERTIFICATE > PASSWORD ECDHE > %token EDH TICKETS CONNECTION CONNECTIONS CONTEXT ERRORS STATE CHANGES > CHECKS > @@ -1549,6 +1549,20 @@ ruleopts : METHOD STRING > { > rule->rule_kv[keytype].kv_option = $2; > rule->rule_kv[keytype].kv_type = keytype; > } > + | PATH STRIP NUMBER { > + char *strip = NULL; > + > + if ($3 < 0 || $3 > INT_MAX) { > + yyerror("invalid strip number"); > + YYERROR; > + } > + if (asprintf(&strip, "%lld", $3) <= 0) > + fatal("can't parse strip"); > + keytype = KEY_TYPE_PATH; > + rule->rule_kv[keytype].kv_option = KEY_OPTION_STRIP; > + rule->rule_kv[keytype].kv_value = strip; > + rule->rule_kv[keytype].kv_type = keytype; > + } > | QUERYSTR key_option STRING value { > switch ($2) { > case KEY_OPTION_APPEND: > @@ -2481,6 +2495,7 @@ lookup(char *s) > { "ssl", SSL }, > { "state", STATE }, > { "sticky-address", STICKYADDR }, > + { "strip", STRIP }, > { "style", STYLE }, > { "table", TABLE }, > { "tag", TAG }, > Index: relay.c > =================================================================== > RCS file: /cvs/src/usr.sbin/relayd/relay.c,v > retrieving revision 1.251 > diff -u -p -r1.251 relay.c > --- relay.c 14 May 2020 17:27:38 -0000 1.251 > +++ relay.c 3 Jan 2021 10:38:27 -0000 > @@ -214,6 +214,9 @@ relay_ruledebug(struct relay_rule *rule) > case KEY_OPTION_LOG: > fprintf(stderr, "log "); > break; > + case KEY_OPTION_STRIP: > + fprintf(stderr, "strip "); > + break; > case KEY_OPTION_NONE: > break; > } > @@ -227,13 +230,15 @@ relay_ruledebug(struct relay_rule *rule) > break; > } > > + int kvv = (kv->kv_option == KEY_OPTION_STRIP || > + kv->kv_value == NULL); > fprintf(stderr, "%s%s%s%s%s%s ", > kv->kv_key == NULL ? "" : "\"", > kv->kv_key == NULL ? "" : kv->kv_key, > kv->kv_key == NULL ? "" : "\"", > - kv->kv_value == NULL ? "" : " value \"", > + kvv ? "" : " value \"", > kv->kv_value == NULL ? "" : kv->kv_value, > - kv->kv_value == NULL ? "" : "\""); > + kvv ? "" : "\""); > } > > if (rule->rule_tablename[0]) > Index: relay_http.c > =================================================================== > RCS file: /cvs/src/usr.sbin/relayd/relay_http.c,v > retrieving revision 1.79 > diff -u -p -r1.79 relay_http.c > --- relay_http.c 4 Sep 2020 13:09:14 -0000 1.79 > +++ relay_http.c 3 Jan 2021 10:38:27 -0000 > @@ -77,6 +77,7 @@ int relay_match_actions(struct ctl_rel > struct relay_rule *, struct kvlist *, struct kvlist *, > struct relay_table **); > void relay_httpdesc_free(struct http_descriptor *); > +char * server_root_strip(char *, int); > > static struct relayd *env = NULL; > > @@ -1421,14 +1422,16 @@ relay_httppath_test(struct ctl_relay_eve > > if (cre->dir == RELAY_DIR_RESPONSE || kv->kv_type != KEY_TYPE_PATH) > return (0); > - else if (kv->kv_key == NULL) > - return (0); > - else if (fnmatch(kv->kv_key, desc->http_path, 0) == FNM_NOMATCH) > - return (-1); > - else if (kv->kv_value != NULL && kv->kv_option == KEY_OPTION_NONE) { > - query = desc->http_query == NULL ? "" : desc->http_query; > - if (fnmatch(kv->kv_value, query, FNM_CASEFOLD) == FNM_NOMATCH) > + else if (kv->kv_option != KEY_OPTION_STRIP) { > + if (kv->kv_key == NULL) > + return (0); > + else if (fnmatch(kv->kv_key, desc->http_path, 0) == FNM_NOMATCH) > return (-1); > + else if (kv->kv_value != NULL && kv->kv_option == > KEY_OPTION_NONE) { > + query = desc->http_query == NULL ? "" : > desc->http_query; > + if (fnmatch(kv->kv_value, query, FNM_CASEFOLD) == > FNM_NOMATCH) > + return (-1); > + } > } > > relay_match(actions, kv, match, NULL); > @@ -1554,7 +1557,7 @@ relay_apply_actions(struct ctl_relay_eve > struct kv *host = NULL; > const char *value; > struct kv *kv, *match, *kp, *mp, kvcopy, matchcopy, key; > - int addkv, ret; > + int addkv, ret, nstrip; > char buf[IBUF_READ_SIZE], *ptr; > char *msg = NULL; > const char *meth = NULL; > @@ -1655,6 +1658,15 @@ relay_apply_actions(struct ctl_relay_eve > case KEY_OPTION_LOG: > /* perform this later */ > break; > + case KEY_OPTION_STRIP: > + nstrip = strtonum(kv->kv_value, 0, INT_MAX, NULL); > + if (kv->kv_type == KEY_TYPE_PATH) { > + if (kv_setkey(match, > + server_root_strip(match->kv_key, > + nstrip)) == -1) > + goto fail; > + } > + break; > default: > fatalx("%s: invalid action", __func__); > /* NOTREACHED */ > @@ -1932,3 +1944,19 @@ relay_match(struct kvlist *actions, stru > TAILQ_INSERT_TAIL(actions, kv, kv_match_entry); > } > } > + > +char * > +server_root_strip(char *path, int n) > +{ > + char *p; > + > + /* Strip strip leading directories. Leading '/' is ignored. */ > + for (; n > 0 && *path != '\0'; n--) > + if ((p = strchr(++path, '/')) == NULL) > + path = strchr(path, '\0'); > + else > + path = p; > + > + return (path); > +} > + > Index: relayd.conf.5 > =================================================================== > RCS file: /cvs/src/usr.sbin/relayd/relayd.conf.5,v > retrieving revision 1.202 > diff -u -p -r1.202 relayd.conf.5 > --- relayd.conf.5 30 Oct 2020 09:47:35 -0000 1.202 > +++ relayd.conf.5 3 Jan 2021 10:38:27 -0000 > @@ -1289,6 +1289,15 @@ for example: > block path "/index.html" > block path "/cgi-bin/t.cgi" value "foo=bar*" > .Ed > +.It Ic path strip Ar number > +Strip > +.Ar number > +path components from the beginning of the path of the requested URL > +when using the > +.Ic http > +protocol. > +This type is only available with the direction > +.Ic request . > .It Ic query Ar option Oo Ar key Oo Ic value Ar value Oc Oc > Look up the entity as a query variable in the URL when using the > .Ic http > Index: relayd.h > =================================================================== > RCS file: /cvs/src/usr.sbin/relayd/relayd.h,v > retrieving revision 1.262 > diff -u -p -r1.262 relayd.h > --- relayd.h 14 Sep 2020 11:30:25 -0000 1.262 > +++ relayd.h 3 Jan 2021 10:38:27 -0000 > @@ -292,7 +292,8 @@ enum key_option { > KEY_OPTION_SET, > KEY_OPTION_REMOVE, > KEY_OPTION_HASH, > - KEY_OPTION_LOG > + KEY_OPTION_LOG, > + KEY_OPTION_STRIP > }; > > enum key_type { > -- Kind regards, Hiltjo