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<CommAcceptCbPtrFun> 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",

