mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 15:17:01 +02:00
MINOR: tcp-act: parse 'tcp-request attach-srv' session rule
Create a new tcp-request session rule 'attach-srv'. The parsing handler is used to extract the server targetted with the notation 'backend/server'. The server instance is stored in the act_rule instance under the new union variant 'attach_srv'. Extra checks are implemented in parsing to ensure attach-srv is only used for proxy in HTTP mode and with listeners/server with no explicit protocol reference or HTTP/2 only. The action handler itself is really simple. It assigns the stored server instance to the 'reverse' member of the connection instance. It will be used in a future patch to implement passive reverse-connect.
This commit is contained in:
parent
6e428dfaf2
commit
58cb76d7e1
@ -13825,6 +13825,7 @@ tcp-request session <action> [{if | unless} <condition>]
|
||||
The first keyword is the rule's action. Several types of actions are
|
||||
supported:
|
||||
- accept
|
||||
- attach-srv <srv>
|
||||
- reject
|
||||
- sc-add-gpc(<idx>,<sc-id>) { <int> | <expr> }
|
||||
- sc-inc-gpc(<idx>,<sc-id>)
|
||||
@ -13893,6 +13894,16 @@ tcp-request session accept [ { if | unless } <condition> ]
|
||||
This is used to accept the connection. No further "tcp-request session"
|
||||
rules are evaluated.
|
||||
|
||||
tcp-request session attach-srv <srv>
|
||||
|
||||
This is used to intercept the connection after proper HTTP/2 establishment.
|
||||
The connection is reversed to the backend side and inserted into the idle
|
||||
pool of <srv> server. This is useful for reverse server with '@reverse'
|
||||
address.
|
||||
|
||||
This rule is only valid for frontend in HTTP mode. Also all listeners must
|
||||
not require a protocol different from HTTP/2.
|
||||
|
||||
tcp-request session reject [ { if | unless } <condition> ]
|
||||
|
||||
This is used to reject the connection. No further "tcp-request session" rules
|
||||
|
@ -185,6 +185,10 @@ struct act_rule {
|
||||
struct sample_expr *expr;
|
||||
} gpt;
|
||||
struct track_ctr_prm trk_ctr;
|
||||
struct {
|
||||
char *srvname; /* server name from config parsing. */
|
||||
struct server *srv; /* target server to attach the connection */
|
||||
} attach_srv; /* 'attach-srv' rule */
|
||||
struct {
|
||||
void *p[4];
|
||||
} act; /* generic pointers to be used by custom actions */
|
||||
|
@ -703,6 +703,15 @@ static inline int conn_is_reverse(const struct connection *conn)
|
||||
return !!(conn->reverse.target);
|
||||
}
|
||||
|
||||
/* Initialize <conn> as a reverse connection to <target>. */
|
||||
static inline void conn_set_reverse(struct connection *conn, enum obj_type *target)
|
||||
{
|
||||
/* Ensure the correct target type is used depending on the connection side before reverse. */
|
||||
BUG_ON(!conn_is_back(conn) && !objt_server(target));
|
||||
|
||||
conn->reverse.target = target;
|
||||
}
|
||||
|
||||
#endif /* _HAPROXY_CONNECTION_H */
|
||||
|
||||
/*
|
||||
|
105
src/tcp_act.c
105
src/tcp_act.c
@ -32,13 +32,26 @@
|
||||
#include <haproxy/global.h>
|
||||
#include <haproxy/http_rules.h>
|
||||
#include <haproxy/proto_tcp.h>
|
||||
#include <haproxy/proxy-t.h>
|
||||
#include <haproxy/proxy.h>
|
||||
#include <haproxy/sample.h>
|
||||
#include <haproxy/sc_strm.h>
|
||||
#include <haproxy/server.h>
|
||||
#include <haproxy/session.h>
|
||||
#include <haproxy/tcp_rules.h>
|
||||
#include <haproxy/tools.h>
|
||||
|
||||
static enum act_return tcp_action_attach_srv(struct act_rule *rule, struct proxy *px,
|
||||
struct session *sess, struct stream *s, int flags)
|
||||
{
|
||||
struct server *srv = rule->arg.attach_srv.srv;
|
||||
struct connection *conn = objt_conn(sess->origin);
|
||||
if (!conn)
|
||||
return ACT_RET_ABRT;
|
||||
|
||||
conn_set_reverse(conn, &srv->obj_type);
|
||||
return ACT_RET_CONT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute the "set-src" action. May be called from {tcp,http}request.
|
||||
* It only changes the address and tries to preserve the original port. If the
|
||||
@ -374,6 +387,14 @@ static enum act_return tcp_action_set_tos(struct act_rule *rule, struct proxy *p
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Release the sample expr when releasing attach-srv action
|
||||
*/
|
||||
static void release_attach_srv_action(struct act_rule *rule)
|
||||
{
|
||||
ha_free(&rule->arg.attach_srv.srvname);
|
||||
}
|
||||
|
||||
/*
|
||||
* Release the sample expr when releasing a set src/dst action
|
||||
*/
|
||||
@ -382,6 +403,87 @@ static void release_set_src_dst_action(struct act_rule *rule)
|
||||
release_sample_expr(rule->arg.expr);
|
||||
}
|
||||
|
||||
static int tcp_check_attach_srv(struct act_rule *rule, struct proxy *px, char **err)
|
||||
{
|
||||
struct proxy *be = NULL;
|
||||
struct server *srv = NULL;
|
||||
struct bind_conf *bind_conf;
|
||||
char *name = rule->arg.attach_srv.srvname;
|
||||
struct ist be_name, sv_name;
|
||||
|
||||
if (px->mode != PR_MODE_HTTP) {
|
||||
memprintf(err, "attach-srv rule requires HTTP proxy mode");
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_for_each_entry(bind_conf, &px->conf.bind, by_fe) {
|
||||
if ((bind_conf->mux_proto && !isteqi(bind_conf->mux_proto->token, ist("h2")))
|
||||
#ifdef USE_OPENSSL
|
||||
|| (bind_conf->ssl_conf.alpn_str && strcmp(bind_conf->ssl_conf.alpn_str, "\x02h2") != 0)
|
||||
#endif
|
||||
) {
|
||||
memprintf(err, "attach-srv rule: incompatible with listener on %s:%d which uses protocol other than HTTP/2",
|
||||
bind_conf->file, bind_conf->line);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
sv_name = ist(name);
|
||||
be_name = istsplit(&sv_name, '/');
|
||||
if (!istlen(sv_name)) {
|
||||
memprintf(err, "attach-srv rule: invalid server name '%s'", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(be = proxy_be_by_name(ist0(be_name)))) {
|
||||
memprintf(err, "attach-srv rule: no such backend '%s/%s'", ist0(be_name), ist0(sv_name));
|
||||
return 0;
|
||||
}
|
||||
if (!(srv = server_find_by_name(be, ist0(sv_name)))) {
|
||||
memprintf(err, "attach-srv rule: no such server '%s/%s'", ist0(be_name), ist0(sv_name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((srv->mux_proto && !isteqi(srv->mux_proto->token, ist("h2")))
|
||||
#ifdef USE_OPENSSL
|
||||
|| (srv->ssl_ctx.alpn_str && strcmp(srv->ssl_ctx.alpn_str, "\x02h2") != 0)
|
||||
#endif
|
||||
) {
|
||||
memprintf(err, "attach-srv rule: incompatible with server '%s:%s' which uses protocol other than HTTP/2",
|
||||
ist0(be_name), ist0(sv_name));
|
||||
return 0;
|
||||
}
|
||||
|
||||
rule->arg.attach_srv.srv = srv;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static enum act_parse_ret tcp_parse_attach_srv(const char **args, int *cur_arg, struct proxy *px,
|
||||
struct act_rule *rule, char **err)
|
||||
{
|
||||
char *srvname;
|
||||
|
||||
rule->action = ACT_CUSTOM;
|
||||
rule->action_ptr = tcp_action_attach_srv;
|
||||
rule->release_ptr = release_attach_srv_action;
|
||||
rule->check_ptr = tcp_check_attach_srv;
|
||||
rule->arg.attach_srv.srvname = NULL;
|
||||
|
||||
srvname = my_strndup(args[*cur_arg], strlen(args[*cur_arg]));
|
||||
if (!srvname)
|
||||
goto err;
|
||||
rule->arg.attach_srv.srvname = srvname;
|
||||
|
||||
++(*cur_arg);
|
||||
|
||||
return ACT_RET_PRS_OK;
|
||||
|
||||
err:
|
||||
ha_free(&rule->arg.attach_srv.srvname);
|
||||
return ACT_RET_PRS_ERR;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
@ -551,6 +653,7 @@ 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, {
|
||||
{ "attach-srv" , tcp_parse_attach_srv },
|
||||
{ "set-dst" , tcp_parse_set_src_dst },
|
||||
{ "set-dst-port", tcp_parse_set_src_dst },
|
||||
{ "set-mark", tcp_parse_set_mark },
|
||||
|
Loading…
Reference in New Issue
Block a user