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 --