]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] support fully transparent proxy on Linux (USE_LINUX_TPROXY)
authorWilly Tarreau <w@1wt.eu>
Sun, 13 Jan 2008 13:49:51 +0000 (14:49 +0100)
committerWilly Tarreau <w@1wt.eu>
Sun, 13 Jan 2008 13:49:51 +0000 (14:49 +0100)
Using some Linux kernel patches, it is possible to redirect non-local
traffic to local sockets when IP forwarding is enabled. In order to
enable this option, we introduce the "transparent" option keyword on
the "bind" command line. It will make the socket reachable by remote
sources even if the destination address does not belong to the machine.

Makefile
doc/configuration.txt
include/common/compat.h
include/types/protocols.h
src/cfgparse.c
src/proto_tcp.c

index 17d9dd1dd133cb2ecbf06d53ddd333f984844653..43c05fd8ba0b853d66ff9c45571eb517d5140552 100644 (file)
--- 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
index f2ebd8f6c9c48446396a13f074f69b0662b2249f..6df3f0e570ed7728b063ec4abd16862da743b182 100644 (file)
@@ -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 <algorithm> [ <arguments> ]
 
 
 bind [<address>]:<port> [, ...]
+bind [<address>]:<port> [, ...] 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 :
-    <address> 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".
-
-    <port>    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 (':').
+    <address>     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".
+
+    <port>        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
index 774f9b44c38257d100ba187b50ccd0b153601467..3c51fb237c43c4755924a30aaa9627a290abbdc2 100644 (file)
@@ -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
 #include <linux/netfilter_ipv4.h>
 #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
index f360746591956713f86dca9ac3e9c6807b113d1d..971a2a6f6d8dd4cd2c942a95b50a9d7d20fb9996 100644 (file)
@@ -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
index 0c89c5bb8cf2045be60706961ab8758189b11474..b2bc4514e53a9f44fab4193861c1732deb81e24c 100644 (file)
@@ -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;
        }
index 2da34db38fdd0d1e3534d7f6f089256964bfe737..78d936746d5ba4ee11eb0704ff921f89f724ca24 100644 (file)
@@ -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;