Author: adrian.chadd
Date: Sun Jun 14 06:30:02 2009
New Revision: 14093
Modified:
branches/LUSCA_HEAD/configure.in
branches/LUSCA_HEAD/libiapp/comm.c
branches/LUSCA_HEAD/libiapp/comm.h
branches/LUSCA_HEAD/libiapp/comm_ips.h
branches/LUSCA_HEAD/libiapp/comm_ips_freebsd.c
branches/LUSCA_HEAD/libiapp/comm_ips_null.c
branches/LUSCA_HEAD/libiapp/comm_ips_tproxy2.c
branches/LUSCA_HEAD/libiapp/comm_ips_tproxy4.c
branches/LUSCA_HEAD/libiapp/comm_types.h
branches/LUSCA_HEAD/src/client_side.c
branches/LUSCA_HEAD/src/forward.c
Log:
This commit both tries to bring sanity to the whole interception/spoofing
mess -and- fix TPROXY-4.
* Firstly, separate out the "spoofing" flag (fd_table[fd].flags.tproxy)
into two flags - tproxy_lcl
and tproxy_rem. tproxy_lcl is for listen() sockets listening for
intercepted requests. tproxy_rem
is for outbound connections to upstreams/origin servers which want the
client IP spoofed.
* Add in hooks in the http listen socket connection code in client_side.c
to set the COMM_TPROXY_LCL
flag so the relevant fiddling of the listen socket occurs for
interception.
* Disable the netfilter requirement for TPROXY4. This is the magic/special
undocumented thing.
For TPROXY2, incoming sockets are redirected and handled by netfilter.
For TPROXY4, the incoming
sockets are redirected and handled by TPROXY4. TPROXY4 returns the
original destination IP in
getsockname(), like BSD's ipfw transparent hijack method. Trying the
netfilter method under TPROXY4
returns an error.
Now, this isn't explicitly defined in the Squid-3 code or the TPROXY4
documentation. The TPROXY4
intercepted connection code IMHO works "by accident". If netfilter is
compiled in it will fail;
Squid-3 has it fail gracefully down to the default getsockname() method
which works.
There's a whole lot of tidying up which needs to happen with the
interception lookup code, currently
done in client_side.c:clientNatLookup(). Just for now, TPROXY2 should use
netfilter's destination
lookup; TPROXY4 should use the default getsockname() lookup and FreeBSD's
interception method should
use getsockname() also.
I've verified this works for TPROXY4, WCCPv2 in mask assignment / l2
redirection mode. I haven't
tested TPROXY2 or FreeBSD. It is quite possible this commit breaks existing
functionality.
Modified: branches/LUSCA_HEAD/configure.in
==============================================================================
--- branches/LUSCA_HEAD/configure.in (original)
+++ branches/LUSCA_HEAD/configure.in Sun Jun 14 06:30:02 2009
@@ -1158,13 +1158,9 @@
[ --enable-linux-tproxy4
Enable real Transparent Proxy support for Netfilter
TPROXY v4.],
[ if test "$enableval" = "yes" ; then
- echo "Linux Netfilter/TPROXY v4 enabled"
+ echo "Linux 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"
- fi
fi
])
Modified: branches/LUSCA_HEAD/libiapp/comm.c
==============================================================================
--- branches/LUSCA_HEAD/libiapp/comm.c (original)
+++ branches/LUSCA_HEAD/libiapp/comm.c Sun Jun 14 06:30:02 2009
@@ -269,8 +269,10 @@
commSetCloseOnExec(new_socket);
if ((flags & COMM_REUSEADDR))
commSetReuseAddr(new_socket);
- if ((flags & COMM_TPROXY))
- F->flags.tproxy = 1;
+ if ((flags & COMM_TPROXY_LCL))
+ F->flags.tproxy_lcl = 1;
+ if ((flags & COMM_TPROXY_REM))
+ F->flags.tproxy_rem = 1;
if (sqinet_get_port(a) > 0) {
#ifdef _SQUID_MSWIN_
if (sock_type != SOCK_DGRAM)
@@ -280,9 +282,32 @@
commSetReuseAddr(new_socket);
}
- if (F->flags.tproxy) {
- if (comm_ips_bind(new_socket, &F->local_address) != COMM_OK) {
- debug(1, 1) ("comm_fdopen6: FD %d: TPROXY comm_ips_bind
failed? Why?\n", new_socket);
+ /*
+ * The local endpoint bind() stuff is a bit of a mess.
+ *
+ * There's three kinds of "bind" going on.
+ *
+ * The default bind(), for a normal socket. This is used both for
setting the listen address for
+ * an incoming socket and the local address of a remote connection
socket.
+ *
+ * The "spoof connection" bind, which is a bind() to a non-local
address, for a remote connection
+ * socket. Ie, spoofing the client IP when connecting to an upstream.
+ *
+ * Finally, the "non-local listen" bind, which is a bind() for the
purposes of intercepting
+ * connections which aren't targetted at a local IP.
+ *
+ * These are all treated differently by the various interception
techniques on various operating
+ * systems; this is why things are broken out.
+ */
+ if (F->flags.tproxy_lcl) {
+ if (comm_ips_bind_lcl(new_socket, &F->local_address) != COMM_OK) {
+ debug(1, 1) ("comm_fdopen6: FD %d: TPROXY comm_ips_bind_lcl()
failed? Why?\n", new_socket);
+ comm_close(new_socket);
+ return -1;
+ }
+ } else if (F->flags.tproxy_rem) {
+ if (comm_ips_bind_rem(new_socket, &F->local_address) != COMM_OK) {
+ debug(1, 1) ("comm_fdopen6: FD %d: TPROXY comm_ips_bind_rem()
failed? Why?\n", new_socket);
comm_close(new_socket);
return -1;
}
Modified: branches/LUSCA_HEAD/libiapp/comm.h
==============================================================================
--- branches/LUSCA_HEAD/libiapp/comm.h (original)
+++ branches/LUSCA_HEAD/libiapp/comm.h Sun Jun 14 06:30:02 2009
@@ -81,7 +81,8 @@
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 tproxy:1; /* should the source address of this FD
be
spoofed via comm_ips_bind()? */
+ unsigned int tproxy_lcl:1; /* should this listen socket
have its listen
details spoofed via comm_ips_lcl_bind()? */
+ unsigned int tproxy_rem:1; /* should the source address of
this FD be
spoofed via comm_ips_rem_bind()? */
} flags;
comm_pending read_pending;
comm_pending write_pending;
Modified: branches/LUSCA_HEAD/libiapp/comm_ips.h
==============================================================================
--- branches/LUSCA_HEAD/libiapp/comm_ips.h (original)
+++ branches/LUSCA_HEAD/libiapp/comm_ips.h Sun Jun 14 06:30:02 2009
@@ -2,7 +2,12 @@
#define __LIBIAPP_COMM_IPS_H__
-extern int comm_ips_bind(int fd, sqaddr_t *a);
+/* "Local" bind spoofing is for listen sockets wishing to listen on
non-local addresses */
+extern int comm_ips_bind_lcl(int fd, sqaddr_t *a);
+
+/* "Remote" bind spoofing is for connect sockets wishing to bind to a
non-local address */
+extern int comm_ips_bind_rem(int fd, sqaddr_t *a);
+
extern void comm_ips_keepCapabilities(void);
extern void comm_ips_restoreCapabilities(void);
Modified: branches/LUSCA_HEAD/libiapp/comm_ips_freebsd.c
==============================================================================
--- branches/LUSCA_HEAD/libiapp/comm_ips_freebsd.c (original)
+++ branches/LUSCA_HEAD/libiapp/comm_ips_freebsd.c Sun Jun 14 06:30:02 2009
@@ -19,8 +19,21 @@
#include "comm_types.h"
#include "globals.h"
+/*
+ * FreeBSD non-local bind listen() sockets bind to the relevant address
and use
+ * getsockname() to determine the original destination (local address
being spoofed)
+ * of the new connection.
+ */
int
-comm_ips_bind(int fd, sqaddr_t *a)
+comm_ips_bind_lcl(int fd, sqaddr_t *a)
+{
+ if (bind(fd, sqinet_get_entry(a), sqinet_get_length(a)) != 0)
+ return COMM_ERROR;
+ return COMM_OK;
+}
+
+int
+comm_ips_bind_rem(int fd, sqaddr_t *a)
{
int on = 1;
Modified: branches/LUSCA_HEAD/libiapp/comm_ips_null.c
==============================================================================
--- branches/LUSCA_HEAD/libiapp/comm_ips_null.c (original)
+++ branches/LUSCA_HEAD/libiapp/comm_ips_null.c Sun Jun 14 06:30:02 2009
@@ -20,7 +20,13 @@
#include "globals.h"
int
-comm_ips_bind(int fd, sqaddr_t *a)
+comm_ips_bind_lcl(int fd, sqaddr_t *a)
+{
+ return COMM_ERROR;
+}
+
+int
+comm_ips_bind_rem(int fd, sqaddr_t *a)
{
return COMM_ERROR;
}
Modified: branches/LUSCA_HEAD/libiapp/comm_ips_tproxy2.c
==============================================================================
--- branches/LUSCA_HEAD/libiapp/comm_ips_tproxy2.c (original)
+++ branches/LUSCA_HEAD/libiapp/comm_ips_tproxy2.c Sun Jun 14 06:30:02 2009
@@ -40,9 +40,19 @@
#include "../include/util.h"
+/*
+ * TPROXY2 listen() sockets just bind() to the specified address and
receive connections that way.
+ */
+int
+comm_ips_bind_lcl(int fd, sqaddr_t *a)
+{
+ if (bind(fd, sqinet_get_entry(a), sqinet_get_length(a)) != 0)
+ return COMM_ERROR;
+ return COMM_OK;
+}
int
-comm_ips_bind(int fd, sqaddr_t *a)
+comm_ips_bind_rem(int fd, sqaddr_t *a)
{
if (sqinet_get_family(a) != AF_INET)
return COMM_ERROR;
Modified: branches/LUSCA_HEAD/libiapp/comm_ips_tproxy4.c
==============================================================================
--- branches/LUSCA_HEAD/libiapp/comm_ips_tproxy4.c (original)
+++ branches/LUSCA_HEAD/libiapp/comm_ips_tproxy4.c Sun Jun 14 06:30:02 2009
@@ -49,8 +49,8 @@
#include "comm_types.h"
#include "globals.h"
-int
-comm_ips_bind(int fd, sqaddr_t *a)
+static int
+tproxy4_set_transparent(int fd, sqaddr_t *a)
{
int on = 1;
@@ -59,6 +59,22 @@
if (bind(fd, sqinet_get_entry(a), sqinet_get_length(a)) != 0)
return COMM_ERROR;
return COMM_OK;
+}
+
+/*
+ * TPROXY4 requires the local socket be set IP_TRANSPARENT and then the
bind() address
+ * will determine which TCP/UDP connections are hijacked.
+ */
+int
+comm_ips_bind_lcl(int fd, sqaddr_t *a)
+{
+ return tproxy4_set_transparent(fd, a);
+}
+
+int
+comm_ips_bind_rem(int fd, sqaddr_t *a)
+{
+ return tproxy4_set_transparent(fd, a);
}
void
Modified: branches/LUSCA_HEAD/libiapp/comm_types.h
==============================================================================
--- branches/LUSCA_HEAD/libiapp/comm_types.h (original)
+++ branches/LUSCA_HEAD/libiapp/comm_types.h Sun Jun 14 06:30:02 2009
@@ -30,7 +30,8 @@
COMM_NONBLOCKING = 1,
COMM_NOCLOEXEC = 2,
COMM_REUSEADDR = 4,
- COMM_TPROXY = 8
+ COMM_TPROXY_LCL = 8,
+ COMM_TPROXY_REM = 16
} comm_flags_t;
/* The default "no TOS" value */
Modified: branches/LUSCA_HEAD/src/client_side.c
==============================================================================
--- branches/LUSCA_HEAD/src/client_side.c (original)
+++ branches/LUSCA_HEAD/src/client_side.c Sun Jun 14 06:30:02 2009
@@ -5193,7 +5193,11 @@
{
http_port_list *s;
int fd;
+ int comm_flags;
for (s = Config.Sockaddr.http; s; s = s->next) {
+ comm_flags = COMM_NONBLOCKING;
+ if (s->tproxy)
+ comm_flags |= COMM_TPROXY_LCL;
if (MAXHTTPPORTS == NHttpSockets) {
debug(1, 1) ("WARNING: You have too many 'http_port' lines.\n");
debug(1, 1) (" The limit is %d\n", MAXHTTPPORTS);
@@ -5210,7 +5214,7 @@
SOCK_STREAM,
no_addr,
ntohs(s->s.sin_port),
- COMM_NONBLOCKING,
+ comm_flags,
COMM_TOS_DEFAULT,
"HTTP Socket");
} else {
@@ -5219,7 +5223,7 @@
IPPROTO_TCP,
s->s.sin_addr,
ntohs(s->s.sin_port),
- COMM_NONBLOCKING,
+ comm_flags,
COMM_TOS_DEFAULT,
"HTTP Socket");
leave_suid();
@@ -5233,10 +5237,11 @@
* peg the CPU with select() when we hit the FD limit.
*/
commSetDefer(fd, httpAcceptDefer, NULL);
- debug(1, 1) ("Accepting %s HTTP connections at %s, port %d, FD %d.\n",
+ debug(1, 1) ("Accepting %s %sHTTP connections at %s, port %d, FD %d.\n",
s->transparent ? "transparently proxied" :
s->accel ? "accelerated" :
"proxy",
+ s->tproxy ? "and tproxy'ied " : "",
inet_ntoa(s->s.sin_addr),
(int) ntohs(s->s.sin_port),
fd);
Modified: branches/LUSCA_HEAD/src/forward.c
==============================================================================
--- branches/LUSCA_HEAD/src/forward.c (original)
+++ branches/LUSCA_HEAD/src/forward.c Sun Jun 14 06:30:02 2009
@@ -527,7 +527,7 @@
/* XXX at the moment the local port is still 0; should this change to
support FreeBSD's tproxy derivative? -adrian */
if (fwdState->request->flags.tproxy) {
fd = comm_open(SOCK_STREAM, IPPROTO_TCP, fwdState->src.sin_addr, 0,
- COMM_NONBLOCKING | COMM_TPROXY, tos, url);
+ COMM_NONBLOCKING | COMM_TPROXY_REM, tos, url);
}
if (fd == -1) {
fd = comm_open(SOCK_STREAM, IPPROTO_TCP, outgoing, 0,
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"lusca-commit" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/lusca-commit?hl=en
-~----------~----~----~----~------~----~------~--~---