On 26.02.13 21:56, Amos Jeffries wrote:

I'm happy with the use-case too now. If the code adjusted to 3.HEAD
still looks good I think it could go in.

I've attached a patch against 3.HEAD. I've tested it, although I would appreciate it if you could double check that I'm using HttpRequest::Pointer correctly in client_side.cc.

As well as the spoof_client_ip ACL, this introduces a new request flag called interceptTproxy, which is set for all TPROXY requests. The spoofClientIp flag is now only set for TPROXY requests that we want to spoof.

Many thanks.

--

 - Steve Hill
   Technical Director
   Opendium Limited     http://www.opendium.com

Direct contacts:
   Instant messager: xmpp:st...@opendium.com
   Email:            st...@opendium.com
   Phone:            sip:st...@opendium.com

Sales / enquiries contacts:
   Email:            sa...@opendium.com
   Phone:            +44-844-9791439 / sip:sa...@opendium.com

Support contacts:
   Email:            supp...@opendium.com
   Phone:            +44-844-4844916 / sip:supp...@opendium.com
=== 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",

Reply via email to