diff --git a/Makefile b/Makefile index 17d9dd1dd..43c05fd8b 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ # USE_STATIC_PCRE : enable static libpcre. Recommended. # USE_TCPSPLICE : enable tcp_splice() on Linux (needs kernel patch). # USE_TPROXY : enable transparent proxy. Automatic. +# USE_LINUX_TPROXY : enable full transparent proxy (need kernel patch). # # Options can be forced by specifying "USE_xxx=1" or can be disabled by using # "USE_xxx=" (empty string). @@ -291,6 +292,11 @@ OPTIONS_CFLAGS += -DTPROXY BUILD_OPTIONS += $(call ignore_implicit,USE_TPROXY) endif +ifneq ($(USE_LINUX_TPROXY),) +OPTIONS_CFLAGS += -DCONFIG_HAP_LINUX_TPROXY +BUILD_OPTIONS += $(call ignore_implicit,USE_LINUX_TPROXY) +endif + ifneq ($(USE_POLL),) OPTIONS_CFLAGS += -DENABLE_POLL OPTIONS_OBJS += src/ev_poll.o diff --git a/doc/configuration.txt b/doc/configuration.txt index f2ebd8f6c..6df3f0e57 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -2,9 +2,9 @@ HAProxy Configuration Manual ---------------------- - version 1.3.14.2 + version 1.3.15 willy tarreau - 2008/01/05 + 2008/01/13 This document covers the configuration language as implemented in the version @@ -758,19 +758,30 @@ balance [ ] bind [
]: [, ...] +bind [
]: [, ...] transparent Define one or several listening addresses and/or ports in a frontend. May be used in sections : defaults | frontend | listen | backend no | yes | yes | no Arguments : -
is optional and can be a host name, an IPv4 address, an IPv6 - address, or '*'. It designates the address the frontend will - listen on. If unset, all IPv4 addresses of the system will be - listened on. The same will apply for '*' or the system's special - address "0.0.0.0". +
is optional and can be a host name, an IPv4 address, an IPv6 + address, or '*'. It designates the address the frontend will + listen on. If unset, all IPv4 addresses of the system will be + listened on. The same will apply for '*' or the system's + special address "0.0.0.0". - is the TCP port number the proxy will listen on. The port is - mandatory. Note that in the case of an IPv6 address, the port is - always the number after the last colon (':'). + is the TCP port number the proxy will listen on. The port is + mandatory. Note that in the case of an IPv6 address, the port + is always the number after the last colon (':'). + + transparent is an optional keyword which is supported only on certain + Linux kernels. It indicates that the addresses will be bound + even if they do not belong to the local machine. Any packet + targetting any of these addresses will be caught just as if + the address was locally configured. This normally requires + that IP forwarding is enabled. Caution! do not use this with + the default address '*', as it would redirect any traffic for + the specified port. This keyword is available only when + HAProxy is built with USE_LINUX_TPROXY=1. It is possible to specify a list of address:port combinations delimited by commas. The frontend will then listen on all of these addresses. There is no diff --git a/include/common/compat.h b/include/common/compat.h index 774f9b44c..3c51fb237 100644 --- a/include/common/compat.h +++ b/include/common/compat.h @@ -2,7 +2,7 @@ include/common/compat.h Operating system compatibility interface. - Copyright (C) 2000-2006 Willy Tarreau - w@1wt.eu + Copyright (C) 2000-2008 Willy Tarreau - w@1wt.eu This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -66,6 +66,13 @@ #include #endif +/* On Linux, IP_TRANSPARENT generally requires a kernel patch */ +#if defined(CONFIG_HAP_LINUX_TPROXY) +#if !defined(IP_TRANSPARENT) +#define IP_TRANSPARENT 19 +#endif /* !IP_TRANSPARENT */ +#endif /* CONFIG_HAP_LINUX_TPROXY */ + /* 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 diff --git a/include/types/protocols.h b/include/types/protocols.h index f36074659..971a2a6f6 100644 --- a/include/types/protocols.h +++ b/include/types/protocols.h @@ -2,7 +2,7 @@ include/types/protocols.h This file defines the structures used by generic network protocols. - Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu + Copyright (C) 2000-2008 Willy Tarreau - w@1wt.eu This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -65,6 +65,7 @@ /* listener socket options */ #define LI_O_NONE 0x0000 #define LI_O_NOLINGER 0x0001 /* disable linger on this socket */ +#define LI_O_FOREIGN 0x0002 /* permit listening on foreing addresses */ /* The listener will be directly referenced by the fdtab[] which holds its * socket. The listener provides the protocol-specific accept() function to diff --git a/src/cfgparse.c b/src/cfgparse.c index 0c89c5bb8..b2bc4514e 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -728,6 +728,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv) /* Now let's parse the proxy-specific keywords */ if (!strcmp(args[0], "bind")) { /* new listen addresses */ + struct listener *last_listen; if (curproxy == &defproxy) { Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]); return -1; @@ -740,9 +741,30 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv) file, linenum, args[0]); return -1; } - curproxy->listen = str2listener(args[1], curproxy->listen); + + last_listen = curproxy->listen; + curproxy->listen = str2listener(args[1], last_listen); if (!curproxy->listen) return -1; + if (*args[2]) { +#ifdef CONFIG_HAP_LINUX_TPROXY + if (!strcmp(args[2], "transparent")) { /* transparently bind to these addresses */ + struct listener *l; + + for (l = curproxy->listen; l != last_listen; l = l->next) + l->options |= LI_O_FOREIGN; + } + else { + Alert("parsing [%s:%d] : '%s' only supports the 'transparent' option.\n", + file, linenum, args[0]); + return -1; + } +#else + Alert("parsing [%s:%d] : '%s' supports no option after the address list.\n", + file, linenum, args[0]); + return -1; +#endif + } global.maxsock++; return 0; } diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 2da34db38..78d936746 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -153,6 +153,13 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen) * it might return an error that we will silently ignore. */ setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *) &one, sizeof(one)); +#endif +#ifdef CONFIG_HAP_LINUX_TPROXY + if ((listener->options & LI_O_FOREIGN) + && (setsockopt(fd, SOL_IP, IP_TRANSPARENT, (char *) &one, sizeof(one)) == -1)) { + msg = "cannot make listening socket transparent"; + err |= ERR_ALERT; + } #endif if (bind(fd, (struct sockaddr *)&listener->addr, listener->proto->sock_addrlen) == -1) { err |= ERR_RETRYABLE | ERR_ALERT;