diff -ur --exclude configure squid-2.5.STABLE1.orig/acconfig.h squid-2.5.STABLE1/acconfig.h --- squid-2.5.STABLE1.orig/acconfig.h Mon Jul 1 09:55:11 2002 +++ squid-2.5.STABLE1/acconfig.h Mon Mar 10 16:54:46 2003 @@ -331,6 +331,11 @@ */ #undef LINUX_NETFILTER +/* + * Enable real Transparent Proxy support for Netfilter TPROXY. + */ +#undef LINUX_TPROXY + /* * Do we have unix sockets? (required for the winbind ntlm helper */ diff -ur --exclude configure squid-2.5.STABLE1.orig/configure.in squid-2.5.STABLE1/configure.in --- squid-2.5.STABLE1.orig/configure.in Tue Sep 24 21:00:03 2002 +++ squid-2.5.STABLE1/configure.in Mon Mar 10 16:07:42 2003 @@ -746,6 +746,17 @@ 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) + LINUX_TPROXY="yes" + fi +]) + AM_CONDITIONAL(MAKE_LEAKFINDER, false) dnl Enable Leak Finding Functions AC_ARG_ENABLE(leakfinder, @@ -1153,6 +1164,7 @@ libc.h \ limits.h \ linux/netfilter_ipv4.h \ + linux/netfilter_ipv4/ip_tproxy.h \ malloc.h \ math.h \ memory.h \ @@ -1764,6 +1776,27 @@ sleep 10 fi +dnl Linux Netfilter/TPROXY 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) + # hold on to your hats... + if test "$ac_cv_header_linux_netfilter_ipv4_ip_tproxy_h" = "yes"; then + LINUX_TPROXY="yes" + AC_DEFINE(LINUX_TPROXY, 1) + else + LINUX_TPROXY="no" + AC_DEFINE(LINUX_TPROXY, 0) + fi + AC_MSG_RESULT($LINUX_TPROXY) +fi +if test "$LINUX_TPROXY" = "no" ; then + echo "WARNING: Cannot find TPROXY headers, you need to install the" + echo "tproxy package from:" + echo " - lynx http://www.balabit.com/downloads/tproxy/linux-2.4/" + sleep 10 +fi + if test -z "$USE_GNUREGEX" ; then case "$host" in *-sun-solaris2.[[0-4]]) diff -ur --exclude configure squid-2.5.STABLE1.orig/include/autoconf.h.in squid-2.5.STABLE1/include/autoconf.h.in --- squid-2.5.STABLE1.orig/include/autoconf.h.in Mon Jul 15 22:29:47 2002 +++ squid-2.5.STABLE1/include/autoconf.h.in Tue Mar 11 11:46:33 2003 @@ -350,6 +350,11 @@ */ #undef LINUX_NETFILTER +/* + * Enable real Transparent Proxy support for Netfilter TPROXY. + */ +#undef LINUX_TPROXY + /* * Do we have unix sockets? (required for the winbind ntlm helper */ @@ -645,6 +650,9 @@ /* Define if you have the header file. */ #undef HAVE_LINUX_NETFILTER_IPV4_H +/* Define if you have the header file. */ +#undef HAVE_LINUX_NETFILTER_IPV4_IP_TPROXY_H + /* Define if you have the header file. */ #undef HAVE_MALLOC_H diff -ur --exclude configure squid-2.5.STABLE1.orig/src/cf.data.pre squid-2.5.STABLE1/src/cf.data.pre --- squid-2.5.STABLE1.orig/src/cf.data.pre Wed Sep 4 14:35:01 2002 +++ squid-2.5.STABLE1/src/cf.data.pre Tue Mar 11 11:48:48 2003 @@ -3837,4 +3837,20 @@ until all the child processes have been started. DOC_END +NAME: linux_tproxy +IFDEF: LINUX_TPROXY +COMMENT: on|off +TYPE: onoff +LOC: Config.onoff.linux_tproxy +DEFAULT: off +DOC_START + If you have Linux 2.4 with netfilter and TPROXY support and you + have compiled squid with the correct options then you can enable + this option to allow squid to spoof the source address of + outgoing connections to servers so that they see connections from + the original client IP addresses. Enable this only if you know + what you are doing. You will need to set a valid + tcp_outgoing_address. +DOC_END + EOF diff -ur --exclude configure squid-2.5.STABLE1.orig/src/client_side.c squid-2.5.STABLE1/src/client_side.c --- squid-2.5.STABLE1.orig/src/client_side.c Mon Sep 23 05:04:03 2002 +++ squid-2.5.STABLE1/src/client_side.c Mon Mar 10 16:06:03 2003 @@ -322,6 +322,7 @@ new_request->http_ver = old_request->http_ver; httpHeaderAppend(&new_request->header, &old_request->header); new_request->client_addr = old_request->client_addr; + new_request->client_port = old_request->client_port; new_request->my_addr = old_request->my_addr; new_request->my_port = old_request->my_port; new_request->flags.redirected = 1; @@ -2977,6 +2978,7 @@ safe_free(http->log_uri); http->log_uri = xstrdup(urlCanonicalClean(request)); request->client_addr = conn->peer.sin_addr; + request->client_port = conn->peer.sin_port; request->my_addr = conn->me.sin_addr; request->my_port = ntohs(conn->me.sin_port); request->http_ver = http->http_ver; diff -ur --exclude configure squid-2.5.STABLE1.orig/src/forward.c squid-2.5.STABLE1/src/forward.c --- squid-2.5.STABLE1.orig/src/forward.c Mon Apr 1 13:51:27 2002 +++ squid-2.5.STABLE1/src/forward.c Wed Mar 12 15:18:20 2003 @@ -36,6 +36,13 @@ #include "squid.h" +#if LINUX_NETFILTER +#include +#endif +#if LINUX_TPROXY +#include +#endif + static PSC fwdStartComplete; static void fwdDispatch(FwdState *); static void fwdConnectStart(void *); /* should be same as EVH */ @@ -331,6 +338,15 @@ time_t ctimeout; struct in_addr outgoing; unsigned short tos; + struct in_addr *local=NULL; +#if LINUX_TPROXY + int f=ITP_CONNECT; + struct in_tproxy itp; + + if ( Config.onoff.linux_tproxy ) + local=&fwdState->src.sin_addr; +#endif + assert(fs); assert(fwdState->server_fd == -1); debug(17, 3) ("fwdConnectStart: %s\n", url); @@ -349,7 +365,7 @@ port = fwdState->request->port; ctimeout = Config.Timeout.connect; } - if ((fd = pconnPop(host, port)) >= 0) { + if ((fd = pconnPop(host, port, local)) >= 0) { debug(17, 3) ("fwdConnectStart: reusing pconn FD %d\n", fd); fwdState->server_fd = fd; fwdState->n_tries++; @@ -396,6 +412,18 @@ ctimeout, fwdConnectTimeout, fwdState); +#if LINUX_TPROXY + if ( Config.onoff.linux_tproxy ) { + itp.itp_faddr.s_addr = fwdState->src.sin_addr.s_addr; + itp.itp_fport = fwdState->src.sin_port; + + /* If these syscalls fail then we just fallback to connecting + * normally by simply ignoring the errors... + */ + setsockopt(fd, SOL_IP, IP_TPROXY_ASSIGN, &itp, sizeof(itp)); + setsockopt(fd, SOL_IP, IP_TPROXY_FLAGS, &f, sizeof(f)); + } +#endif commConnectStart(fd, host, port, fwdConnectDone, fwdState); } @@ -610,6 +638,15 @@ fwdState->server_fd = -1; fwdState->request = requestLink(r); fwdState->start = squid_curtime; + +#if LINUX_TPROXY + /* If we need to transparently proxy the request + * then we need the client source address and port */ + fwdState->src.sin_family = AF_INET; + fwdState->src.sin_addr = r->client_addr; + fwdState->src.sin_port = r->client_port; +#endif + storeLockObject(e); EBIT_SET(e->flags, ENTRY_FWD_HDR_WAIT); storeRegisterAbort(e, fwdAbort, fwdState); diff -ur --exclude configure squid-2.5.STABLE1.orig/src/http.c squid-2.5.STABLE1/src/http.c --- squid-2.5.STABLE1.orig/src/http.c Sat Sep 7 23:52:10 2002 +++ squid-2.5.STABLE1/src/http.c Wed Mar 12 13:50:50 2003 @@ -542,6 +542,7 @@ int bin; int clen; size_t read_sz; + struct in_addr *local=NULL; #if DELAY_POOLS delay_id delay_id; @@ -551,6 +552,12 @@ else delay_id = delayMostBytesAllowed(entry->mem_obj); #endif + +#if LINUX_TPROXY + if ( Config.onoff.linux_tproxy ) + local=&httpState->request->client_addr; +#endif + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { comm_close(fd); return; @@ -657,7 +664,7 @@ #endif comm_remove_close_handler(fd, httpStateFree, httpState); fwdUnregister(fd, httpState->fwd); - pconnPush(fd, request->host, request->port); + pconnPush(fd, request->host, request->port, local); fwdComplete(httpState->fwd); httpState->fd = -1; httpStateFree(fd, httpState); diff -ur --exclude configure squid-2.5.STABLE1.orig/src/main.c squid-2.5.STABLE1/src/main.c --- squid-2.5.STABLE1.orig/src/main.c Sun Jul 14 18:20:49 2002 +++ squid-2.5.STABLE1/src/main.c Tue Mar 11 11:48:18 2003 @@ -422,6 +422,16 @@ #ifdef _SQUID_OS2_ return; #endif + + /* Transparent proxy support requires squid to run as root which + * kinda sucks. I will look towards implementing a solution in + * kernel space to combat this, perhaps a sysctl to set a certain + * GID to be able to use the TPROXY stuff */ +#if LINUX_TPROXY + if ( Config.onoff.linux_tproxy ) + return; +#endif + if (geteuid() == 0) { debug(0, 0) ("Squid is not safe to run as root! If you must\n"); debug(0, 0) ("start Squid as root, then you must configure\n"); diff -ur --exclude configure squid-2.5.STABLE1.orig/src/pconn.c squid-2.5.STABLE1/src/pconn.c --- squid-2.5.STABLE1.orig/src/pconn.c Sat Apr 14 01:03:23 2001 +++ squid-2.5.STABLE1/src/pconn.c Wed Mar 12 15:20:04 2003 @@ -49,7 +49,6 @@ static PF pconnRead; static PF pconnTimeout; -static const char *pconnKey(const char *host, u_short port); static hash_table *table = NULL; static struct _pconn *pconnNew(const char *key); static void pconnDelete(struct _pconn *p); @@ -58,12 +57,17 @@ static MemPool *pconn_data_pool = NULL; static MemPool *pconn_fds_pool = NULL; -static const char * -pconnKey(const char *host, u_short port) +#define PCONN_KEYLEN (SQUIDHOSTNAMELEN + 24) + +static inline const int +pconnKey(char *buf, const char *peer, u_short port, struct in_addr *local) { - LOCAL_ARRAY(char, buf, SQUIDHOSTNAMELEN + 10); - snprintf(buf, SQUIDHOSTNAMELEN + 10, "%s.%d", host, (int) port); - return buf; + if ( local == NULL ) { + return snprintf(buf, PCONN_KEYLEN, "%s.%d", peer, (int) port); + }else{ + return snprintf(buf, PCONN_KEYLEN, "%s.%d.%s", + peer, (int) port, inet_ntoa(*local)); + } } static struct _pconn * @@ -184,11 +188,11 @@ } void -pconnPush(int fd, const char *host, u_short port) +pconnPush(int fd, const char *peer, u_short port, struct in_addr *local) { struct _pconn *p; int *old; - LOCAL_ARRAY(char, key, SQUIDHOSTNAMELEN + 10); + LOCAL_ARRAY(char, key, PCONN_KEYLEN); LOCAL_ARRAY(char, desc, FD_DESC_SZ); if (fdNFree() < (RESERVED_FD << 1)) { debug(48, 3) ("pconnPush: Not many unused FDs\n"); @@ -199,7 +203,7 @@ return; } assert(table != NULL); - strcpy(key, pconnKey(host, port)); + pconnKey(key, peer, port, local); p = (struct _pconn *) hash_lookup(table, key); if (p == NULL) p = pconnNew(key); @@ -217,20 +221,20 @@ p->fds[p->nfds++] = fd; commSetSelect(fd, COMM_SELECT_READ, pconnRead, p, 0); commSetTimeout(fd, Config.Timeout.pconn, pconnTimeout, p); - snprintf(desc, FD_DESC_SZ, "%s idle connection", host); + snprintf(desc, FD_DESC_SZ, "%s idle connection", peer); fd_note(fd, desc); debug(48, 3) ("pconnPush: pushed FD %d for %s\n", fd, key); } int -pconnPop(const char *host, u_short port) +pconnPop(const char *peer, u_short port, struct in_addr *local) { struct _pconn *p; hash_link *hptr; int fd = -1; - LOCAL_ARRAY(char, key, SQUIDHOSTNAMELEN + 10); + LOCAL_ARRAY(char, key, PCONN_KEYLEN); assert(table != NULL); - strcpy(key, pconnKey(host, port)); + pconnKey(key, peer, port, local); hptr = hash_lookup(table, key); if (hptr != NULL) { p = (struct _pconn *) hptr; diff -ur --exclude configure squid-2.5.STABLE1.orig/src/protos.h squid-2.5.STABLE1/src/protos.h --- squid-2.5.STABLE1.orig/src/protos.h Sat Sep 7 16:13:05 2002 +++ squid-2.5.STABLE1/src/protos.h Wed Mar 12 13:37:31 2003 @@ -1142,8 +1142,8 @@ extern int errorReservePageId(const char *page_name); extern ErrorState *errorCon(err_type type, http_status); -extern void pconnPush(int, const char *host, u_short port); -extern int pconnPop(const char *host, u_short port); +extern void pconnPush(int, const char *peer, u_short port, struct in_addr *local); +extern int pconnPop(const char *peer, u_short port, struct in_addr *local); extern void pconnInit(void); extern int asnMatchIp(void *, struct in_addr); diff -ur --exclude configure squid-2.5.STABLE1.orig/src/structs.h squid-2.5.STABLE1/src/structs.h --- squid-2.5.STABLE1.orig/src/structs.h Sun Sep 8 00:11:23 2002 +++ squid-2.5.STABLE1/src/structs.h Mon Mar 10 16:06:03 2003 @@ -585,6 +585,9 @@ int ie_refresh; int vary_ignore_expire; int pipeline_prefetch; +#if LINUX_NETFILTER + int linux_tproxy; +#endif } onoff; acl *aclList; struct { @@ -1645,6 +1648,7 @@ int imslen; int max_forwards; /* these in_addr's could probably be sockaddr_in's */ + in_port_t client_port; struct in_addr client_addr; struct in_addr my_addr; unsigned short my_port; @@ -1962,6 +1966,9 @@ unsigned int dont_retry:1; unsigned int ftp_pasv_failed:1; } flags; +#if LINUX_NETFILTER + struct sockaddr_in src; +#endif }; #if USE_HTCP