=== modified file 'src/HttpRequest.cc' --- src/HttpRequest.cc 2013-02-17 02:24:54 +0000 +++ src/HttpRequest.cc 2013-02-28 10:08:37 +0000 @@ -596,7 +597,7 @@ // Because it failed verification, or someone bypassed the security tests // we cannot cache the reponse for sharing between clients. // TODO: update cache to store for particular clients only (going to same Host: and destination IP) - if (!flags.hostVerified && (flags.intercepted || flags.spoofClientIp)) + if (!flags.hostVerified && (flags.intercepted || flags.interceptTproxy)) return false; switch (protocol) { === modified file 'src/RequestFlags.h' --- src/RequestFlags.h 2013-01-24 10:26:24 +0000 +++ src/RequestFlags.h 2013-02-27 15:34:00 +0000 @@ -87,7 +87,12 @@ bool intercepted :1; /** set if the Host: header passed verification */ bool hostVerified :1; - /** request to spoof the client ip */ + /// + /// Set for requests handled by a "tproxy" port. + bool interceptTproxy :1; + /// The client IP address should be spoofed when connecting to the web server. + /// This applies to TPROXY traffic that has not had spoofing disabled through + /// the spoof_client_ip squid.conf ACL. bool spoofClientIp :1; /** set if the request is internal (\see ClientHttpRequest::flags.internal)*/ bool internal :1; === modified file 'src/SquidConfig.h' --- src/SquidConfig.h 2013-02-08 09:25:04 +0000 +++ src/SquidConfig.h 2013-02-27 15:39:40 +0000 @@ -403,6 +403,10 @@ #if ICAP_CLIENT acl_access* icap; #endif + + /// spoof_client_ip squid.conf acl. + /// nil unless configured + acl_access* spoof_client_ip; } accessList; AclDenyInfoList *denyInfoList; === modified file 'src/acl/DestinationIp.cc' --- src/acl/DestinationIp.cc 2013-01-28 16:56:05 +0000 +++ src/acl/DestinationIp.cc 2013-02-27 15:30:24 +0000 @@ -56,7 +56,7 @@ // Bypass of browser same-origin access control in intercepted communication // To resolve this we will force DIRECT and only to the original client destination. // In which case, we also need this ACL to accurately match the destination - if (Config.onoff.client_dst_passthru && (checklist->request->flags.intercepted || checklist->request->flags.spoofClientIp)) { + if (Config.onoff.client_dst_passthru && (checklist->request->flags.intercepted || checklist->request->flags.interceptTproxy)) { assert(checklist->conn() && checklist->conn()->clientConnection != NULL); return ACLIP::match(checklist->conn()->clientConnection->local); } === modified file 'src/auth/Acl.cc' --- src/auth/Acl.cc 2012-09-19 17:16:56 +0000 +++ src/auth/Acl.cc 2013-02-27 15:27:16 +0000 @@ -34,7 +34,7 @@ } else if (request->flags.accelerated) { /* WWW authorization on accelerated requests */ headertype = HDR_AUTHORIZATION; - } else if (request->flags.intercepted || request->flags.spoofClientIp) { + } else if (request->flags.intercepted || request->flags.interceptTproxy) { debugs(28, DBG_IMPORTANT, "NOTICE: Authentication not applicable on intercepted requests."); return ACCESS_DENIED; } else { === modified file 'src/cache_cf.cc' --- src/cache_cf.cc 2013-02-10 16:31:40 +0000 +++ src/cache_cf.cc 2013-02-27 15:19:13 +0000 @@ -3605,8 +3605,7 @@ s->flags.tproxyIntercept = true; Ip::Interceptor.StartTransparency(); /* Log information regarding the port modes under transparency. */ - debugs(3, DBG_IMPORTANT, "Starting IP Spoofing on port " << s->s); - debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (IP spoofing enabled)"); + debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (TPROXY enabled)"); if (!Ip::Interceptor.ProbeForTproxy(s->s)) { debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: TPROXY support in the system does not work."); === modified file 'src/cf.data.pre' --- src/cf.data.pre 2013-02-12 21:49:03 +0000 +++ src/cf.data.pre 2013-02-27 15:38:15 +0000 @@ -1223,6 +1223,27 @@ sources is required to prevent abuse of your proxy. DOC_END +NAME: spoof_client_ip +TYPE: acl_access +LOC: Config.accessList.spoof_client_ip +DEFAULT: none +DEFAULT_DOC: allow +DOC_START + Control client IP address spoofing of TPROXY traffic based on + defined access lists. + + spoof_client_ip allow|deny [!]aclname ... + + If there are no "spoof_client_ip" lines present, the default + is to "allow" spoofing of any suitable request. + + Note that the cache_peer "no-tproxy" option overrides this ACL. + + This clause supports fast acl types. + See http://wiki.squid-cache.org/SquidFaq/SquidAcl for details. +DOC_END + + NAME: http_access TYPE: acl_access LOC: Config.accessList.http @@ -2936,6 +2957,7 @@ no-tproxy Do not use the client-spoof TPROXY support when forwarding requests to this peer. Use normal address selection instead. + This overrides the spoof_client_ip ACL. proxy-only objects fetched from the peer will not be stored locally. === modified file 'src/client_side.cc' --- src/client_side.cc 2013-02-12 11:34:35 +0000 +++ src/client_side.cc 2013-02-27 16:38:57 +0000 @@ -2696,7 +2696,14 @@ */ if (http->clientConnection != NULL) { request->flags.intercepted = ((http->clientConnection->flags & COMM_INTERCEPTION) != 0); - request->flags.spoofClientIp = ((http->clientConnection->flags & COMM_TRANSPARENT) != 0 ) ; + request->flags.interceptTproxy = ((http->clientConnection->flags & COMM_TRANSPARENT) != 0 ) ; + if (request->flags.interceptTproxy) { + if (Config.accessList.spoof_client_ip) { + ACLFilledChecklist *checklist = clientAclChecklistCreate(Config.accessList.spoof_client_ip, http); + request->flags.spoofClientIp = checklist->fastCheck() == ACCESS_ALLOWED; + delete checklist; + } else request->flags.spoofClientIp = 1; + } else request->flags.spoofClientIp = 0; } if (internalCheck(request->urlpath.termedBuf())) { @@ -3598,7 +3605,7 @@ else { char buf[MAX_IPSTRLEN]; assert(bumpMode != Ssl::bumpNone && bumpMode != Ssl::bumpEnd); - HttpRequest *fakeRequest = new HttpRequest; + HttpRequest::Pointer fakeRequest(new HttpRequest); fakeRequest->SetHost(details->local.NtoA(buf, sizeof(buf))); fakeRequest->port = details->local.GetPort(); fakeRequest->clientConnectionManager = connState; @@ -3607,10 +3614,17 @@ fakeRequest->indirect_client_addr = connState->clientConnection->remote; #endif fakeRequest->my_addr = connState->clientConnection->local; - fakeRequest->flags.spoofClientIp = ((connState->clientConnection->flags & COMM_TRANSPARENT) != 0 ) ; + fakeRequest->flags.interceptTproxy = ((connState->clientConnection->flags & COMM_TRANSPARENT) != 0 ) ; fakeRequest->flags.intercepted = ((connState->clientConnection->flags & COMM_INTERCEPTION) != 0); + fakeRequest->myportname = connState->port->name; + if (fakeRequest->flags.interceptTproxy) { + if (Config.accessList.spoof_client_ip) { + ACLFilledChecklist checklist(Config.accessList.spoof_client_ip, fakeRequest.getRaw(), NULL); + fakeRequest->flags.spoofClientIp = checklist.fastCheck() == ACCESS_ALLOWED; + } else fakeRequest->flags.spoofClientIp = 1; + } else fakeRequest->flags.spoofClientIp = 0; debugs(33, 4, HERE << details << " try to generate a Dynamic SSL CTX"); - connState->switchToHttps(fakeRequest, bumpMode); + connState->switchToHttps(fakeRequest.getRaw(), bumpMode); } } @@ -4145,7 +4159,7 @@ debugs(1, DBG_IMPORTANT, "Accepting " << (s->flags.natIntercept ? "NAT intercepted " : "") << - (s->flags.tproxyIntercept ? "TPROXY spoofing " : "") << + (s->flags.tproxyIntercept ? "TPROXY intercepted " : "") << (s->flags.tunnelSslBumping ? "SSL bumped " : "") << (s->flags.accelSurrogate ? "reverse-proxy " : "") << FdNote(portTypeNote) << " connections at " === modified file 'src/client_side_request.cc' --- src/client_side_request.cc 2013-02-12 11:34:35 +0000 +++ src/client_side_request.cc 2013-02-27 15:29:59 +0000 @@ -671,7 +671,7 @@ } debugs(85, 3, HERE << "validate host=" << host << ", port=" << port << ", portStr=" << (portStr?portStr:"NULL")); - if (http->request->flags.intercepted || http->request->flags.spoofClientIp) { + if (http->request->flags.intercepted || http->request->flags.interceptTproxy) { // verify the Host: port (if any) matches the apparent destination if (portStr && port != http->getConn()->clientConnection->local.GetPort()) { debugs(85, 3, HERE << "FAIL on validate port " << http->getConn()->clientConnection->local.GetPort() << @@ -971,7 +971,7 @@ const wordlist *p = NULL; // intercepted requests MUST NOT (yet) be sent to peers unless verified - if (!request->flags.hostVerified && (request->flags.intercepted || request->flags.spoofClientIp)) + if (!request->flags.hostVerified && (request->flags.intercepted || request->flags.interceptTproxy)) return 0; /* === modified file 'src/format/Format.cc' --- src/format/Format.cc 2013-02-11 23:11:12 +0000 +++ src/format/Format.cc 2013-02-27 15:27:44 +0000 @@ -383,7 +383,7 @@ case LFT_LOCAL_LISTENING_IP: { // avoid logging a dash if we have reliable info const bool interceptedAtKnownPort = al->request ? - (al->request->flags.spoofClientIp || + (al->request->flags.interceptTproxy || al->request->flags.intercepted) && al->cache.port : false; if (interceptedAtKnownPort) { === modified file 'src/forward.cc' --- src/forward.cc 2013-02-18 13:02:42 +0000 +++ src/forward.cc 2013-02-27 15:31:33 +0000 @@ -151,7 +151,7 @@ // Bug 3243: CVE 2009-0801 // Bypass of browser same-origin access control in intercepted communication // To resolve this we must force DIRECT and only to the original client destination. - const bool isIntercepted = request && !request->flags.redirected && (request->flags.intercepted || request->flags.spoofClientIp); + const bool isIntercepted = request && !request->flags.redirected && (request->flags.intercepted || request->flags.interceptTproxy); const bool useOriginalDst = Config.onoff.client_dst_passthru || (request && !request->flags.hostVerified); if (isIntercepted && useOriginalDst) { selectPeerForIntercepted(); === modified file 'src/peer_select.cc' --- src/peer_select.cc 2013-02-12 11:34:35 +0000 +++ src/peer_select.cc 2013-02-27 15:34:13 +0000 @@ -236,7 +236,7 @@ // on intercepted traffic which failed Host verification const HttpRequest *req = psstate->request; const bool isIntercepted = !req->flags.redirected && - (req->flags.intercepted || req->flags.spoofClientIp); + (req->flags.intercepted || req->flags.interceptTproxy); const bool useOriginalDst = Config.onoff.client_dst_passthru || !req->flags.hostVerified; const bool choseDirect = fs && fs->code == HIER_DIRECT; if (isIntercepted && useOriginalDst && choseDirect) { @@ -343,7 +343,7 @@ if (psstate->paths->size() >= (unsigned int)Config.forward_max_tries) break; - // for TPROXY we must skip unusable addresses. + // for TPROXY spoofing we must skip unusable addresses. if (psstate->request->flags.spoofClientIp && !(fs->_peer && fs->_peer->options.no_tproxy) ) { if (ia->in_addrs[n].IsIPv4() != psstate->request->client_addr.IsIPv4()) { // we CAN'T spoof the address on this link. find another. === modified file 'src/tunnel.cc' --- src/tunnel.cc 2013-02-12 11:34:35 +0000 +++ src/tunnel.cc 2013-02-27 15:26:54 +0000 @@ -541,7 +541,7 @@ TunnelStateData *tunnelState = (TunnelStateData *)data; debugs(26, 3, HERE << server << ", tunnelState=" << tunnelState); - if (tunnelState->request && (tunnelState->request->flags.spoofClientIp || tunnelState->request->flags.intercepted)) + if (tunnelState->request && (tunnelState->request->flags.interceptTproxy || tunnelState->request->flags.intercepted)) tunnelStartShoveling(tunnelState); // ssl-bumped connection, be quiet else { AsyncCall::Pointer call = commCbCall(5,5, "tunnelConnectedWriteDone",