[squid-users] tproxy2 patch for squid3

From: Jan Engelhardt <jengelh@dont-contact.us>
Date: Sat, 29 Jul 2006 09:44:19 +0200 (MEST)

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

-- 
Received on Sat Jul 29 2006 - 01:44:29 MDT

This archive was generated by hypermail pre-2.1.9 : Tue Aug 01 2006 - 12:00:02 MDT