Here are the diffs in a little better format.
Ken
------------------------------------------------------------------------------------------------------------------------------------------------------
Index: configure.in
--- base/squid-2.5.STABLE9/configure.in 2005-02-23 15:54:54.000000000
-0800
+++ change/squid-2.5.STABLE9/configure.in 2005-10-26
15:37:48.000000000 -0700
@@ -747,6 +747,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,
@@ -1209,6 +1220,7 @@
libc.h \
limits.h \
linux/netfilter_ipv4.h \
+ linux/netfilter_ipv4/ip_tproxy.h \
malloc.h \
math.h \
memory.h \
@@ -1893,6 +1905,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]])
Index: cf.data.pre
--- base/squid-2.5.STABLE9/src/cf.data.pre 2005-02-22
16:06:34.000000000 -0800
+++ change/squid-2.5.STABLE9/src/cf.data.pre 2005-06-14
15:53:09.000000000 -0700
@@ -1,4 +1,3 @@
-
#
# $Id: cf.data.pre,v 1.245.2.85 2005/02/23 00:06:34 hno Exp $
#
@@ -3958,6 +3957,21 @@
DOC_START
If the one-minute average page fault rate exceeds this
value, Squid prints a WARNING with debug level 0 to get
+DOC_END
+
+NAME: 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.
the administrators attention. The value is in page faults
per second.
DOC_END
Index: src/client_side.c
--- base/squid-2.5.STABLE9/src/client_side.c 2005-02-20
11:07:45.000000000 -0800
+++ change/squid-2.5.STABLE9/src/client_side.c 2005-06-14
15:53:11.000000000 -0700
@@ -355,6 +355,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;
@@ -2480,7 +2481,12 @@
{
char *url = http->uri;
request_t *r = http->request;
+ const HttpHeader *req_hdr = &r->header;
ErrorState *err = NULL;
+ String xfwd;
+
+ int status;
+
debug(33, 4) ("clientProcessMiss: '%s %s'\n",
RequestMethodStr[r->method], url);
/*
@@ -2535,6 +2541,35 @@
}
if (http->flags.internal)
r->protocol = PROTO_INTERNAL;
+
+ /*
+ * If we have TPROXY enabled, parse the http header for
'X-Forwarded-for'.
+ * If it's there, convert it into an in_addr and put it into the
request
+ * structure we pass to forward.
+ */
+ if (Config.onoff.linux_tproxy) {
+ xfwd = httpHeaderGetList(req_hdr, HDR_X_FORWARDED_FOR);
+ if (xfwd.len != 0) {
+ debug(33, 2) ("%s: xfwd_ip[%s]\n", __func__, xfwd.buf);
+ status = inet_aton(xfwd.buf, &r->xfwd_ip);
+ if (status == 0) {
+ r->xfwd_ip.s_addr = htonl(INADDR_ANY);
+ }
+ } else {
+ r->xfwd_ip.s_addr = htonl(INADDR_ANY);
+ }
+
+ if (r->xfwd_ip.s_addr != INADDR_ANY) {
+ debug(33, 2) ("xfwd: %s:%d\n", inet_ntoa(r->xfwd_ip),
+ htons(r->client_port));
+ } else {
+ debug(33, 2) ("xfwd: Field Empty [%s]\n",
+ inet_ntoa(r->xfwd_ip));
+ }
+
+
+ }
+
fwdStart(http->conn->fd, http->entry, r);
}
@@ -3131,6 +3166,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;
Index: src/forward.c
--- base/squid-2.5.STABLE9/src/forward.c 2005-02-22
16:06:35.000000000 -0800
+++ change/squid-2.5.STABLE9/src/forward.c 2005-06-14
15:53:11.000000000 -0700
@@ -1,4 +1,3 @@
-
/*
* $Id: forward.c,v 1.82.2.14 2005/02/23 00:06:35 hno Exp $
*
@@ -36,6 +35,9 @@
#include "squid.h"
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv4/ip_tproxy.h>
+
static PSC fwdStartComplete;
static void fwdDispatch(FwdState *);
static void fwdConnectStart(void *); /* should be same as EVH */
@@ -348,6 +350,118 @@
}
static void
+forward_handle_tproxy (int fd, FwdState *fwdState)
+{
+ struct in_tproxy itp;
+ int itp_flags;
+ struct in_addr client_addr;
+ struct in_addr my_addr;
+ struct in_addr out_addr;
+
+ debug(20, 2)("%s: client[%s][%d], proxy[%s][%d], my[%s][%d]\n",
+ __func__,
+ inet_ntoa(fwdState->request->client_addr),
+ ntohs(fwdState->request->client_port),
+ inet_ntoa(fwdState->request->xfwd_ip),
+ ntohs(fwdState->request->client_port),
+ inet_ntoa(fwdState->request->my_addr),
+ ntohs(fwdState->request->my_port));
+
+
+ /*
+ * If the client address as stored in the X-FORWARD field is a
local address,
+ * don't try to proxy.
+ */
+ client_addr.s_addr = ntohl(fwdState->request->xfwd_ip.s_addr);
+ my_addr.s_addr = ntohl(fwdState->request->my_addr.s_addr);
+ out_addr = getOutgoingAddr(fwdState->request);
+ out_addr.s_addr = ntohl(out_addr.s_addr);
+
+ if (client_addr.s_addr == INADDR_ANY) {
+ return;
+ }
+
+ if (client_addr.s_addr == INADDR_LOOPBACK) {
+ return;
+ }
+
+ if (client_addr.s_addr == my_addr.s_addr) {
+ return;
+ }
+
+ if (client_addr.s_addr == out_addr.s_addr) {
+ return;
+ }
+
+ /*
+ * OK, it's safe to proxy for the client.
+ */
+ itp.itp_faddr.s_addr = fwdState->request->xfwd_ip.s_addr;
+
+ /*
+ * On a connect, the port number is assigned by the system
+ */
+ itp.itp_fport = 0;
+
+
+ /* If these syscalls fail then we just fallback to connecting
+ * normally by simply ignoring the errors...
+ */
+
+ /*
+ * We need to be superuser to set the proxy address.
+ */
+ enter_suid();
+
+ /*
+ * Register the client address we're interested in.
+ */
+ if (setsockopt(fd, SOL_IP, IP_TPROXY_ASSIGN, &itp, sizeof(itp))
== -1)
+ {
+ debug(20, 2)("%s: tproxy ip=%s, port=%d, ERROR ASSIGN: %s\n",
+ __func__,
+ inet_ntoa(itp.itp_faddr),
+ ntohs(itp.itp_fport), strerror(errno));
+ /*
+ * If this fails, don't try the proxy connect
+ */
+ leave_suid();
+ return;
+
+ } else {
+ debug(20, 2)("%s: tproxy ip=%s,0x%x,port=%d TPROXY_ASSIGN\n",
+ __func__,
+ inet_ntoa(itp.itp_faddr),
+ ntohl(itp.itp_faddr.s_addr),
+ ntohs(itp.itp_fport));
+ }
+
+ /*
+ * Set the socket up for an outgoing connect using
+ * the client address.
+ */
+ itp_flags = ITP_CONNECT;
+ if (setsockopt(fd, SOL_IP, IP_TPROXY_FLAGS, &itp_flags,
+ sizeof(itp_flags)) == -1)
+ {
+ debug(20, 2)("%s: tproxy ip=%x,port=%d, ERROR CONNECT: %s\n",
+ __func__,
+ ntohl(itp.itp_faddr.s_addr),
+ ntohs(itp.itp_fport), strerror(errno));
+ } else {
+ debug(20, 2)("%s: tproxy ip=%x,port=%d TPROXY_CONNECT\n",
+ __func__,
+ ntohl(itp.itp_faddr.s_addr),
+ ntohs(itp.itp_fport));
+ }
+
+ /*
+ * Back to previous user id
+ */
+ leave_suid();
+}
+
+static void
fwdConnectStart(void *data)
{
FwdState *fwdState = data;
@@ -361,6 +475,14 @@
int ftimeout = Config.Timeout.forward - (squid_curtime -
fwdState->start);
struct in_addr outgoing;
unsigned short tos;
+ struct in_addr *local;
+
+ if (Config.onoff.linux_tproxy) {
+ local=&fwdState->src.sin_addr;
+ } else {
+ local = NULL;
+ }
+
assert(fs);
assert(fwdState->server_fd == -1);
debug(17, 3) ("fwdConnectStart: %s\n", url);
@@ -383,7 +505,7 @@
ftimeout = 5;
if (ftimeout < ctimeout)
ctimeout = ftimeout;
- if ((fd = pconnPop(host, port)) >= 0) {
+ if ((fd = pconnPop(host, port, local)) >= 0) {
if (fwdCheckRetriable(fwdState)) {
debug(17, 3) ("fwdConnectStart: reusing pconn FD %d\n", fd);
fwdState->server_fd = fd;
@@ -407,8 +529,8 @@
outgoing = getOutgoingAddr(fwdState->request);
tos = getOutgoingTOS(fwdState->request);
- debug(17, 3) ("fwdConnectStart: got addr %s, tos %d\n",
- inet_ntoa(outgoing), tos);
+ debug(17, 3) ("%s: outgoing addr %s, tos %d\n",
+ __func__, inet_ntoa(outgoing), tos);
fd = comm_openex(SOCK_STREAM,
0,
outgoing,
@@ -417,7 +539,7 @@
tos,
url);
if (fd < 0) {
- debug(50, 4) ("fwdConnectStart: %s\n", xstrerror());
+ debug(50, 3) ("fwdConnectStart: %s\n", xstrerror());
err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
err->xerrno = errno;
err->request = requestLink(fwdState->request);
@@ -444,6 +566,18 @@
ctimeout,
fwdConnectTimeout,
fwdState);
+
+ switch (Config.onoff.linux_tproxy) {
+ case 0:
+ break;
+ case 1:
+ forward_handle_tproxy(fd, fwdState);
+ break;
+
+ default:
+ break;
+ }
+
commConnectStart(fd, host, port, fwdConnectDone, fwdState);
}
Index: src/http.c
--- base/squid-2.5.STABLE9/src/http.c 2005-02-11 02:52:59.000000000 -0800
+++ change/squid-2.5.STABLE9/src/http.c 2005-06-14 15:53:09.000000000
-0700
@@ -566,6 +566,10 @@
int bin;
int clen;
size_t read_sz;
+ struct in_addr *local;
+
+ local = NULL;
+
#if DELAY_POOLS
delay_id delay_id;
@@ -575,6 +579,11 @@
else
delay_id = delayMostBytesAllowed(entry->mem_obj);
#endif
+
+ if ( Config.onoff.linux_tproxy ) {
+ local=&httpState->request->client_addr;
+ }
+
if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
comm_close(fd);
return;
@@ -761,7 +770,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);
Index: src/pconn.c
--- base/squid-2.5.STABLE9/src/pconn.c 2003-12-15 15:38:43.000000000
-0800
+++ change/squid-2.5.STABLE9/src/pconn.c 2005-06-14
15:53:11.000000000 -0700
@@ -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 (fdUsageHigh()) {
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;
Index: src/protos.h
--- base/squid-2.5.STABLE9/src/protos.h 2005-02-20 18:55:04.000000000
-0800
+++ change/squid-2.5.STABLE9/src/protos.h 2005-06-14
15:53:11.000000000 -0700
@@ -1137,8 +1137,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);
Index: src/structs.h
--- base/squid-2.5.STABLE9/src/structs.h 2005-02-22
16:06:35.000000000 -0800
+++ change/squid-2.5.STABLE9/src/structs.h 2005-06-14
15:53:11.000000000 -0700
@@ -608,6 +608,9 @@
int relaxed_header_parser;
int accel_uses_host_header;
int accel_no_pmtu_disc;
+#if LINUX_NETFILTER
+ int linux_tproxy;
+#endif
} onoff;
acl *aclList;
struct {
@@ -1657,6 +1660,7 @@
struct _request_t {
method_t method;
protocol_t protocol;
+ in_port_t client_port;
char login[MAX_LOGIN_SZ];
char host[SQUIDHOSTNAMELEN + 1];
auth_user_request_t *auth_user_request;
@@ -1675,6 +1679,11 @@
struct in_addr client_addr;
struct in_addr my_addr;
unsigned short my_port;
+ /*
+ * The client IP addresses from the X-Forwarded-For field in the
+ * request header.
+ */
+ struct in_addr xfwd_ip;
HttpHeader header;
int content_length;
HierarchyLogEntry hier;
@@ -1992,6 +2001,9 @@
unsigned int dont_retry:1;
unsigned int ftp_pasv_failed:1;
} flags;
+#if LINUX_NETFILTER
+ struct sockaddr_in src;
+#endif
};
#if USE_HTCP
Received on Wed Oct 26 2005 - 17:13:47 MDT
This archive was generated by hypermail pre-2.1.9 : Tue Nov 01 2005 - 12:00:07 MST