MAJOR: tproxy: remove support for cttproxy

This was the first transparent proxy technology supported by haproxy
circa 2005 but it was obsoleted in 2007 by Tproxy 4.0 which removed a
lot of the earlier versions' shortcomings and was finally merged into
the kernel. Since nobody has been using cttproxy for many years now
and nobody has even just tried to compile the files, it's time to
remove it. The doc was updated as well.
This commit is contained in:
Willy Tarreau 2015-08-20 19:35:14 +02:00
parent e0627bdae0
commit 29fbe51490
14 changed files with 13 additions and 392 deletions

View File

@ -5,7 +5,6 @@
#
# Valid USE_* options are the following. Most of them are automatically set by
# the TARGET, others have to be explictly specified :
# USE_CTTPROXY : enable CTTPROXY on Linux (needs kernel patch).
# USE_DLMALLOC : enable use of dlmalloc (see DLMALLOC_SRC)
# USE_EPOLL : enable epoll() on Linux 2.6. Automatic.
# USE_GETSOCKNAME : enable getsockname() on Linux 2.2. Automatic.
@ -426,12 +425,6 @@ OPTIONS_CFLAGS += -DCONFIG_HAP_LINUX_SPLICE
BUILD_OPTIONS += $(call ignore_implicit,USE_LINUX_SPLICE)
endif
ifneq ($(USE_CTTPROXY),)
OPTIONS_CFLAGS += -DCONFIG_HAP_CTTPROXY
OPTIONS_OBJS += src/cttproxy.o
BUILD_OPTIONS += $(call ignore_implicit,USE_CTTPROXY)
endif
ifneq ($(USE_TPROXY),)
OPTIONS_CFLAGS += -DTPROXY
BUILD_OPTIONS += $(call ignore_implicit,USE_TPROXY)

View File

@ -5477,8 +5477,8 @@ option mysql-check [ user <username> [ post-41 ] ]
various purposes, including IP privilege matching and connection logging.
When possible, it is often wise to masquerade the client's IP address when
connecting to the server using the "usesrc" argument of the "source" keyword,
which requires the cttproxy feature to be compiled in, and the MySQL server
to route the client via the machine hosting haproxy.
which requires the transparent proxy feature to be compiled in, and the MySQL
server to route the client via the machine hosting haproxy.
See also: "option httpchk"
@ -5725,7 +5725,7 @@ option smtpchk <hello> <domain>
various purposes, including spam filtering, anti-spoofing and logging. When
possible, it is often wise to masquerade the client's IP address when
connecting to the server using the "usesrc" argument of the "source" keyword,
which requires the cttproxy feature to be compiled in.
which requires the transparent proxy feature to be compiled in.
Example :
option smtpchk HELO mydomain.org
@ -6973,13 +6973,6 @@ source <addr>[:<port>] [interface <name>]
connection tracking on the machine will not be upset by the reuse of the
same session.
Note that depending on the transparent proxy technology used, it may be
required to force the source address. In fact, cttproxy version 2 requires an
IP address in <addr> above, and does not support setting of "0.0.0.0" as the
IP address because it creates NAT entries which much match the exact outgoing
address. Tproxy version 4 and some other kernel patches which work in pure
forwarding mode generally will not have this limitation.
This option sets the default source for all servers in the backend. It may
also be specified in a "defaults" section. Finer source address specification
is possible at the server level using the "source" server option. Refer to

View File

@ -1,101 +0,0 @@
Nécessite CAP_NET_ADMIN (12)
On peut donc aussi mettre CAP_NET_BIND_SERVICE (10) pour autoriser les ports < 1024
charger le module :
# modprobe ip_conntrack hashsize=65536
# modprobe iptable_tproxy hashsize=65536
# echo 15 > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_timeout_time_wait
# echo 30 > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_timeout_fin_wait
Si on utilise "usesrc client", alors on rencontre ce problème en cas
de réutilisation d'un port :
# dmesg
IP_TPROXY: error applying NAT mapping, hooknum=4 0103000a:e5a2 -> 05000001:d204
IP_TPROXY: error applying NAT mapping, hooknum=4 0103000a:e5a2 -> 05000001:d204
Solution retenue pour la configuration :
You have to write "usesrc XXXX" on the "source" line. "XXXX" is either
an IP address or the keyword "clientip" to reuse the client's IP with
a dynamically allocated port, or "client" to reuse both the client's IP
and port (dangerous). But due to the way cttproxy works, the source address
is mandatory. Eg:
backend static
source 192.168.1.254 usesrc clientip
server static1 192.168.1.10 source 192.168.1.254 usesrc clientip
---- Anciennes réflexions ----
Il faudrait donc peut-être toujours avoir un port dynamique, ou bien
traiter le TIME_WAIT correctement en appliquant natdel => corrige pratiquement
toujours le problème (mais réduire les timeouts semble important)
source 10.1.2.3 present 10.2.3.4
source 10.1.2.3 present same_ip
source 10.1.2.3 present same
source 10.1.2.3:5000 present same
source 10.1.2.3 appear_as 10.2.3.4
source 10.1.2.3 appear_as same_ip
source 10.1.2.3 appear_as same
source 10.1.2.3:5000 appear_as same
source 10.1.2.3 {keepsrc | keepip | usesrc 1.2.3.4}
source 10.1.2.3 snat { client | clientip | 1.2.3.4 }
source 10.1.2.3 extbind same
source 10.1.2.3 intercept same
source 10.1.2.3 spoof same
source 10.1.2.3 showsrc same
source 10.1.2.3 usesrc same
source 10.1.2.3 setsrc same
source 10.1.2.3 withsrc same
source 10.1.2.3 usesrc clientip:sameport
source 10.1.2.3 alias same
source 10.1.2.3 as same
source 10.1.2.3 outgoing same
source 10.1.2.3 public same
source 10.1.2.3:5000 pretend same
source 10.1.2.3=same
source 10.1.2.3=10.2.3.4
source 10.1.2.3^same
source 10.1.2.3^10.2.3.4
source 10.1.2.3@same
source 10.1.2.3@10.2.3.4
source 10.1.2.3!same
source 10.1.2.3!10.2.3.4
source 10.1.2.3|same
source 10.1.2.3|10.2.3.4
source 10.1.2.3(same)
source 10.1.2.3(10.2.3.4)
source 10.1.2.3~same
source 10.1.2.3~10.2.3.4
A l'inverse, si "source" contient l'adresse vue :
source same bindto 1.2.3.4
source 2.3.4.5 bindto 1.2.3.4
Problème: si "bindto" est oublié, le bind sur 2.3.4.5 ne fonctionnera pas.
Pour l'adresse de listen (avec "bind"), il serait bien que l'adresse
translatée apparaisse au même niveau que l'IP afin que les plages et
listes continuent de fonctionner par association.
Différences entre source et bind :
- source: 1 seule IP source, éventuellement un port, plus tard une plage
- bind : liste de (IP source facultatives, port obligatoire, parfois une plage)

View File

@ -1,5 +0,0 @@
- check TPROXY_VERSION if lstchk_tproxy
- check capabilities for CAP_NET_ADMIN if lstchk_tproxy
- add capabilities support to the global conf (cap_bind_service)
- add support for non-local listen address

View File

@ -1,77 +0,0 @@
/*
* Transparent proxy support for Linux/iptables
*
* Copyright (c) 2002-2004 BalaBit IT Ltd.
* Author: Balázs Scheidler
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#ifndef _IP_TPROXY_H
#define _IP_TPROXY_H
#ifdef __KERNEL__
#include <linux/types.h>
#include <linux/in.h>
#else
#include <netinet/in.h>
#ifndef IP_RECVORIGADDRS
#define IP_RECVORIGADDRS 11273
#define IP_ORIGADDRS IP_RECVORIGADDRS
struct in_origaddrs {
struct in_addr ioa_srcaddr;
struct in_addr ioa_dstaddr;
unsigned short int ioa_srcport;
unsigned short int ioa_dstport;
};
#endif
#endif
/*
* used in setsockopt(SOL_IP, IP_TPROXY) should not collide
* with values in <linux/in.h>
*/
#define IP_TPROXY 11274
/* tproxy operations */
enum {
TPROXY_VERSION = 0,
TPROXY_ASSIGN,
TPROXY_UNASSIGN,
TPROXY_QUERY,
TPROXY_FLAGS,
TPROXY_ALLOC,
TPROXY_CONNECT
};
/* bitfields in IP_TPROXY_FLAGS */
#define ITP_CONNECT 0x00000001
#define ITP_LISTEN 0x00000002
#define ITP_ESTABLISHED 0x00000004
#define ITP_ONCE 0x00010000
#define ITP_MARK 0x00020000
#define ITP_APPLIED 0x00040000
#define ITP_UNIDIR 0x00080000
struct in_tproxy_addr{
struct in_addr faddr;
u_int16_t fport;
};
struct in_tproxy {
/* fixed part, should not change between versions */
u_int32_t op;
/* extensible part */
union _in_args {
u_int32_t version;
struct in_tproxy_addr addr;
u_int32_t flags;
} v;
};
#endif

View File

@ -1,47 +0,0 @@
/*
include/proto/cttproxy.h
This file contains prototypes for Linux's cttproxy interface.
This file should be included only if CTTPROXY is enabled.
Copyright (C) 2000-2007 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
License as published by the Free Software Foundation, version 2.1
exclusively.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _PROTO_CTTPROXY_H
#define _PROTO_CTTPROXY_H
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <common/config.h>
#include <import/ip_tproxy.h>
/*
* Checks that CTTPROXY is available and in the right version.
* Returns 0 if OK, -1 if wrong version, -2 if not available or other error.
*/
int check_cttproxy_version();
#endif /* _PROTO_CTTPROXY_H */
/*
* Local variables:
* c-indent-level: 8
* c-basic-offset: 8
* End:
*/

View File

@ -231,7 +231,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_TRANSPARENT)
#if 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 */

View File

@ -52,8 +52,7 @@
/* list of last checks to perform, depending on config options */
#define LSTCHK_CAP_BIND 0x00000001 /* check that we can bind to any port */
#define LSTCHK_CTTPROXY 0x00000002 /* check that tproxy is enabled */
#define LSTCHK_NETADM 0x00000004 /* check that we have CAP_NET_ADMIN */
#define LSTCHK_NETADM 0x00000002 /* check that we have CAP_NET_ADMIN */
/* Global tuning options */
/* available polling mechanisms */

View File

@ -953,7 +953,7 @@ int assign_server_and_queue(struct stream *s)
*/
static void assign_tproxy_address(struct stream *s)
{
#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
#if defined(CONFIG_HAP_TRANSPARENT)
struct server *srv = objt_server(s->target);
struct conn_src *src;
struct connection *cli_conn;

View File

@ -2630,7 +2630,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_TRANSPARENT)
#if defined(CONFIG_HAP_TRANSPARENT)
curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
#endif
}
@ -5898,15 +5898,7 @@ stats_error_parsing:
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_TRANSPARENT)
#if !defined(CONFIG_HAP_TRANSPARENT)
if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
file, linenum, "usesrc");
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
#endif
#if defined(CONFIG_HAP_TRANSPARENT)
if (!*args[cur_arg + 1]) {
Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
file, linenum, "usesrc");
@ -5988,9 +5980,6 @@ stats_error_parsing:
curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
}
global.last_checks |= LSTCHK_NETADM;
#if !defined(CONFIG_HAP_TRANSPARENT)
global.last_checks |= LSTCHK_CTTPROXY;
#endif
#else /* no TPROXY support */
Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
file, linenum, "usesrc");
@ -8176,7 +8165,7 @@ out_uri_auth_compat:
}
}
#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
#if 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",
@ -8209,7 +8198,7 @@ out_uri_auth_compat:
err_code |= ERR_WARN;
}
#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
#if 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",

View File

@ -1,65 +0,0 @@
/*
* Functions for managing transparent proxying with CTTPROXY.
* This file should be compiled only if CTTPROXY is enabled.
*
* Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <common/compat.h>
#include <common/config.h>
#include <common/time.h>
#include <import/ip_tproxy.h>
/*
* Checks that CTTPROXY is available and in the right version.
* Returns 0 if OK, -1 if wrong version, -2 if not available or other error.
*/
int check_cttproxy_version() {
struct in_tproxy itp1;
int fd, ret;
memset(&itp1, 0, sizeof(itp1));
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1)
return -2;
itp1.op = TPROXY_VERSION;
itp1.v.version = 0x02000000; /* CTTPROXY version 2.0 expected */
ret = 0;
if (setsockopt(fd, SOL_IP, IP_TPROXY, &itp1, sizeof(itp1)) == -1) {
if (errno == -EINVAL)
ret = -1; /* wrong version */
else
ret = -2; /* not supported or other error */
}
close(fd);
return ret;
}
/*
* Local variables:
* c-indent-level: 8
* c-basic-offset: 8
* End:
*/

View File

@ -102,10 +102,6 @@
#include <proto/task.h>
#include <proto/dns.h>
#ifdef CONFIG_HAP_CTTPROXY
#include <proto/cttproxy.h>
#endif
#ifdef USE_OPENSSL
#include <proto/ssl_sock.h>
#endif
@ -368,11 +364,8 @@ void display_build_opts()
printf("Built without Lua support\n");
#endif
#if defined(CONFIG_HAP_TRANSPARENT) || defined(CONFIG_HAP_CTTPROXY)
#if defined(CONFIG_HAP_TRANSPARENT)
printf("Built with transparent proxy support using:"
#if defined(CONFIG_HAP_CTTPROXY)
" CTTPROXY"
#endif
#if defined(IP_TRANSPARENT)
" IP_TRANSPARENT"
#endif
@ -1697,22 +1690,6 @@ int main(int argc, char **argv)
}
}
#ifdef CONFIG_HAP_CTTPROXY
if (global.last_checks & LSTCHK_CTTPROXY) {
int ret;
ret = check_cttproxy_version();
if (ret < 0) {
Alert("[%s.main()] Cannot enable cttproxy.\n%s",
argv[0],
(ret == -1) ? " Incorrect module version.\n"
: " Make sure you have enough permissions and that the module is loaded.\n");
protocol_unbind_all();
exit(1);
}
}
#endif
if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
"", argv[0]);

View File

@ -57,10 +57,6 @@
#include <proto/stream_interface.h>
#include <proto/task.h>
#ifdef CONFIG_HAP_CTTPROXY
#include <import/ip_tproxy.h>
#endif
static int tcp_bind_listeners(struct protocol *proto, char *errmsg, int errlen);
static int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen);
@ -160,7 +156,6 @@ static struct action_kw *tcp_res_cont_action(const char *kw)
*
* The function supports multiple foreign binding methods :
* - linux_tproxy: we directly bind to the foreign address
* - cttproxy: we bind to a local address then nat.
* The second one can be used as a fallback for the first one.
* This function returns 0 when everything's OK, 1 if it could not bind, to the
* local address, 2 if it could not bind to the foreign address.
@ -263,25 +258,6 @@ int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct so
if (!flags)
return 0;
#ifdef CONFIG_HAP_CTTPROXY
if (!foreign_ok && remote->ss_family == AF_INET) {
struct in_tproxy itp1, itp2;
memset(&itp1, 0, sizeof(itp1));
itp1.op = TPROXY_ASSIGN;
itp1.v.addr.faddr = ((struct sockaddr_in *)&bind_addr)->sin_addr;
itp1.v.addr.fport = ((struct sockaddr_in *)&bind_addr)->sin_port;
/* set connect flag on socket */
itp2.op = TPROXY_FLAGS;
itp2.v.flags = ITP_CONNECT | ITP_ONCE;
if (setsockopt(fd, SOL_IP, IP_TPROXY, &itp1, sizeof(itp1)) != -1 &&
setsockopt(fd, SOL_IP, IP_TPROXY, &itp2, sizeof(itp2)) != -1) {
foreign_ok = 1;
}
}
#endif
if (!foreign_ok)
/* we could not bind to a foreign address */
return 2;

View File

@ -1441,15 +1441,7 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
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_TRANSPARENT)
#if !defined(CONFIG_HAP_TRANSPARENT)
if (!is_inet_addr(&newsrv->conn_src.source_addr)) {
Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
file, linenum, "usesrc", "source");
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
#endif
#if defined(CONFIG_HAP_TRANSPARENT)
if (!*args[cur_arg + 1]) {
Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
file, linenum, "usesrc");
@ -1531,9 +1523,6 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
}
global.last_checks |= LSTCHK_NETADM;
#if !defined(CONFIG_HAP_TRANSPARENT)
global.last_checks |= LSTCHK_CTTPROXY;
#endif
cur_arg += 2;
continue;
#else /* no TPROXY support */
@ -1541,7 +1530,7 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
file, linenum, "usesrc");
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
#endif /* defined(CONFIG_HAP_TRANSPARENT) */
} /* "usesrc" */
if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */