Hi Henrik, Amos, etc I've been trying to compile Squid-2.7.STABLE8 (squid-2.HEAD-20100222) but am having difficulty applying the Visolve TProxy-4 patch * http://www.visolve.com/squid/squid-tproxy.php The patch no longer applies cleanly. I spent some time trying to resolve the conflicts, and after successful compilation, Squid is listening on its port, but also complains to cachelog as follows and it's not spoofing the source IP: {{{ Accepting proxy HTTP connections at 192.168.251.106, port 800, FD 27. ... commBind: Cannot bind socket FD 31 to 192.168.251.106:800: (98) Address already in use }}} I'm compiling on an Ubuntu 9.10 machine with Linux kernel 2.6.31-19-generic and Linux headers packages installed {{{ aptitude search ~ilinux-headers i linux-headers-2.6.31-19 - Header files related to Linux kernel version 2.6.31 i linux-headers-2.6.31-19-generic - Linux kernel headers for version 2.6.31 on x86/x86_64 i A linux-headers-generic - Generic Linux kernel headers }}} I'm deploying this on a Slackware based box with custom Linux Kernel 2.6.31.6 (TProxy module enabled) {{{ cachebox# dmesg | grep -i tproxy NF_TPROXY: Transparent proxy support initialized, version 4.1.0 NF_TPROXY: Copyright (c) 2006-2007 BalaBit IT Ltd. }}} I think the problem might be caused by this recent patch to the libcap code, particularly - around tools.c: * http://www.squid-cache.org/Versions/v2/HEAD/changesets/12640.patch It looked like the changes to tools.c that had previously been applied by the Tproxy patch are now part of the 2.7 tree, but re-factored slightly. Then again I may be totally off the mark :) I've attached my latest version of the patch in which I rejected all the Tproxy changes to tools.c. Has anyone already prepared a more up to date version of the Tproxy patch? If not, I'd like to help fix the patch, but perhaps someone can quickly summarise what might be the problem and what needs doing. -RichardW.
Index: configure =================================================================== --- configure (revision 9786) +++ configure (working copy) @@ -9554,7 +9554,6 @@ grp.h \ libc.h \ linux/netfilter_ipv4.h \ - linux/netfilter_ipv4/ip_tproxy.h \ malloc.h \ math.h \ memory.h \ @@ -29104,10 +29103,10 @@ fi if test "$LINUX_TPROXY"; then - { $as_echo "$as_me:$LINENO: checking if TPROXY header files are installed" >&5 -$as_echo_n "checking if TPROXY header files are installed... " >&6; } + { echo "$as_me:$LINENO: checking if sys/capability header files are installed" >&5 +echo $ECHO_N "checking if sys/capability header files are installed... $ECHO_C" >&6; } # hold on to your hats... - if test "$ac_cv_header_linux_netfilter_ipv4_ip_tproxy_h" = "yes" && test "$LINUX_NETFILTER" = "yes"; then + if test "$ac_cv_header_sys_capability_h" = "yes" && test "$LINUX_NETFILTER" = "yes"; then LINUX_TPROXY="yes" cat >>confdefs.h <<\_ACEOF @@ -29122,8 +29121,12 @@ _ACEOF fi - { $as_echo "$as_me:$LINENO: result: $LINUX_TPROXY" >&5 -$as_echo "$LINUX_TPROXY" >&6; } + { echo "$as_me:$LINENO: result: $LINUX_TPROXY" >&5 +echo "${ECHO_T}$LINUX_TPROXY" >&6; } + + if test "$LINUX_TPROXY" = "no" ; then + echo "WARNING: Cannot find necessary system capability headers files" + echo " Linux TProxy-4 support WILL NOT be enabled" if test "$use_libcap" != "yes"; then { $as_echo "$as_me:$LINENO: WARNING: Missing needed capabilities (libcap or libcap2) for TPROXY" >&5 $as_echo "$as_me: WARNING: Missing needed capabilities (libcap or libcap2) for TPROXY" >&2;} @@ -29131,11 +29134,6 @@ sleep 10 fi fi -if test "$LINUX_TPROXY" = "no" && test "$LINUX_NETFILTER" = "yes"; then - echo "WARNING: Cannot find TPROXY headers, you need to patch your kernel with the" - echo "tproxy package from:" - echo " - lynx http://www.balabit.com/downloads/files/tproxy/" - sleep 10 fi if test -z "$USE_GNUREGEX" ; then Index: configure.in =================================================================== --- configure.in (revision 9786) +++ configure.in (working copy) @@ -1802,7 +1802,6 @@ grp.h \ libc.h \ linux/netfilter_ipv4.h \ - linux/netfilter_ipv4/ip_tproxy.h \ malloc.h \ math.h \ memory.h \ @@ -2946,9 +2945,9 @@ dnl Linux Netfilter/TPROXY support requires some specific header files and libcap dnl Shamelessly copied from shamelessly copied from above if test "$LINUX_TPROXY"; then - AC_MSG_CHECKING(if TPROXY header files are installed) + AC_MSG_CHECKING(if sys/capability 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 + if test "$ac_cv_header_sys_capability_h" = "yes" && test "$LINUX_NETFILTER" = "yes"; then LINUX_TPROXY="yes" AC_DEFINE(LINUX_TPROXY, 1, [Enable real Transparent Proxy support for Netfilter TPROXY.]) else @@ -2961,13 +2960,12 @@ LINUX_TPROXY="no" sleep 10 fi + + if test "$LINUX_TPROXY" = "no" ; then + echo "WARNING: Cannot find necessary system capability headers files" + echo " Linux TProxy-4 support WILL NOT be enabled" + fi fi -if test "$LINUX_TPROXY" = "no" && test "$LINUX_NETFILTER" = "yes"; then - echo "WARNING: Cannot find TPROXY headers, you need to patch your kernel with the" - echo "tproxy package from:" - echo " - lynx http://www.balabit.com/downloads/files/tproxy/" - sleep 10 -fi if test -z "$USE_GNUREGEX" ; then case "$host" in Index: src/ssl.c =================================================================== --- src/ssl.c (revision 9786) +++ src/ssl.c (working copy) @@ -499,6 +499,11 @@ char *url = http->uri; struct in_addr outgoing; unsigned long tos; +#ifdef LINUX_TPROXY + int flags; +#endif + + /* * client_addr == no_addr indicates this is an "internal" request * from peer_digest.c, asn.c, netdb.c, etc and should always @@ -522,11 +527,17 @@ outgoing = getOutgoingAddr(request); tos = getOutgoingTOS(request); /* Create socket. */ + flags = COMM_NONBLOCKING; +#ifdef LINUX_TPROXY + if (request->flags.tproxy) { + flags |= COMM_TRANSPARENT; + } +#endif sock = comm_openex(SOCK_STREAM, IPPROTO_TCP, outgoing, 0, - COMM_NONBLOCKING, + flags, tos, url); if (sock == COMM_ERROR) { Index: src/structs.h =================================================================== --- src/structs.h (revision 9786) +++ src/structs.h (working copy) @@ -942,6 +942,7 @@ unsigned int close_on_exec:1; unsigned int backoff:1; /* keep track of whether the fd is backed off */ unsigned int dnsfailed:1; /* did the dns lookup fail */ + unsigned int transparent:1; } flags; comm_pending read_pending; comm_pending write_pending; Index: src/defines.h =================================================================== --- src/defines.h (revision 9786) +++ src/defines.h (working copy) @@ -93,6 +93,9 @@ #define COMM_NONBLOCKING 0x01 #define COMM_NOCLOEXEC 0x02 #define COMM_REUSEADDR 0x04 +#ifdef LINUX_TPROXY +#define COMM_TRANSPARENT 0x08 +#endif #define do_debug(SECTION, LEVEL) \ ((_db_level = (LEVEL)) <= debugLevels[SECTION]) Index: src/comm.c =================================================================== --- src/comm.c (revision 9786) +++ src/comm.c (working copy) @@ -47,6 +47,12 @@ #include <netinet/tcp.h> #endif +#ifdef LINUX_TPROXY +#ifndef IP_TRANSPARENT +#define IP_TRANSPARENT 19 +#endif +#endif + typedef struct { char *host; u_short port; @@ -65,6 +71,9 @@ static void commSetReuseAddr(int); static void commSetNoLinger(int); static void CommWriteStateCallbackAndFree(int fd, int code); +#ifdef LINUX_TPROXY +static void commSetTransparent(int); +#endif #ifdef TCP_NODELAY static void commSetTcpNoDelay(int); #endif @@ -258,6 +267,12 @@ if (opt_reuseaddr) commSetReuseAddr(new_socket); } +#ifdef LINUX_TPROXY + if (flags & COMM_TRANSPARENT) { + F->flags.transparent = 1; + commSetTransparent(new_socket); + } +#endif if (addr.s_addr != no_addr.s_addr) { if (commBind(new_socket, addr, port) != COMM_OK) { comm_close(new_socket); @@ -435,6 +450,12 @@ * yuck, this has assumptions about comm_open() arguments for * the original socket */ +#ifdef LINUX_TPROXY + if (F->flags.transparent) { + commSetTransparent(cs->fd); + } +#endif + if (commBind(cs->fd, F->local_addr, F->local_port) != COMM_OK) { debug(5, 0) ("commResetFD: bind: %s\n", xstrerror()); return 0; @@ -1534,3 +1555,19 @@ } } } + +#ifdef LINUX_TPROXY +static void +commSetTransparent(int fd) +{ + int on = 1; + debug(5, 3) ("commSetTransparent: FD %d\n", fd); + if (setsockopt(fd, SOL_IP, IP_TRANSPARENT, (char*)&on, sizeof(on)) < 0) { + debug(5, 1) ("commSetTransparent: FD %d: %s\n", fd, xstrerror()); + } + fd_table[fd].flags.transparent = 1; +} +#endif + + + Index: src/forward.c =================================================================== --- src/forward.c (revision 9786) +++ src/forward.c (working copy) @@ -40,9 +40,6 @@ #include <linux/types.h> #include <linux/netfilter_ipv4.h> #endif -#if LINUX_TPROXY -#include <linux/netfilter_ipv4/ip_tproxy.h> -#endif static PSC fwdStartComplete; static void fwdDispatch(FwdState *); @@ -515,7 +512,7 @@ struct in_addr outgoing; unsigned short tos; #if LINUX_TPROXY - struct in_tproxy itp; + int flags; #endif int idle = -1; @@ -624,11 +621,19 @@ debug(17, 3) ("fwdConnectStart: got addr %s, tos %d\n", inet_ntoa(outgoing), tos); + flags = COMM_NONBLOCKING; +#ifdef LINUX_TPROXY + if ((outgoing.s_addr == INADDR_ANY) && fwdState->request->flags.tproxy) { + outgoing = fwdState->request->client_addr; + flags |= COMM_TRANSPARENT; + debug(17,3)("fwdConnectStart: setting outgoing.s_addr=%08X (will set TRANSPARENT)\n", outgoing.s_addr); + } +#endif fd = comm_openex(SOCK_STREAM, IPPROTO_TCP, outgoing, 0, - COMM_NONBLOCKING, + flags, tos, url); if (fd < 0) { @@ -661,32 +666,6 @@ if (fs->peer) { hierarchyNote(&fwdState->request->hier, fs->code, fs->peer->name); } else { -#if LINUX_TPROXY - if (fwdState->request->flags.tproxy) { - - itp.v.addr.faddr.s_addr = fwdState->src.sin_addr.s_addr; - itp.v.addr.fport = 0; - - /* If these syscalls fail then we just fallback to connecting - * normally by simply ignoring the errors... - */ - itp.op = TPROXY_ASSIGN; - if (setsockopt(fd, SOL_IP, IP_TPROXY, &itp, sizeof(itp)) == -1) { - debug(20, 1) ("tproxy ip=%s,0x%x,port=%d ERROR ASSIGN\n", - inet_ntoa(itp.v.addr.faddr), - itp.v.addr.faddr.s_addr, - itp.v.addr.fport); - } else { - itp.op = TPROXY_FLAGS; - itp.v.flags = ITP_CONNECT; - if (setsockopt(fd, SOL_IP, IP_TPROXY, &itp, sizeof(itp)) == -1) { - debug(20, 1) ("tproxy ip=%x,port=%d ERROR CONNECT\n", - itp.v.addr.faddr.s_addr, - itp.v.addr.fport); - } - } - } -#endif hierarchyNote(&fwdState->request->hier, fs->code, fwdState->request->host); } Index: src/client_side.c =================================================================== --- src/client_side.c (revision 9786) +++ src/client_side.c (working copy) @@ -5172,6 +5172,7 @@ { http_port_list *s; int fd; + int flags; for (s = Config.Sockaddr.http; s; s = s->next) { if (MAXHTTPPORTS == NHttpSockets) { debug(1, 1) ("WARNING: You have too many 'http_port' lines.\n"); @@ -5193,11 +5194,17 @@ "HTTP Socket"); } else { enter_suid(); + flags = COMM_NONBLOCKING; +#ifdef LINUX_TPROXY + if (s->tproxy) { + flags |= COMM_TRANSPARENT; + } +#endif fd = comm_open(SOCK_STREAM, IPPROTO_TCP, s->s.sin_addr, ntohs(s->s.sin_port), - COMM_NONBLOCKING, + flags, "HTTP Socket"); leave_suid(); }