REORG: tproxy: prepare the transparent proxy defines for accepting other OSes
This patch does not change the logic of the code, it only changes the way OS-specific defines are tested. At the moment the transparent proxy code heavily depends on Linux-specific defines. This first patch introduces a new define "CONFIG_HAP_TRANSPARENT" which is set every time the defines used by transparent proxy are present. This also means that with an up-to-date libc, it should not be necessary anymore to force CONFIG_HAP_LINUX_TPROXY during the build, as the flags will automatically be detected. The CTTPROXY flags still remain separate because this older API doesn't work the same way. A new line has been added in the version output for haproxy -vv to indicate what transparent proxy support is available.
This commit is contained in:
parent
dd11293e84
commit
d551fb5a8d
|
@ -93,6 +93,12 @@
|
|||
#endif /* !IPV6_TRANSPARENT */
|
||||
#endif /* CONFIG_HAP_LINUX_TPROXY */
|
||||
|
||||
#if defined(IP_FREEBIND) \
|
||||
|| defined(IP_TRANSPARENT) \
|
||||
|| defined(IPV6_TRANSPARENT)
|
||||
#define CONFIG_HAP_TRANSPARENT
|
||||
#endif
|
||||
|
||||
/* We'll try to enable SO_REUSEPORT on Linux 2.4 and 2.6 if not defined.
|
||||
* There are two families of values depending on the architecture. Those
|
||||
* are at least valid on Linux 2.4 and 2.6, reason why we'll rely on the
|
||||
|
|
|
@ -219,7 +219,7 @@ struct conn_src {
|
|||
char *iface_name; /* bind interface name or NULL */
|
||||
struct port_range *sport_range; /* optional per-server TCP source ports */
|
||||
struct sockaddr_storage source_addr; /* the address to which we want to bind for connect() */
|
||||
#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
|
||||
#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
|
||||
struct sockaddr_storage tproxy_addr; /* non-local address we want to bind to for connect() */
|
||||
char *bind_hdr_name; /* bind to this header name if defined */
|
||||
int bind_hdr_len; /* length of the name of the header above */
|
||||
|
|
|
@ -884,7 +884,7 @@ int assign_server_and_queue(struct session *s)
|
|||
*/
|
||||
static void assign_tproxy_address(struct session *s)
|
||||
{
|
||||
#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
|
||||
#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
|
||||
struct server *srv = objt_server(s->target);
|
||||
struct conn_src *src;
|
||||
|
||||
|
|
|
@ -1813,7 +1813,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||
curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
|
||||
curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
|
||||
curproxy->conn_src.opts = defproxy.conn_src.opts;
|
||||
#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
|
||||
#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
|
||||
curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
|
||||
#endif
|
||||
}
|
||||
|
@ -4558,8 +4558,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||
cur_arg += 2;
|
||||
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 defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
|
||||
#if !defined(CONFIG_HAP_TRANSPARENT)
|
||||
if (!is_addr(&newsrv->conn_src.source_addr)) {
|
||||
Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
|
||||
file, linenum, "usesrc", "source");
|
||||
|
@ -4648,7 +4648,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||
newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
|
||||
}
|
||||
global.last_checks |= LSTCHK_NETADM;
|
||||
#if !defined(CONFIG_HAP_LINUX_TPROXY)
|
||||
#if !defined(CONFIG_HAP_TRANSPARENT)
|
||||
global.last_checks |= LSTCHK_CTTPROXY;
|
||||
#endif
|
||||
cur_arg += 2;
|
||||
|
@ -4658,7 +4658,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||
file, linenum, "usesrc");
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
|
||||
#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
|
||||
} /* "usesrc" */
|
||||
|
||||
if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
|
||||
|
@ -5046,8 +5046,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||
cur_arg = 2;
|
||||
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 defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
|
||||
#if !defined(CONFIG_HAP_TRANSPARENT)
|
||||
if (!is_addr(&curproxy->conn_src.source_addr)) {
|
||||
Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
|
||||
file, linenum, "usesrc");
|
||||
|
@ -5136,7 +5136,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||
curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
|
||||
}
|
||||
global.last_checks |= LSTCHK_NETADM;
|
||||
#if !defined(CONFIG_HAP_LINUX_TPROXY)
|
||||
#if !defined(CONFIG_HAP_TRANSPARENT)
|
||||
global.last_checks |= LSTCHK_CTTPROXY;
|
||||
#endif
|
||||
#else /* no TPROXY support */
|
||||
|
@ -6826,7 +6826,7 @@ int check_config_validity()
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
|
||||
#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
|
||||
if (curproxy->conn_src.bind_hdr_occ) {
|
||||
curproxy->conn_src.bind_hdr_occ = 0;
|
||||
Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
|
||||
|
@ -6853,7 +6853,7 @@ int check_config_validity()
|
|||
err_code |= ERR_WARN;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
|
||||
#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
|
||||
if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
|
||||
newsrv->conn_src.bind_hdr_occ = 0;
|
||||
Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
|
||||
|
|
|
@ -313,6 +313,22 @@ void display_build_opts()
|
|||
printf("Built without PCRE support (using libc's regex instead)\n");
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_HAP_TRANSPARENT) || defined(CONFIG_HAP_CTTPROXY)
|
||||
printf("Built with transparent proxy support using:"
|
||||
#if defined(CONFIG_HAP_CTTPROXY)
|
||||
" CTTPROXY"
|
||||
#endif
|
||||
#if defined(IP_TRANSPARENT)
|
||||
" IP_TRANSPARENT"
|
||||
#endif
|
||||
#if defined(IPV6_TRANSPARENT)
|
||||
" IPV6_TRANSPARENT"
|
||||
#endif
|
||||
#if defined(IP_FREEBIND)
|
||||
" IP_FREEBIND"
|
||||
#endif
|
||||
"\n");
|
||||
#endif
|
||||
putchar('\n');
|
||||
|
||||
list_pollers(stdout);
|
||||
|
|
|
@ -122,15 +122,24 @@ int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct so
|
|||
struct sockaddr_storage bind_addr;
|
||||
int foreign_ok = 0;
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_HAP_LINUX_TPROXY
|
||||
static int ip_transp_working = 1;
|
||||
static int ip6_transp_working = 1;
|
||||
|
||||
switch (local->ss_family) {
|
||||
case AF_INET:
|
||||
if (flags && ip_transp_working) {
|
||||
if (setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) == 0
|
||||
|| setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == 0)
|
||||
/* This deserves some explanation. Some platforms will support
|
||||
* multiple combinations of certain methods, so we try the
|
||||
* supported ones until one succeeds.
|
||||
*/
|
||||
if (0
|
||||
#if defined(IP_TRANSPARENT)
|
||||
|| (setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) == 0)
|
||||
#endif
|
||||
#if defined(IP_FREEBIND)
|
||||
|| (setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == 0)
|
||||
#endif
|
||||
)
|
||||
foreign_ok = 1;
|
||||
else
|
||||
ip_transp_working = 0;
|
||||
|
@ -138,14 +147,18 @@ int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct so
|
|||
break;
|
||||
case AF_INET6:
|
||||
if (flags && ip6_transp_working) {
|
||||
if (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, sizeof(one)) == 0)
|
||||
if (0
|
||||
#if defined(IPV6_TRANSPARENT)
|
||||
|| (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, sizeof(one)) == 0)
|
||||
#endif
|
||||
)
|
||||
foreign_ok = 1;
|
||||
else
|
||||
ip6_transp_working = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (flags) {
|
||||
memset(&bind_addr, 0, sizeof(bind_addr));
|
||||
bind_addr.ss_family = remote->ss_family;
|
||||
|
@ -621,25 +634,35 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen)
|
|||
if (!ext)
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
|
||||
#endif
|
||||
#ifdef CONFIG_HAP_LINUX_TPROXY
|
||||
|
||||
if (!ext && (listener->options & LI_O_FOREIGN)) {
|
||||
switch (listener->addr.ss_family) {
|
||||
case AF_INET:
|
||||
if ((setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) == -1)
|
||||
&& (setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == -1)) {
|
||||
if (1
|
||||
#if defined(IP_TRANSPARENT)
|
||||
&& (setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) == -1)
|
||||
#endif
|
||||
#if defined(IP_FREEBIND)
|
||||
&& (setsockopt(fd, SOL_IP, IP_FREEBIND, &one, sizeof(one)) == -1)
|
||||
#endif
|
||||
) {
|
||||
msg = "cannot make listening socket transparent";
|
||||
err |= ERR_ALERT;
|
||||
}
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, sizeof(one)) == -1) {
|
||||
if (1
|
||||
#if defined(IPV6_TRANSPARENT)
|
||||
&& (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &one, sizeof(one)) == -1)
|
||||
#endif
|
||||
) {
|
||||
msg = "cannot make listening socket transparent";
|
||||
err |= ERR_ALERT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SO_BINDTODEVICE
|
||||
/* Note: this might fail if not CAP_NET_RAW */
|
||||
if (!ext && listener->interface) {
|
||||
|
@ -1546,7 +1569,7 @@ static int bind_parse_v6only(char **args, int cur_arg, struct proxy *px, struct
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HAP_LINUX_TPROXY
|
||||
#ifdef CONFIG_HAP_TRANSPARENT
|
||||
/* parse the "transparent" bind keyword */
|
||||
static int bind_parse_transparent(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
|
||||
{
|
||||
|
@ -1695,7 +1718,7 @@ static struct bind_kw_list bind_kws = { "TCP", { }, {
|
|||
#ifdef TCP_FASTOPEN
|
||||
{ "tfo", bind_parse_tfo, 0 }, /* enable TCP_FASTOPEN of listening socket */
|
||||
#endif
|
||||
#ifdef CONFIG_HAP_LINUX_TPROXY
|
||||
#ifdef CONFIG_HAP_TRANSPARENT
|
||||
{ "transparent", bind_parse_transparent, 0 }, /* transparently bind to the specified addresses */
|
||||
#endif
|
||||
#ifdef IPV6_V6ONLY
|
||||
|
|
Loading…
Reference in New Issue