Hi,

Here is the first cut of the patch against squid-2.5, it is all fairly
self-explanatory. Still a couple of things I need to do.

The patch adds a new onoff config 'linux_tproxy' which when set will
spoof the source address of outgoing server connections to be the same
as the original client address. There is one slight bogon which is
disabling the euid==0 check because squid needs to run as root to use
the tproxy functionality. Perhaps this could be more fine-grained and
only allow euid==0 when linux_tproxy is enabled. If it came to it I
could always fix minor warts like this with some interesting kernel
kludge instead (eg: echo 666 > /proc/sys/tproxy_gid).

TODO
----
 o Document the weird stuff, you need to set a tcp_outgoing_address when
   using netfilter TPROXY and disable server persistent connections.
 o Bail with an error if server persistent connections is enabled in
   conjunction with linux_tproxy.
 o Remove euid-check wart
 o port to HEAD ;)

Still not had time to checkout HEAD but will do before going home
tonight if I get time, have you any technical thoughts on implementing
'connection-pinning' both for 2.5 and 3.0? I think that will be the next
thing to do. Should be fun :)

Thanks.

-- 
// Gianni Tedesco (gianni at scaramanga dot co dot uk)
lynx --source www.scaramanga.co.uk/gianni-at-ecsc.asc | gpg --import
8646BE7D: 6D9F 2287 870E A2C9 8F60 3A3C 91B5 7669 8646 BE7D
diff -ur 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	Fri Mar  7 16:50:42 2003
@@ -3837,4 +3837,20 @@
 	until all the child processes have been started.
 DOC_END
 
+NAME: linux_tproxy
+IFDEF: LINUX_NETFILTER
+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 disable server peristent
+	connections and set a valid tcp_outgoing_address.
+DOC_END
+
 EOF
diff -ur 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	Fri Mar  7 12:29:50 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 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	Fri Mar  7 13:59:49 2003
@@ -36,6 +36,14 @@
 
 #include "squid.h"
 
+#if LINUX_NETFILTER
+/* FIXME: For now this means you also have transparent
+ * proxy support. Need to add a new option to configure.in
+*/
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv4/ip_tproxy.h>
+#endif
+
 static PSC fwdStartComplete;
 static void fwdDispatch(FwdState *);
 static void fwdConnectStart(void *);	/* should be same as EVH */
@@ -331,6 +339,11 @@
     time_t ctimeout;
     struct in_addr outgoing;
     unsigned short tos;
+#if LINUX_NETFILTER
+    int f=ITP_CONNECT;
+    struct in_tproxy itp;
+#endif
+
     assert(fs);
     assert(fwdState->server_fd == -1);
     debug(17, 3) ("fwdConnectStart: %s\n", url);
@@ -396,6 +409,23 @@
 	ctimeout,
 	fwdConnectTimeout,
 	fwdState);
+#if LINUX_NETFILTER
+    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));
+
+        debug(17, 1) ("tproxy: %s:%u -> %s:%u\n",
+            inet_ntoa(fwdState->src.sin_addr),
+            htons(fwdState->src.sin_port),
+            host, port);
+    }
+#endif
     commConnectStart(fd, host, port, fwdConnectDone, fwdState);
 }
 
@@ -610,6 +640,15 @@
     fwdState->server_fd = -1;
     fwdState->request = requestLink(r);
     fwdState->start = squid_curtime;
+
+#if LINUX_NETFILTER
+    /* 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 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	Fri Mar  7 13:15:12 2003
@@ -422,6 +422,7 @@
 #ifdef _SQUID_OS2_
     return;
 #endif
+    return;
     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 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	Fri Mar  7 13:53:36 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

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to