Looking into bug 3901 if we skip past the broken assumptions and drop half of the proposed patch...

The root cause of this report is that we have no way to selectively per-IP determine that the outgoing connection should not be made. We have miss_access/always_direct/never_direct acting at a gross per-request level which way destinations should be located. But nothing equivalent takes place after the particular destination IPs are identified.

The interesting part of the proposed bug fix is to allow tcp_outgoing_address selection produce an invalid output which causes the connection to be discarded from the set of upstream sources. I have polished that up a bit and submit here. The invalid address used is NOADDR, since ANYADDR is used for signalling system-assigned local IP.

I have also updated the documentation of tcp_outgoing_address to detail the special values that can be configured there and what they do.

Amos

=== modified file 'src/cache_cf.cc'
--- src/cache_cf.cc     2013-08-29 09:21:53 +0000
+++ src/cache_cf.cc     2013-08-30 07:57:05 +0000
@@ -1379,9 +1379,9 @@
         return;
     }
 
-    if (!strcmp(token,"any_addr"))
+    if (!strcmp(token,"any_addr") || !strcmp(token,"autoselect"))
         addr->setAnyAddr();
-    else if ( (!strcmp(token,"no_addr")) || (!strcmp(token,"full_mask")) )
+    else if ( (!strcmp(token,"no_addr")) || (!strcmp(token,"full_mask")) || 
(!strcmp(token,"none")))
         addr->setNoAddr();
     else if ( (*addr = token) ) // try parse numeric/IPA
         (void) 0;
@@ -1408,10 +1408,12 @@
     AclAddress *l;
 
     for (l = head; l; l = l->next) {
-        if (!l->addr.isAnyAddr())
+        if (l->addr.isAnyAddr())
+            storeAppendPrintf(entry, "%s autoselect", name);
+        else if (l->addr.isNoAddr())
+            storeAppendPrintf(entry, "%s none", name);
+        else
             storeAppendPrintf(entry, "%s %s", name, 
l->addr.toStr(buf,MAX_IPSTRLEN));
-        else
-            storeAppendPrintf(entry, "%s autoselect", name);
 
         dump_acl_list(entry, l->aclList);
 

=== modified file 'src/cf.data.pre'
--- src/cf.data.pre     2013-08-29 09:21:53 +0000
+++ src/cf.data.pre     2013-08-30 08:09:48 +0000
@@ -2105,8 +2105,24 @@
        Allows you to map requests to different outgoing IP addresses
        based on the username or source address of the user making
        the request.
-
-       tcp_outgoing_address ipaddr [[!]aclname] ...
+       These directives are tested individually for each upstream
+       destination IP address.
+
+               tcp_outgoing_address ipaddr [[!]aclname] ...
+
+       Special values for IP address:
+               autoselect      Let the operating system decide.
+                               This is the default.
+
+               0.0.0.0         Let the operating system decide, but only
+                               amongst IPv4 addresses.
+
+               ::              Let the operating system decide, but only
+                               amongst IPv6 addresses.
+
+               none            Do not use the destination IP being
+                               checked for.
+
 
        For example;
                Forwarding clients with dedicated IPs for certain subnets.
@@ -2131,11 +2147,6 @@
        Requests going to IPv6 websites will use the outgoing 2001:db8:* 
addresses.
 
 
-       NOTE: The use of this directive using client dependent ACLs is
-       incompatible with the use of server side persistent connections. To
-       ensure correct results it is best to set server_persistent_connections
-       to off when using this directive in such configurations.
-
        NOTE: The use of this directive to set a local IP on outgoing TCP links
        is incompatible with using TPROXY to set client IP out outbound TCP 
links.
        When needing to contact peers use the no-tproxy cache_peer option and 
the

=== modified file 'src/peer_select.cc'
--- src/peer_select.cc  2013-06-29 04:21:47 +0000
+++ src/peer_select.cc  2013-08-30 15:35:49 +0000
@@ -362,7 +362,8 @@
 
             // check for a configured outgoing address for this destination...
             getOutgoingAddress(psstate->request, p);
-            psstate->paths->push_back(p);
+            if (!p->local.isNoAddr())
+                psstate->paths->push_back(p);
         }
     } else {
         debugs(44, 3, HERE << "Unknown host: " << (fs->_peer ? fs->_peer->host 
: psstate->request->GetHost()));

Reply via email to