Search squid archive

tproxy2 patch for squid3

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,


Regular client-side transparent proxying is easily accomplished by 
redirecting network traffic using -j DNAT, -j REDIRECT, or -j TPROXY (I do 
not know why this seems needed). However, server-side transparency requires 
a little more kick.
https://lists.balabit.hu/pipermail/tproxy/2006-July/000273.html

This patch actually brew in my homemade version of squid3 and worked long 
before tproxy even hit the squid2.6 scene. CAP_NET_ADMIN must be accounted for
by the user, and in my case, is easily done through the MultiAdmin linux kernel
module.

diff --fast -Ndpru squid-3.0.PRE4-20060727~/src/cf.data.pre squid-3.0.PRE4-20060727/src/cf.data.pre
--- squid-3.0.PRE4-20060727~/src/cf.data.pre	2006-07-02 18:53:46.000000000 +0200
+++ squid-3.0.PRE4-20060727/src/cf.data.pre	2006-07-28 15:56:59.629577000 +0200
@@ -2852,6 +2852,16 @@ DOC_START
 	the correct result.
 DOC_END
 
+NAME: tproxy
+TYPE: onoff
+DEFAULT: off
+LOC: Config.onoff.tproxy
+DOC_START
+	If you have Linux with iptables and TPROXY2 support, you can enable
+	this option to have SQUID make outgoing connections using the original
+	IP address of the client.
+DOC_END
+
 NAME: tcp_outgoing_tos tcp_outgoing_ds tcp_outgoing_dscp
 TYPE: acl_tos
 DEFAULT: none
diff --fast -Ndpru squid-3.0.PRE4-20060727~/src/comm.cc squid-3.0.PRE4-20060727/src/comm.cc
--- squid-3.0.PRE4-20060727~/src/comm.cc	2006-05-30 23:15:58.000000000 +0200
+++ squid-3.0.PRE4-20060727/src/comm.cc	2006-07-28 15:57:02.299577000 +0200
@@ -39,8 +39,10 @@
 #include "StoreIOBuffer.h"
 #include "comm.h"
 #include "fde.h"
+#include "forward.h"
 #include "CommIO.h"
 #include "ConnectionDetail.h"
+#include "HttpRequest.h"
 #include "MemBuf.h"
 #include "pconn.h"
 #include "SquidTime.h"
@@ -52,6 +54,7 @@
 #include <netinet/tcp.h>
 #endif
 
+#include "ip_tproxy.h"
 
 class ConnectStateData
 {
@@ -66,7 +69,7 @@ public:
     char *host;
     u_short port;
 
-    struct sockaddr_in S;
+    struct sockaddr_in S, src_addr;
     CallBack<CNCB> callback;
 
     struct IN_ADDR in_addr;
@@ -1150,6 +1153,26 @@ ConnectStateData::operator delete (void 
     cbdataFree(address);
 }
 
+void commConnectStart2(int fd, const char *host, u_short port, CNCB *callback,
+ FwdState *fs)
+{
+    ConnectStateData *cs;
+
+    cs = new ConnectStateData;
+    cs->fd = fd;
+    cs->host = xstrdup(host);
+    cs->port = port;
+    cs->callback = CallBack<CNCB>(callback, fs);
+    if(fs->request != NULL) {
+        cs->src_addr.sin_addr = fs->request->client_addr;
+        cs->src_addr.sin_port = htons(fs->request->client_port);
+    } else {
+        memset(&cs->src_addr, 0, sizeof(cs->src_addr));
+    }
+    comm_add_close_handler(fd, commConnectFree, cs);
+    ipcache_nbgethostbyname(host, commConnectDnsHandle, cs);
+}
+
 void
 commConnectStart(int fd, const char *host, u_short port, CNCB * callback, void *data)
 {
@@ -1353,7 +1376,7 @@ ConnectStateData::connect()
     if (S.sin_addr.s_addr == 0)
         defaults();
 
-    switch (comm_connect_addr(fd, &S)) {
+    switch (comm_connect_addr(fd, &S, &src_addr)) {
 
     case COMM_INPROGRESS:
         debug(5, 5) ("ConnectStateData::connect: FD %d: COMM_INPROGRESS\n", fd);
@@ -1406,9 +1429,45 @@ commSetTimeout(int fd, int timeout, PF *
     return F->timeout;
 }
 
-int
+static void do_tproxy(int sock, const struct sockaddr_in *src,
+ const struct sockaddr_in *dest)
+{
+    struct in_tproxy itp;
+    int ret;
 
-comm_connect_addr(int sock, const struct sockaddr_in *address)
+    memset(&itp, 0, sizeof(itp));
+    itp.v.addr.faddr = src->sin_addr; // fix endianness
+    itp.v.addr.fport = 0; //src->sin_port;
+    itp.op = TPROXY_ASSIGN;
+
+    if((ret = setsockopt(sock, SOL_IP, IP_TPROXY, &itp, sizeof(itp))) != 0) {
+        debug(5, 3) ("setsockopt IP_TPROXY/TPROXY_ASSIGN failed\n");
+        return;
+    }
+
+    memset(&itp, 0, sizeof(itp));
+    itp.v.addr.faddr = dest->sin_addr;
+    itp.v.addr.fport = dest->sin_port;
+    itp.op = TPROXY_CONNECT;
+    if((ret = setsockopt(sock, SOL_IP, IP_TPROXY, &itp, sizeof(itp))) != 0) {
+        debug(5, 3) ("setsockopt IP_TPROXY/TPROXY_CONNECT failed\n");
+        return;
+    }
+
+    memset(&itp, 0, sizeof(itp));
+    itp.v.flags = ITP_CONNECT;
+    itp.op = TPROXY_FLAGS;
+    if((ret = setsockopt(sock, SOL_IP, IP_TPROXY, &itp, sizeof(itp))) != 0) {
+        debug(5, 3) ("setsockopt IP_TPROXY/TPROXY_FLAGS failed\n");
+        return;
+    }
+
+    return;
+}
+
+int
+comm_connect_addr(int sock, const struct sockaddr_in *address,
+ const struct sockaddr_in *src)
 {
     comm_err_t status = COMM_OK;
     fde *F = &fd_table[sock];
@@ -1425,6 +1484,10 @@ comm_connect_addr(int sock, const struct
         F->flags.called_connect = 1;
         statCounter.syscalls.sock.connects++;
 
+        if(Config.onoff.tproxy && src != NULL && src->sin_addr.s_addr != 0 &&
+         ((ntohl(src->sin_addr.s_addr) >> 24) & 0xFF) != 0x7F)
+                do_tproxy(sock, src, address);
+
         x = connect(sock, (struct sockaddr *) address, sizeof(*address));
 
         if (x < 0)
diff --fast -Ndpru squid-3.0.PRE4-20060727~/src/forward.cc squid-3.0.PRE4-20060727/src/forward.cc
--- squid-3.0.PRE4-20060727~/src/forward.cc	2006-06-20 00:49:59.000000000 +0200
+++ squid-3.0.PRE4-20060727/src/forward.cc	2006-07-28 15:56:59.629577000 +0200
@@ -811,7 +811,7 @@ FwdState::connectStart()
     else
         hierarchyNote(&request->hier, fs->code, request->host);
 
-    commConnectStart(fd, host, port, fwdConnectDoneWrapper, this);
+    commConnectStart2(fd, host, port, fwdConnectDoneWrapper, this);
 }
 
 void
diff --fast -Ndpru squid-3.0.PRE4-20060727~/src/ip_tproxy.h squid-3.0.PRE4-20060727/src/ip_tproxy.h
--- squid-3.0.PRE4-20060727~/src/ip_tproxy.h	1970-01-01 01:00:00.000000000 +0100
+++ squid-3.0.PRE4-20060727/src/ip_tproxy.h	2006-07-28 15:56:59.639577000 +0200
@@ -0,0 +1,78 @@
+/*
+ * Transparent proxy support for Linux/iptables
+ *
+ * Copyright (c) 2002-2004 BalaBit IT Ltd.
+ * Author: Balzs Scheidler
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _IP_TPROXY_H
+#define _IP_TPROXY_H
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/in.h>
+#else
+#include <netinet/in.h>
+#ifndef IP_RECVORIGADDRS
+#define IP_RECVORIGADDRS	11273
+#define IP_ORIGADDRS	IP_RECVORIGADDRS
+struct in_origaddrs {
+        struct in_addr ioa_srcaddr;
+        struct in_addr ioa_dstaddr;
+        unsigned short int ioa_srcport;
+        unsigned short int ioa_dstport;
+};
+#endif
+#endif
+
+/*
+ * used in setsockopt(SOL_IP, IP_TPROXY) should not collide
+ * with values in <linux/in.h>
+ */
+
+#define IP_TPROXY	11274
+
+/* tproxy operations */
+enum {
+	TPROXY_VERSION = 0,
+	TPROXY_ASSIGN,
+	TPROXY_UNASSIGN,
+	TPROXY_QUERY,
+	TPROXY_FLAGS,
+	TPROXY_ALLOC,
+	TPROXY_CONNECT
+};
+
+/* bitfields in IP_TPROXY_FLAGS */
+#define ITP_CONNECT     0x00000001
+#define ITP_LISTEN      0x00000002
+#define ITP_ESTABLISHED 0x00000004
+
+#define ITP_ONCE        0x00010000
+#define ITP_MARK        0x00020000
+#define ITP_APPLIED     0x00040000
+#define ITP_UNIDIR      0x00080000
+
+struct in_tproxy_addr{
+	struct in_addr	faddr;
+	u_int16_t	fport;
+};
+
+struct in_tproxy {
+	/* fixed part, should not change between versions */
+	u_int32_t op;
+	/* extensible part */
+	union _in_args {
+		u_int32_t		version;
+		struct in_tproxy_addr	addr;
+		u_int32_t		flags;
+	} v;
+};
+
+#endif
+
diff --fast -Ndpru squid-3.0.PRE4-20060727~/src/protos.h squid-3.0.PRE4-20060727/src/protos.h
--- squid-3.0.PRE4-20060727~/src/protos.h	2006-07-02 18:53:46.000000000 +0200
+++ squid-3.0.PRE4-20060727/src/protos.h	2006-07-28 15:57:02.299577000 +0200
@@ -132,8 +132,10 @@ SQUIDCEXTERN void comm_reset_close(int f
 SQUIDCEXTERN void comm_lingering_close(int fd);
 #endif
 SQUIDCEXTERN void commConnectStart(int fd, const char *, u_short, CNCB *, void *);
+class FwdState;
+SQUIDCEXTERN void commConnectStart2(int, const char *, u_short, CNCB *, FwdState *);
 
-SQUIDCEXTERN int comm_connect_addr(int sock, const struct sockaddr_in *);
+SQUIDCEXTERN int comm_connect_addr(int sock, const struct sockaddr_in *, const struct sockaddr_in * = NULL);
 SQUIDCEXTERN void comm_init(void);
 
 SQUIDCEXTERN int comm_open(int, int, struct IN_ADDR, u_short port, int, const char *note);
@@ -256,7 +258,6 @@ SQUIDCEXTERN void fqdncache_restart(void
 SQUIDCEXTERN EVH fqdncache_purgelru;
 SQUIDCEXTERN void fqdncacheAddEntryFromHosts(char *addr, wordlist * hostnames);
 
-class FwdState;
 SQUIDCEXTERN void ftpStart(FwdState *);
 SQUIDCEXTERN char *ftpUrlWith2f(const HttpRequest *);
 
diff --fast -Ndpru squid-3.0.PRE4-20060727~/src/structs.h squid-3.0.PRE4-20060727/src/structs.h
--- squid-3.0.PRE4-20060727~/src/structs.h	2006-07-02 18:53:47.000000000 +0200
+++ squid-3.0.PRE4-20060727/src/structs.h	2006-07-28 15:57:02.309577000 +0200
@@ -559,6 +559,7 @@ struct _SquidConfig
         int emailErrData;
         int httpd_suppress_version_string;
         int global_internal_static;
+        int tproxy;
     }
 
     onoff;
#<<eof>>

Jan Engelhardt
-- 

[Index of Archives]     [Linux Audio Users]     [Samba]     [Big List of Linux Books]     [Linux USB]     [Yosemite News]

  Powered by Linux