diff -urN squid-3.3.1.vanilla/src/acl/DestinationIp.cc squid-3.3.1/src/acl/DestinationIp.cc --- squid-3.3.1.vanilla/src/acl/DestinationIp.cc 2013-02-09 07:30:01.000000000 +0000 +++ squid-3.3.1/src/acl/DestinationIp.cc 2013-02-25 16:25:17.000000000 +0000 @@ -54,7 +54,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); } diff -urN squid-3.3.1.vanilla/src/anyp/PortCfg.cc squid-3.3.1/src/anyp/PortCfg.cc --- squid-3.3.1.vanilla/src/anyp/PortCfg.cc 2013-02-09 07:30:01.000000000 +0000 +++ squid-3.3.1/src/anyp/PortCfg.cc 2013-02-25 16:25:17.000000000 +0000 @@ -58,7 +58,7 @@ b->defaultsite = xstrdup(defaultsite); b->intercepted = intercepted; - b->spoof_client_ip = spoof_client_ip; + b->interceptTproxy = interceptTproxy; b->accel = accel; b->allow_direct = allow_direct; b->vhost = vhost; diff -urN squid-3.3.1.vanilla/src/anyp/PortCfg.h squid-3.3.1/src/anyp/PortCfg.h --- squid-3.3.1.vanilla/src/anyp/PortCfg.h 2013-02-09 07:30:01.000000000 +0000 +++ squid-3.3.1/src/anyp/PortCfg.h 2013-02-25 16:25:17.000000000 +0000 @@ -30,7 +30,7 @@ char *defaultsite; /* default web site */ unsigned int intercepted:1; /**< intercepting proxy port */ - unsigned int spoof_client_ip:1; /**< spoof client ip if possible */ + unsigned int interceptTproxy:1; /**< TPROXY port */ unsigned int accel:1; /**< HTTP accelerator */ unsigned int allow_direct:1; /**< Allow direct forwarding in accelerator mode */ unsigned int vhost:1; /**< uses host header */ diff -urN squid-3.3.1.vanilla/src/auth/Acl.cc squid-3.3.1/src/auth/Acl.cc --- squid-3.3.1.vanilla/src/auth/Acl.cc 2013-02-09 07:30:01.000000000 +0000 +++ squid-3.3.1/src/auth/Acl.cc 2013-02-25 16:25:17.000000000 +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 { diff -urN squid-3.3.1.vanilla/src/cache_cf.cc squid-3.3.1/src/cache_cf.cc --- squid-3.3.1.vanilla/src/cache_cf.cc 2013-02-09 07:30:01.000000000 +0000 +++ squid-3.3.1/src/cache_cf.cc 2013-02-25 16:25:17.000000000 +0000 @@ -3556,13 +3556,13 @@ /* modes first */ if (strcmp(token, "accel") == 0) { - if (s->intercepted || s->spoof_client_ip) { + if (s->intercepted || s->interceptTproxy) { debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: Accelerator mode requires its own port. It cannot be shared with other modes."); self_destruct(); } s->accel = s->vhost = 1; } else if (strcmp(token, "transparent") == 0 || strcmp(token, "intercept") == 0) { - if (s->accel || s->spoof_client_ip) { + if (s->accel || s->interceptTproxy) { debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: Intercept mode requires its own interception port. It cannot be shared with other modes."); self_destruct(); } @@ -3584,7 +3584,7 @@ debugs(3,DBG_CRITICAL, "FATAL: http(s)_port: TPROXY option requires its own interception port. It cannot be shared with other modes."); self_destruct(); } - s->spoof_client_ip = 1; + s->interceptTproxy = 1; Ip::Interceptor.StartTransparency(); /* Log information regarding the port modes under transparency. */ debugs(3, DBG_IMPORTANT, "Starting IP Spoofing on port " << s->s); @@ -3794,7 +3794,7 @@ #if USE_SSL if (strcasecmp(protocol, "https") == 0) { /* ssl-bump on https_port configuration requires either tproxy or intercept, and vice versa */ - const bool hijacked = s->spoof_client_ip || s->intercepted; + const bool hijacked = s->interceptTproxy || s->intercepted; if (s->sslBump && !hijacked) { debugs(3, DBG_CRITICAL, "FATAL: ssl-bump on https_port requires tproxy/intercept which is missing."); self_destruct(); @@ -3832,7 +3832,7 @@ if (s->intercepted) storeAppendPrintf(e, " intercept"); - else if (s->spoof_client_ip) + else if (s->interceptTproxy) storeAppendPrintf(e, " tproxy"); else if (s->accel) { diff -urN squid-3.3.1.vanilla/src/cf.data.pre squid-3.3.1/src/cf.data.pre --- squid-3.3.1.vanilla/src/cf.data.pre 2013-02-09 07:30:01.000000000 +0000 +++ squid-3.3.1/src/cf.data.pre 2013-02-25 16:25:17.000000000 +0000 @@ -1133,6 +1133,26 @@ 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 @@ -2788,6 +2808,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. diff -urN squid-3.3.1.vanilla/src/client_side.cc squid-3.3.1/src/client_side.cc --- squid-3.3.1.vanilla/src/client_side.cc 2013-02-09 07:30:01.000000000 +0000 +++ squid-3.3.1/src/client_side.cc 2013-02-25 16:25:17.000000000 +0000 @@ -2674,7 +2674,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())) { @@ -3575,7 +3582,7 @@ else { char buf[MAX_IPSTRLEN]; assert(bumpMode != Ssl::bumpNone && bumpMode != Ssl::bumpEnd); - HttpRequest *fakeRequest = new HttpRequest; + HttpRequest *fakeRequest = HTTPMSGLOCK(new HttpRequest); fakeRequest->SetHost(details->local.NtoA(buf, sizeof(buf))); fakeRequest->port = details->local.GetPort(); fakeRequest->clientConnectionManager = connState; @@ -3584,10 +3591,18 @@ fakeRequest->indirect_client_addr = connState->clientConnection->remote; #endif fakeRequest->my_addr = connState->clientConnection->local; - fakeRequest->flags.spoofClientIp = ((connState->clientConnection->flags & COMM_TRANSPARENT) != 0 ) ; + fakeRequest->myportname = connState->port->name; + fakeRequest->flags.interceptTproxy = ((connState->clientConnection->flags & COMM_TRANSPARENT) != 0); + if (fakeRequest->flags.interceptTproxy) { + if (Config.accessList.spoof_client_ip) { + ACLFilledChecklist checklist(Config.accessList.spoof_client_ip, fakeRequest, NULL); + fakeRequest->flags.spoofClientIp = checklist.fastCheck() == ACCESS_ALLOWED; + } else fakeRequest->flags.spoofClientIp = 1; + } else fakeRequest->flags.spoofClientIp = 0; fakeRequest->flags.intercepted = ((connState->clientConnection->flags & COMM_INTERCEPTION) != 0); debugs(33, 4, HERE << details << " try to generate a Dynamic SSL CTX"); connState->switchToHttps(fakeRequest, bumpMode); + HTTPMSGUNLOCK(fakeRequest); } } @@ -3950,7 +3965,7 @@ debugs(33, 5, HERE << "Error while bumping: " << sslConnectHostOrIp); Ip::Address intendedDest; intendedDest = sslConnectHostOrIp.termedBuf(); - const bool isConnectRequest = !port->spoof_client_ip && !port->intercepted; + const bool isConnectRequest = !port->interceptTproxy && !port->intercepted; // Squid serves its own error page and closes, so we want // a CN that causes no additional browser errors. Possible @@ -4031,7 +4046,7 @@ // then pass back when active so we can start a TcpAcceptor subscription. s->listenConn = new Comm::Connection; s->listenConn->local = s->s; - s->listenConn->flags = COMM_NONBLOCKING | (s->spoof_client_ip ? COMM_TRANSPARENT : 0) | (s->intercepted ? COMM_INTERCEPTION : 0); + s->listenConn->flags = COMM_NONBLOCKING | (s->interceptTproxy ? COMM_TRANSPARENT : 0) | (s->intercepted ? COMM_INTERCEPTION : 0); // setup the subscriptions such that new connections accepted by listenConn are handled by HTTP typedef CommCbFunPtrCallT AcceptCall; @@ -4085,7 +4100,7 @@ // Fill out a Comm::Connection which IPC will open as a listener for us s->listenConn = new Comm::Connection; s->listenConn->local = s->s; - s->listenConn->flags = COMM_NONBLOCKING | (s->spoof_client_ip ? COMM_TRANSPARENT : 0) | + s->listenConn->flags = COMM_NONBLOCKING | (s->interceptTproxy ? COMM_TRANSPARENT : 0) | (s->intercepted ? COMM_INTERCEPTION : 0); // setup the subscriptions such that new connections accepted by listenConn are handled by HTTPS @@ -4118,7 +4133,7 @@ debugs(1, DBG_IMPORTANT, "Accepting " << (s->intercepted ? "NAT intercepted " : "") << - (s->spoof_client_ip ? "TPROXY spoofing " : "") << + (s->interceptTproxy ? "TPROXY intercepted " : "") << (s->sslBump ? "SSL bumped " : "") << (s->accel ? "reverse-proxy " : "") << FdNote(portTypeNote) << " connections at " diff -urN squid-3.3.1.vanilla/src/client_side_request.cc squid-3.3.1/src/client_side_request.cc --- squid-3.3.1.vanilla/src/client_side_request.cc 2013-02-09 07:30:01.000000000 +0000 +++ squid-3.3.1/src/client_side_request.cc 2013-02-25 16:25:17.000000000 +0000 @@ -664,7 +664,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() << @@ -924,7 +924,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; /* diff -urN squid-3.3.1.vanilla/src/format/Format.cc squid-3.3.1/src/format/Format.cc --- squid-3.3.1.vanilla/src/format/Format.cc 2013-02-09 07:30:01.000000000 +0000 +++ squid-3.3.1/src/format/Format.cc 2013-02-25 16:25:17.000000000 +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) { diff -urN squid-3.3.1.vanilla/src/forward.cc squid-3.3.1/src/forward.cc --- squid-3.3.1.vanilla/src/forward.cc 2013-02-09 07:30:01.000000000 +0000 +++ squid-3.3.1/src/forward.cc 2013-02-25 16:25:17.000000000 +0000 @@ -147,7 +147,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(); @@ -729,7 +729,7 @@ // For intercepted connections, set the host name to the server // certificate CN. Otherwise, we just hope that CONNECT is using // a user-entered address (a host name or a user-entered IP). - const bool isConnectRequest = !request->clientConnectionManager->port->spoof_client_ip && + const bool isConnectRequest = !request->clientConnectionManager->port->interceptTproxy && !request->clientConnectionManager->port->intercepted; if (request->flags.sslPeek && !isConnectRequest) { if (X509 *srvX509 = errDetails->peerCert()) { @@ -826,7 +826,7 @@ // unless it was the CONNECT request with a user-typed address. const char *hostname = request->GetHost(); const bool hostnameIsIp = request->GetHostIsNumeric(); - const bool isConnectRequest = !request->clientConnectionManager->port->spoof_client_ip && + const bool isConnectRequest = !request->clientConnectionManager->port->interceptTproxy && !request->clientConnectionManager->port->intercepted; if (!request->flags.sslPeek || isConnectRequest) SSL_set_ex_data(ssl, ssl_ex_index_server, (void*)hostname); diff -urN squid-3.3.1.vanilla/src/HttpRequest.cc squid-3.3.1/src/HttpRequest.cc --- squid-3.3.1.vanilla/src/HttpRequest.cc 2013-02-09 07:30:01.000000000 +0000 +++ squid-3.3.1/src/HttpRequest.cc 2013-02-25 16:25:17.000000000 +0000 @@ -582,7 +582,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; if (protocol == AnyP::PROTO_HTTP) diff -urN squid-3.3.1.vanilla/src/peer_select.cc squid-3.3.1/src/peer_select.cc --- squid-3.3.1.vanilla/src/peer_select.cc 2013-02-09 07:30:01.000000000 +0000 +++ squid-3.3.1/src/peer_select.cc 2013-02-25 16:25:17.000000000 +0000 @@ -235,7 +235,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) { @@ -342,7 +342,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. diff -urN squid-3.3.1.vanilla/src/RequestFlags.h squid-3.3.1/src/RequestFlags.h --- squid-3.3.1.vanilla/src/RequestFlags.h 2013-02-09 07:30:01.000000000 +0000 +++ squid-3.3.1/src/RequestFlags.h 2013-02-25 16:25:17.000000000 +0000 @@ -83,11 +83,16 @@ bool accelerated :1; /** if set, ignore Cache-Control headers */ bool ignoreCc :1; + /// + /// Set for requests handled by an "intercept" or "tproxy" port. + bool interceptTproxy :1; /** set for intercepted requests */ bool intercepted :1; /** set if the Host: header passed verification */ bool hostVerified :1; - /** request to spoof the client ip */ + /// 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; diff -urN squid-3.3.1.vanilla/src/SquidConfig.h squid-3.3.1/src/SquidConfig.h --- squid-3.3.1.vanilla/src/SquidConfig.h 2013-02-09 07:30:01.000000000 +0000 +++ squid-3.3.1/src/SquidConfig.h 2013-02-25 16:25:17.000000000 +0000 @@ -398,6 +398,9 @@ #if ICAP_CLIENT acl_access* icap; #endif + /// spoof_client_ip squid.conf acl. + /// nil unless configured + acl_access* spoof_client_ip; } accessList; AclDenyInfoList *denyInfoList; diff -urN squid-3.3.1.vanilla/src/tools.cc squid-3.3.1/src/tools.cc --- squid-3.3.1.vanilla/src/tools.cc 2013-02-09 07:30:01.000000000 +0000 +++ squid-3.3.1/src/tools.cc 2013-02-25 16:25:17.000000000 +0000 @@ -1169,7 +1169,7 @@ AnyP::PortCfg *p = NULL; if ((p = Config.Sockaddr.http)) { // skip any special interception ports - while (p && (p->intercepted || p->spoof_client_ip)) + while (p && (p->intercepted || p->interceptTproxy)) p = p->next; if (p) return p->s.GetPort(); @@ -1178,7 +1178,7 @@ #if USE_SSL if ((p = Config.Sockaddr.https)) { // skip any special interception ports - while (p && (p->intercepted || p->spoof_client_ip)) + while (p && (p->intercepted || p->interceptTproxy)) p = p->next; if (p) return p->s.GetPort(); diff -urN squid-3.3.1.vanilla/src/tunnel.cc squid-3.3.1/src/tunnel.cc --- squid-3.3.1.vanilla/src/tunnel.cc 2013-02-09 07:30:01.000000000 +0000 +++ squid-3.3.1/src/tunnel.cc 2013-02-25 16:25:17.000000000 +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",