# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: squid3@treenet.co.nz-20080331104554-n0bgvxboeo99ej0u
# target_branch: file:///src/squid/bzr/trunk/
# testament_sha1: c15fc2a03b9d847977021f33bf29cb22a5821752
# timestamp: 2008-04-01 12:16:41 +1200
# base_revision_id: henrik@henriknordstrom.net-20080328204641-\
# so853tluhwlx6qc5
#
# Begin patch
=== modified file 'configure.in'
--- configure.in 2008-03-18 11:58:16 +0000
+++ configure.in 2008-03-26 11:49:34 +0000
@@ -1219,13 +1219,26 @@
fi
dnl Enable Linux transparent proxy support
-AC_ARG_ENABLE(linux-tproxy,
-[ --enable-linux-tproxy
- Enable real Transparent Proxy support for Netfilter TPROXY.],
-[ if test "$enableval" = "yes" ; then
- echo "Linux Netfilter/TPROXY enabled"
- AC_DEFINE(LINUX_TPROXY, 1, [Enable real Transparent Proxy support for Netfilter TPROXY.])
- LINUX_TPROXY="yes"
+AC_ARG_ENABLE(linux-tproxy2,
+[ --enable-linux-tproxy2
+ Enable real Transparent Proxy support for Netfilter TPROXY (version 2).],
+[ if test "$enableval" = "yes" ; then
+ echo "Linux Netfilter/TPROXY v2 enabled"
+ AC_DEFINE(LINUX_TPROXY2, 1, [Enable real Transparent Proxy support for Netfilter TPROXY v2.])
+ LINUX_TPROXY2="yes"
+ if test -z "$LINUX_NETFILTER"; then
+ echo "Linux-Netfilter Transparent Proxy automatically enabled"
+ LINUX_NETFILTER="yes"
+ fi
+ fi
+])
+AC_ARG_ENABLE(linux-tproxy4,
+[ --enable-linux-tproxy4
+ Enable real Transparent Proxy support for Netfilter TPROXY (version 4+).],
+[ if test "$enableval" = "yes" ; then
+ echo "Linux Netfilter/TPROXY v4 enabled"
+ AC_DEFINE(LINUX_TPROXY4, 1, [Enable real Transparent Proxy support for Netfilter TPROXY v4.])
+ LINUX_TPROXY4="yes"
if test -z "$LINUX_NETFILTER"; then
echo "Linux-Netfilter Transparent Proxy automatically enabled"
LINUX_NETFILTER="yes"
@@ -2882,25 +2895,26 @@
sleep 10
fi
-dnl Linux Netfilter/TPROXY support requires some specific header files
+dnl Linux Netfilter/TPROXYv2 support requires some specific header files
dnl Shamelessly copied from shamelessly copied from above
-if test "$LINUX_TPROXY" ; then
- AC_MSG_CHECKING(if TPROXY header files are installed)
+if test "$LINUX_TPROXY2" ; then
+ AC_MSG_CHECKING(if TPROXYv2 header files are installed)
# hold on to your hats...
if test "$ac_cv_header_linux_netfilter_ipv4_ip_tproxy_h" = "yes" && test "$LINUX_NETFILTER" = "yes"; then
- LINUX_TPROXY="yes"
- AC_DEFINE(LINUX_TPROXY, 1, [Enable real Transparent Proxy support for Netfilter TPROXY.])
+ LINUX_TPROXY2="yes"
+ AC_DEFINE(LINUX_TPROXY2, 1, [Enable real Transparent Proxy support for Netfilter TPROXY v2.])
else
- LINUX_TPROXY="no"
- AC_DEFINE(LINUX_TPROXY, 0, [Enable real Transparent Proxy support for Netfilter TPROXY.])
- fi
- AC_MSG_RESULT($LINUX_TPROXY)
-fi
-if test "$LINUX_TPROXY" = "no" && test "$LINUX_NETFILTER" = "yes"; then
- echo "WARNING: Cannot find TPROXY headers, you need to install the"
- echo "tproxy package from:"
- echo " - lynx http://www.balabit.com/downloads/tproxy/"
- sleep 10
+ LINUX_TPROXY2="no"
+ AC_DEFINE(LINUX_TPROXY2, 0, [Enable real Transparent Proxy support for Netfilter TPROXY v2.])
+ fi
+ AC_MSG_RESULT($LINUX_TPROXY2)
+ if test "$LINUX_TPROXY2" = "no" && test "$LINUX_NETFILTER" = "yes"; then
+ echo "WARNING: Cannot find TPROXY v2 headers, you need to install the"
+ echo "tproxy package from:"
+ echo " - lynx http://www.balabit.com/downloads/tproxy/"
+ echo "Or select the '--enable-linux-tproxy4' option instead."
+ sleep 10
+ fi
fi
if test -z "$USE_GNUREGEX" ; then
=== modified file 'doc/release-notes/release-3.1.sgml'
--- doc/release-notes/release-3.1.sgml 2008-01-17 17:09:05 +0000
+++ doc/release-notes/release-3.1.sgml 2008-03-29 11:23:47 +0000
@@ -298,6 +298,16 @@
but please report the bugs anyway.
+ --enable-linux-tproxy2
+ New option to enable TPROXY version 2 support in squid (previously known as --enable-linux-tproxy).
+ Linux Kernel patches from Balabit are required before building squid with this option.
+
+
+ --enable-linux-tproxy4
+ New option to enable TPROXY version 4+ support in squid.
+ This options requires a linux kernel 2.6.25 or later for embeded netfilter TPROXY targets.
+
+
@@ -308,7 +318,7 @@
--disable-internl-dns
Better support for Linux using the external DNS helper.
The helper will compile and work with dns_nameservers on more variants of Linux than previously.
-
+
@@ -334,6 +344,8 @@
The following configure options have been removed.
+ --enable-linux-tproxy
+ Replaced by --enable-linux-tproxy2 to make way for differences in TPROXY v2 and v4 support.
=== modified file 'include/autoconf.h.in'
--- include/autoconf.h.in 2008-02-17 16:24:48 +0000
+++ include/autoconf.h.in 2008-03-26 11:49:34 +0000
@@ -792,8 +792,11 @@
/* Enable support for Transparent Proxy on Linux (Netfilter) systems */
#undef LINUX_NETFILTER
-/* Enable real Transparent Proxy support for Netfilter TPROXY. */
-#undef LINUX_TPROXY
+/* Enable real Transparent Proxy support for Netfilter TPROXY v2. */
+#undef LINUX_TPROXY2
+
+/* Enable real Transparent Proxy support for Netfilter TPROXY v4. */
+#undef LINUX_TPROXY4
/* If we need to declare sys_errlist[] as external */
#undef NEED_SYS_ERRLIST
=== modified file 'src/IPInterception.cc'
--- src/IPInterception.cc 2008-02-06 05:38:24 +0000
+++ src/IPInterception.cc 2008-03-26 11:49:34 +0000
@@ -1,4 +1,3 @@
-
/*
* $Id: IPInterception.cc,v 1.20 2008/02/05 22:38:24 amosjeffries Exp $
*
@@ -88,11 +87,12 @@
#include
#endif
-#if IPF_TRANSPARENT
int
-
clientNatLookup(int fd, const IPAddress &me, const IPAddress &peer, IPAddress &dst)
{
+
+#if IPF_TRANSPARENT /* --enable-ipf-transparent */
+
dst = me;
if( !me.IsIPv4() ) return -1;
if( !peer.IsIPv4() ) return -1;
@@ -198,12 +198,11 @@
return 0;
}
-}
-
-#elif LINUX_NETFILTER
-int
-clientNatLookup(int fd, const IPAddress &me, const IPAddress &peer, IPAddress &dst)
-{
+
+
+
+#elif LINUX_NETFILTER || LINUX_TPROXY4 /* --enable-linux-netfilter OR --enable-linux-tproxy4 */
+
dst = me;
if( !me.IsIPv4() ) return -1;
if( !peer.IsIPv4() ) return -1;
@@ -213,12 +212,16 @@
dst.GetAddrInfo(lookup,AF_INET);
+#if LINUX_NETFILTER
if (getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, lookup->ai_addr, &lookup->ai_addrlen) != 0)
+#elif LINUX_TPROXY4
+ if (getsockopt(fd, SOL_IP, IP_TRANSPARENT, lookup->ai_addr, &lookup->ai_addrlen) != 0)
+#endif
{
dst.FreeAddrInfo(lookup);
if (squid_curtime - last_reported > 60) {
- debugs(89, 1, "clientNatLookup: peer " << peer << " NF getsockopt(SO_ORIGINAL_DST) failed: " << xstrerror());
+ debugs(89, 1, "clientNatLookup: peer " << peer << " NF getsockopt(" << (LINUX_NETFILTER?"SO_ORIGINAL_DST":"IP_TRANSPARENT") << ") failed: " << xstrerror());
last_reported = squid_curtime;
}
@@ -234,13 +237,9 @@
return 0;
else
return -1;
-}
-
-#elif PF_TRANSPARENT
-int
-
-clientNatLookup(int fd, const IPAddress &me, const IPAddress &peer, IPAddress dst)
-{
+
+
+#elif PF_TRANSPARENT /* --enable-pf-transparent */
struct pfioc_natlook nl;
static int pffd = -1;
@@ -300,12 +299,10 @@
else
return -1;
}
-}
-
-#elif IPFW_TRANSPARENT
-int
-clientNatLookup(int fd, const IPAddress &me, const IPAddress &peer, IPAddress &dst)
-{
+
+
+#elif IPFW_TRANSPARENT /* --enable-ipfw-transparent */
+
int ret;
struct addrinfo *lookup = NULL;
@@ -330,14 +327,13 @@
dst.FreeAddrInfo(lookup);
return 0;
-}
-
-#else
-int
-clientNatLookup(int fd, const IPAddress &me, const IPAddress &peer, IPAddress &dst)
-{
+
+
+#else /* none of the transparent options configured */
+
debugs(89, 1, "WARNING: transparent proxying not supported");
return -1;
+
+#endif
+
}
-#endif
-
=== modified file 'src/IPInterception.h'
--- src/IPInterception.h 2007-12-15 06:11:41 +0000
+++ src/IPInterception.h 2008-03-26 11:49:34 +0000
@@ -1,4 +1,3 @@
-
/*
* $Id: IPInterception.h,v 1.7 2007/12/14 23:11:45 amosjeffries Exp $
*
@@ -30,13 +29,15 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
*/
-
#ifndef SQUID_IPINTERCEPTION_H
#define SQUID_IPINTERCEPTION_H
#include "IPAddress.h"
-SQUIDCEXTERN int
-clientNatLookup(int fd, const IPAddress &me, const IPAddress &peer, IPAddress &dst);
+#if LINUX_TPROXY4 && !defined(IP_TRANSPARENT)
+#define IP_TRANSPARENT 19
+#endif
+
+SQUIDCEXTERN int clientNatLookup(int fd, const IPAddress &me, const IPAddress &peer, IPAddress &dst);
#endif /* SQUID_IPINTERCEPTION_H */
=== modified file 'src/ProtoPort.h'
--- src/ProtoPort.h 2008-03-16 21:48:45 +0000
+++ src/ProtoPort.h 2008-03-26 11:49:34 +0000
@@ -31,7 +31,8 @@
int vport; /* virtual port support, -1 for dynamic, >0 static*/
int disable_pmtu_discovery;
-#if LINUX_TPROXY
+
+#if LINUX_TPROXY2 || LINUX_TPROXY4
unsigned int tproxy:1; /* spoof client ip using tproxy */
#endif
=== modified file 'src/cache_cf.cc'
--- src/cache_cf.cc 2008-03-20 23:20:58 +0000
+++ src/cache_cf.cc 2008-03-31 10:45:54 +0000
@@ -1,4 +1,3 @@
-
/*
* $Id: cache_cf.cc,v 1.544 2008/03/04 12:00:36 amosjeffries Exp $
*
@@ -2928,10 +2927,11 @@
else
self_destruct();
-#if LINUX_TPROXY
+#if LINUX_TPROXY2 || LINUX_TPROXY4
} else if (strcmp(token, "tproxy") == 0) {
s->tproxy = 1;
+ s->transparent = 1;
need_linux_tproxy = 1;
#if USE_IPV6
/* INET6: until transparent REDIRECT works on IPv6 SOCKET, force wildcard to IPv4 */
@@ -2941,6 +2941,7 @@
}
#endif
#endif
+
} else if (strcmp(token, "ipv4") == 0) {
#if USE_IPV6
if( !s->s.SetIPv4() ) {
=== modified file 'src/client_side.cc'
--- src/client_side.cc 2008-03-16 21:48:45 +0000
+++ src/client_side.cc 2008-03-26 11:49:34 +0000
@@ -2213,8 +2213,7 @@
request->flags.transparent = http->flags.transparent;
-#if LINUX_TPROXY
-
+#if LINUX_TPROXY2 || LINUX_TPROXY4
request->flags.tproxy = conn->port->tproxy && need_linux_tproxy;
#endif
@@ -3118,6 +3117,13 @@
if (fd < 0)
continue;
+#if LINUX_TPROXY4
+ /* because the transparent/non-transparent port info is only known here.
+ * we have to set the IP_TRANSPARENT option here. */
+ if(s->transparent)
+ comm_set_transparent(fd,0);
+#endif
+
comm_listen(fd);
comm_accept(fd, httpAccept, s);
=== modified file 'src/comm.cc'
--- src/comm.cc 2008-03-25 15:40:36 +0000
+++ src/comm.cc 2008-03-31 10:45:54 +0000
@@ -48,6 +48,7 @@
#include "SquidTime.h"
#include "CommCalls.h"
#include "IPAddress.h"
+#include "IPInterception.h"
#if defined(_SQUID_CYGWIN_)
#include
@@ -627,6 +628,23 @@
#endif /* sockopt */
}
+void
+comm_set_transparent(int fd)
+{
+#if LINUX_TPROXY4
+ int tos = 1;
+ if (setsockopt(fd, SOL_IP, IP_TRANSPARENT, (char *) &tos, sizeof(int)) < 0) {
+ debugs(50, DBG_IMPORTANT, "comm_open: setsockopt(IP_TRANSPARENT) on FD " << fd << ": " << xstrerror());
+ }
+ else {
+ /* mark the socket as having transparent options */
+ fd_table[fd].flags.transparent = 1;
+ }
+#else
+ debugs(50, DBG_CRITICAL, "WARNING: comm_open: setsockopt(IP_TRANSPARENT) not supported on this platform");
+#endif /* sockopt */
+}
+
/**
* Create a socket. Default is blocking, stream (TCP) socket. IO_TYPE
* is OR of flags specified in defines.h:COMM_*
@@ -1307,6 +1325,14 @@
commSetNonBlocking(sock);
+#if LINUX_TPROXY4
+ /* AYJ: do we need to set this again on every accept? */
+ if(fd_table[fd].flags.transparent == 1) {
+ comm_set_transparent(sock, 0);
+ F->flags.transparent = 1;
+ }
+#endif
+
PROF_stop(comm_accept);
return sock;
}
=== modified file 'src/comm.h'
--- src/comm.h 2008-02-13 05:58:29 +0000
+++ src/comm.h 2008-03-26 12:02:56 +0000
@@ -56,6 +56,11 @@
SQUIDCEXTERN u_short comm_local_port(int fd);
SQUIDCEXTERN int comm_set_tos(int fd, int tos);
+/**
+ * Set the socket IP_TRANSPARENT option for Linux TPROXY v4 support.
+ */
+SQUIDCEXTERN void comm_set_transparent(int fd, int tos);
+
SQUIDCEXTERN void commSetSelect(int, unsigned int, PF *, void *, time_t);
SQUIDCEXTERN void commResetSelect(int);
=== modified file 'src/fde.h'
--- src/fde.h 2008-02-13 06:22:13 +0000
+++ src/fde.h 2008-03-31 04:01:31 +0000
@@ -82,6 +82,9 @@
unsigned int close_on_exec:1;
unsigned int read_pending:1;
unsigned int write_pending:1;
+#if LINUX_TPROXY4
+ unsigned int transparent:1;
+#endif
} flags;
int64_t bytes_read;
=== modified file 'src/forward.cc'
--- src/forward.cc 2008-03-16 21:48:45 +0000
+++ src/forward.cc 2008-03-26 11:49:34 +0000
@@ -49,8 +49,12 @@
#include "SquidTime.h"
#include "Store.h"
-#if LINUX_TPROXY
+#if LINUX_TPROXY2
+#ifdef HAVE_LINUX_NETFILTER_IPV4_IP_TPROXY_H
#include
+#else
+#error " TPROXY v2 Header file missing: linux/netfilter_ipv4/ip_tproxy.h. Perhapse you meant to use TPROXY v4 ? "
+#endif
#endif
static PSC fwdStartCompleteWrapper;
=== modified file 'src/forward.h'
--- src/forward.h 2008-03-16 22:10:18 +0000
+++ src/forward.h 2008-03-26 11:49:34 +0000
@@ -99,7 +99,7 @@
unsigned int ftp_pasv_failed:1;
unsigned int forward_completed:1;
} flags;
-#if LINUX_NETFILTER
+#if LINUX_NETFILTER || LINUX_TPROXY2 || LINUX_TPROXY4
IPAddress src;
#endif
=== modified file 'src/globals.h'
--- src/globals.h 2008-03-20 11:30:19 +0000
+++ src/globals.h 2008-03-26 11:49:34 +0000
@@ -185,7 +185,7 @@
extern const char *external_acl_message; /* NULL */
extern int opt_send_signal; /* -1 */
extern int opt_no_daemon; /* 0 */
-#if LINUX_TPROXY
+#if LINUX_TPROXY2 || LINUX_TPROXY4
extern int need_linux_tproxy; /* 0 */
#endif
=== modified file 'src/http.cc'
--- src/http.cc 2008-02-13 06:55:26 +0000
+++ src/http.cc 2008-03-26 11:49:34 +0000
@@ -1229,7 +1229,8 @@
comm_remove_close_handler(fd, closeHandler);
closeHandler = NULL;
fwd->unregister(fd);
-#if LINUX_TPROXY
+
+#if LINUX_TPROXY2 || LINUX_TPROXY4
if (orig_request->flags.tproxy)
client_addr = orig_request->client_addr;
=== modified file 'src/structs.h'
--- src/structs.h 2008-03-20 23:20:58 +0000
+++ src/structs.h 2008-03-26 11:49:34 +0000
@@ -1029,7 +1029,7 @@
#if HTTP_VIOLATIONS
nocache_hack = 0;
#endif
-#if LINUX_TPROXY
+#if LINUX_TPROXY2 || LINUX_TPROXY4
tproxy = 0;
#endif
}
@@ -1051,7 +1051,7 @@
#endif
unsigned int accelerated:1;
unsigned int transparent:1;
-#if LINUX_TPROXY
+#if LINUX_TPROXY2 || LINUX_TPROXY4
unsigned int tproxy:1; /* spoof client ip using tproxy */
#endif
unsigned int internal:1;
=== modified file 'src/tools.cc'
--- src/tools.cc 2008-03-20 23:20:58 +0000
+++ src/tools.cc 2008-03-26 11:49:34 +0000
@@ -1236,7 +1236,7 @@
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
/* Silent failure unless TPROXY is required. Maybe not started as root */
-#if LINUX_TPROXY
+#if LINUX_TPROXY2 || LINUX_TPROXY4
if (need_linux_tproxy)
debugs(1, 1, "Error - tproxy support requires capability setting which has failed. Continuing without tproxy support");
@@ -1246,7 +1246,6 @@
#endif
}
-
#endif
}
@@ -1273,10 +1272,13 @@
cap->inheritable = 0;
cap->effective = (1 << CAP_NET_BIND_SERVICE);
-#if LINUX_TPROXY
+#if LINUX_TPROXY2
if (need_linux_tproxy)
cap->effective |= (1 << CAP_NET_ADMIN) | (1 << CAP_NET_BROADCAST);
+#elif LINUX_TPROXY4
+ if (need_linux_tproxy)
+ cap->effective |= (1 << CAP_NET_ADMIN);
#endif
@@ -1285,7 +1287,7 @@
if (capset(head, cap) != 0) {
/* Silent failure unless TPROXY is required */
-#if LINUX_TPROXY
+#if LINUX_TPROXY2 || LINUX_TPROXY4
if (need_linux_tproxy)
debugs(50, 1, "Error enabling needed capabilities. Will continue without tproxy support");
@@ -1299,14 +1301,14 @@
nocap:
xfree(head);
xfree(cap);
-#else
-#if LINUX_TPROXY
+#else /* not defined(_SQUID_LINUX_) && HAVE_SYS_CAPABILITY_H */
+
+#if LINUX_TPROXY2 || LINUX_TPROXY4
if (need_linux_tproxy)
debugs(50, 1, "Missing needed capability support. Will continue without tproxy support");
need_linux_tproxy = 0;
-
#endif
#endif
# Begin bundle
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
apcA