[MEDIUM] add support for source interface binding at the server level
Add support for "interface <name>" after the "source" statement on the server line.
This commit is contained in:
parent
d53f96b3f0
commit
c76721da57
@ -4294,6 +4294,7 @@ slowstart <start_time_in_ms>
|
||||
seen as failed.
|
||||
|
||||
source <addr>[:<port>] [usesrc { <addr2>[:<port2>] | client | clientip } ]
|
||||
source <addr>[:<port>] [interface <name>] ...
|
||||
The "source" parameter sets the source address which will be used when
|
||||
connecting to the server. It follows the exact same parameters and principle
|
||||
as the backend "source" keyword, except that it only applies to the server
|
||||
|
@ -91,6 +91,8 @@ struct server {
|
||||
#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
|
||||
struct sockaddr_in tproxy_addr; /* non-local address we want to bind to for connect() */
|
||||
#endif
|
||||
int iface_len; /* bind interface name length */
|
||||
char *iface_name; /* bind interface name or NULL */
|
||||
|
||||
struct server *tracknext, *tracked; /* next server in a tracking list, tracked server */
|
||||
char *trackit; /* temporary variable to make assignment deferrable */
|
||||
|
@ -1718,6 +1718,11 @@ int connect_server(struct session *s)
|
||||
remote = (struct sockaddr_in *)&s->cli_addr;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef SO_BINDTODEVICE
|
||||
/* Note: this might fail if not CAP_NET_RAW */
|
||||
if (s->srv->iface_name)
|
||||
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, s->srv->iface_name, s->srv->iface_len);
|
||||
#endif
|
||||
ret = tcpv4_bind_socket(fd, flags, &s->srv->source_addr, remote);
|
||||
if (ret) {
|
||||
|
@ -1976,39 +1976,66 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
|
||||
newsrv->state |= SRV_BIND_SRC;
|
||||
newsrv->source_addr = *str2sa(args[cur_arg + 1]);
|
||||
cur_arg += 2;
|
||||
if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
|
||||
while (*(args[cur_arg])) {
|
||||
if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
|
||||
#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
|
||||
#if !defined(CONFIG_HAP_LINUX_TPROXY)
|
||||
if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
|
||||
Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
|
||||
file, linenum, "usesrc", "source");
|
||||
return -1;
|
||||
}
|
||||
if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
|
||||
Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
|
||||
file, linenum, "usesrc", "source");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
if (!*args[cur_arg + 1]) {
|
||||
Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
|
||||
file, linenum, "usesrc");
|
||||
return -1;
|
||||
}
|
||||
if (!strcmp(args[cur_arg + 1], "client")) {
|
||||
newsrv->state |= SRV_TPROXY_CLI;
|
||||
} else if (!strcmp(args[cur_arg + 1], "clientip")) {
|
||||
newsrv->state |= SRV_TPROXY_CIP;
|
||||
} else {
|
||||
newsrv->state |= SRV_TPROXY_ADDR;
|
||||
newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
|
||||
}
|
||||
global.last_checks |= LSTCHK_NETADM;
|
||||
if (!*args[cur_arg + 1]) {
|
||||
Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
|
||||
file, linenum, "usesrc");
|
||||
return -1;
|
||||
}
|
||||
if (!strcmp(args[cur_arg + 1], "client")) {
|
||||
newsrv->state |= SRV_TPROXY_CLI;
|
||||
} else if (!strcmp(args[cur_arg + 1], "clientip")) {
|
||||
newsrv->state |= SRV_TPROXY_CIP;
|
||||
} else {
|
||||
newsrv->state |= SRV_TPROXY_ADDR;
|
||||
newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
|
||||
}
|
||||
global.last_checks |= LSTCHK_NETADM;
|
||||
#if !defined(CONFIG_HAP_LINUX_TPROXY)
|
||||
global.last_checks |= LSTCHK_CTTPROXY;
|
||||
global.last_checks |= LSTCHK_CTTPROXY;
|
||||
#endif
|
||||
cur_arg += 2;
|
||||
cur_arg += 2;
|
||||
continue;
|
||||
#else /* no TPROXY support */
|
||||
Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
|
||||
Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
|
||||
file, linenum, "usesrc");
|
||||
return -1;
|
||||
#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
|
||||
} /* "usesrc" */
|
||||
|
||||
if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
|
||||
#ifdef SO_BINDTODEVICE
|
||||
if (!*args[cur_arg + 1]) {
|
||||
Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
|
||||
file, linenum, args[0]);
|
||||
return -1;
|
||||
}
|
||||
if (newsrv->iface_name)
|
||||
free(newsrv->iface_name);
|
||||
|
||||
newsrv->iface_name = strdup(args[cur_arg + 1]);
|
||||
newsrv->iface_len = strlen(newsrv->iface_name);
|
||||
global.last_checks |= LSTCHK_NETADM;
|
||||
#else
|
||||
Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
|
||||
file, linenum, args[0], args[cur_arg]);
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
cur_arg += 2;
|
||||
continue;
|
||||
}
|
||||
/* this keyword in not an option of "source" */
|
||||
break;
|
||||
} /* while */
|
||||
}
|
||||
else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
|
||||
Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
|
||||
|
@ -589,6 +589,12 @@ void process_chk(struct task *t, int *next)
|
||||
remote = (struct sockaddr_in *)&s->tproxy_addr;
|
||||
flags = 3;
|
||||
}
|
||||
#endif
|
||||
#ifdef SO_BINDTODEVICE
|
||||
/* Note: this might fail if not CAP_NET_RAW */
|
||||
if (s->iface_name)
|
||||
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
|
||||
s->iface_name, s->iface_len);
|
||||
#endif
|
||||
ret = tcpv4_bind_socket(fd, flags, &s->source_addr, remote);
|
||||
if (ret) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user