MINOR: checks: Add the addr option for tcp-check connect rule

With this option, it is now possible to use a specific address to open the
connection for a tcp-check connect rule. If the port option is also specified,
it is used in priority.
This commit is contained in:
Christopher Faulet 2020-03-31 08:15:58 +02:00
parent 4dce5923c8
commit 5c28874a69
3 changed files with 67 additions and 24 deletions

View File

@ -9821,9 +9821,12 @@ tcp-check connect [params*]
default Use default options of the server line to do the health
checks. This parameter is exclusive with all other options.
port if not set, check port or server port is used.
It tells HAProxy where to open the connection to.
<port> must be a valid TCP port source integer, from 1 to 65535.
port if not set, check port or server port is used.
It tells HAProxy where to open the connection to.
<port> must be a valid TCP port source integer, from 1 to
65535.
addr <ip> defines the IP address to do the health check.
send-proxy send a PROXY protocol string
@ -9838,7 +9841,7 @@ tcp-check connect [params*]
for instance: "http/1.1,http/1.0" (without quotes).
If it is not set, the server ALPN is used.
linger cleanly close the connection instead of using a single RST.
linger cleanly close the connection instead of using a single RST.
Examples:
# check HTTP and HTTPs services on a server.

View File

@ -220,11 +220,12 @@ struct analyze_status {
#define TCPCHK_OPT_SOCKS4 0x0010 /* check the connection via socks4 proxy */
struct tcpcheck_connect {
uint16_t port; /* port to connect to */
uint16_t options; /* options when setting up a new connection */
char *sni; /* server name to use for SSL connections */
char *alpn; /* ALPN to use for the SSL connection */
int alpn_len; /* ALPN string length */
char *sni; /* server name to use for SSL connections */
char *alpn; /* ALPN to use for the SSL connection */
int alpn_len; /* ALPN string length */
uint16_t options; /* options when setting up a new connection */
uint16_t port; /* port to connect to */
struct sockaddr_storage addr; /* the address to the connect */
};
enum tcpcheck_send_type {

View File

@ -2807,7 +2807,7 @@ static enum tcpcheck_eval_ret tcpcheck_eval_connect(struct check *check, struct
struct protocol *proto;
struct xprt_ops *xprt;
char *comment;
int status;
int status, port;
/* For a connect action we'll create a new connection. We may also have
* to kill a previous one. But we don't want to leave *without* a
@ -2859,20 +2859,26 @@ static enum tcpcheck_eval_ret tcpcheck_eval_connect(struct check *check, struct
goto fail_check;
}
/* connect to the check addr if specified on the server. otherwise, use
* the server addr
/* connect to the connect rule addr if specified, otherwise the check
* addr if specified on the server. otherwise, use the server addr
*/
*conn->dst = (is_addr(&check->addr) ? check->addr : s->addr);
*conn->dst = (is_addr(&connect->addr)
? connect->addr
: (is_addr(&check->addr) ? check->addr : s->addr));
proto = protocol_by_family(conn->dst->ss_family);
if (connect->port)
set_host_port(conn->dst, connect->port);
else if (check->port)
set_host_port(conn->dst, check->port);
else {
int i = get_host_port(&check->addr);
set_host_port(conn->dst, ((i > 0) ? i : s->svc_port));
}
port = 0;
if (!port && connect->port)
port = connect->port;
if (!port && is_inet_addr(&connect->addr))
port = get_host_port(&connect->addr);
if (!port && check->port)
port = check->port;
if (!port && is_inet_addr(&check->addr))
port = get_host_port(&check->addr);
if (!port)
port = s->svc_port;
set_host_port(conn->dst, port);
xprt = ((connect->options & TCPCHK_OPT_DEFAULT_CONNECT)
? check->xprt
@ -3929,7 +3935,7 @@ static int init_srv_check(struct server *srv)
/* search the first action (connect / send / expect) in the list */
r = get_first_tcpcheck_rule(srv->proxy->tcpcheck_rules);
if (!r || (r->action != TCPCHK_ACT_CONNECT) || !r->connect.port) {
if (!r || (r->action != TCPCHK_ACT_CONNECT) || (!r->connect.port && !get_host_port(&r->connect.addr))) {
ha_alert("config: %s '%s': server '%s' has neither service port nor check port "
"nor tcp_check rule 'connect' with port information.\n",
proxy_type_str(srv->proxy), srv->proxy->id, srv->id);
@ -3939,7 +3945,7 @@ static int init_srv_check(struct server *srv)
/* scan the tcp-check ruleset to ensure a port has been configured */
list_for_each_entry(r, srv->proxy->tcpcheck_rules, list) {
if ((r->action == TCPCHK_ACT_CONNECT) && (!r->connect.port)) {
if ((r->action == TCPCHK_ACT_CONNECT) && (!r->connect.port || !get_host_port(&r->connect.addr))) {
ha_alert("config: %s '%s': server '%s' has neither service port nor check port, "
"and a tcp_check rule 'connect' with no port information.\n",
proxy_type_str(srv->proxy), srv->proxy->id, srv->id);
@ -4081,6 +4087,7 @@ static struct tcpcheck_rule *parse_tcpcheck_connect(char **args, int cur_arg, st
char **errmsg)
{
struct tcpcheck_rule *chk = NULL;
struct sockaddr_storage *sk = NULL;
char *comment = NULL, *sni = NULL, *alpn = NULL;
unsigned short conn_opts = 0;
long port = 0;
@ -4106,6 +4113,36 @@ static struct tcpcheck_rule *parse_tcpcheck_connect(char **args, int cur_arg, st
}
conn_opts = TCPCHK_OPT_DEFAULT_CONNECT;
}
else if (strcmp(args[cur_arg], "addr") == 0) {
int port1, port2;
struct protocol *proto;
if (!*(args[cur_arg+1])) {
memprintf(errmsg, "'%s' expects <ipv4|ipv6> as argument.", args[cur_arg]);
goto error;
}
sk = str2sa_range(args[cur_arg+1], NULL, &port1, &port2, errmsg, NULL, NULL, 1);
if (!sk) {
memprintf(errmsg, "'%s' : %s.", args[cur_arg], *errmsg);
goto error;
}
proto = protocol_by_family(sk->ss_family);
if (!proto || !proto->connect) {
memprintf(errmsg, "'%s' : connect() not supported for this address family.\n",
args[cur_arg]);
goto error;
}
if (port1 != port2) {
memprintf(errmsg, "'%s' : port ranges and offsets are not allowed in '%s'\n",
args[cur_arg], args[cur_arg+1]);
goto error;
}
cur_arg++;
}
else if (strcmp(args[cur_arg], "port") == 0) {
if (!*(args[cur_arg+1])) {
memprintf(errmsg, "'%s' expects a port number as argument.", args[cur_arg]);
@ -4171,7 +4208,7 @@ static struct tcpcheck_rule *parse_tcpcheck_connect(char **args, int cur_arg, st
#endif /* USE_OPENSSL */
else {
memprintf(errmsg, "expects 'comment', 'port', 'send-proxy'"
memprintf(errmsg, "expects 'comment', 'port', 'addr', 'send-proxy'"
#ifdef USE_OPENSSL
", 'ssl', 'sni', 'alpn'"
#endif /* USE_OPENSSL */
@ -4194,6 +4231,8 @@ static struct tcpcheck_rule *parse_tcpcheck_connect(char **args, int cur_arg, st
chk->connect.sni = sni;
chk->connect.alpn = alpn;
chk->connect.alpn_len= alpn_len;
if (sk)
chk->connect.addr = *sk;
return chk;
error: