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 lusca-commit@googlegroups.com
To unsubscribe from this group, send email to 
lusca-commit+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/lusca-commit?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to