]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Bug #14: connection setup may look like syn flood attack if server is
authorhno <>
Sat, 3 Apr 2004 21:07:38 +0000 (21:07 +0000)
committerhno <>
Sat, 3 Apr 2004 21:07:38 +0000 (21:07 +0000)
refusing connection

If the contacted server refuses connection then the repeated attempts to
connect to the server may look like a syn flood attack. This patch makes
Squid behave a little friendler in such case and:
 * Delays a little between the repeated attempts. Longer if the attempt
was to an origin server.
 * Limits origin server attempts to 3 connection setup attempts or 2 request
forwarding attempts (was 10 on both which only makes sense in peering
relations)
 * Changes the default for maximum_single_addr_tries to 1 as there is plenty
of reforwarding attempts done by Squid and at least 3 attempts to initiate
the request which makes this directive redundant.
 * removes a redundant lock from commConnect*() (cbdata managed)
 * Adds a small delay to commConnect() reconnection attempts when the
contacted destination has more than one IP address or
maximum_single_addr_tries is used.
 * Small cleanup in how/when digest considers a peer usable to not disturb
the peer probing.
 * Cleanup of peer TCP probing to correct timeout management etc and to
more promptly recover after a failure.

src/cf.data.pre
src/comm.cc
src/forward.cc
src/neighbors.cc
src/structs.h

index 4a0e1c4dfc637ed066efb367dcda1ded2de893c8..8e31b02d7975e1c56f7cc54ba1b54fb0ce5a5254 100644 (file)
@@ -1,6 +1,6 @@
 
 #
-# $Id: cf.data.pre,v 1.344 2004/01/06 03:44:11 hno Exp $
+# $Id: cf.data.pre,v 1.345 2004/04/03 14:07:38 hno Exp $
 #
 #
 # SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -3523,15 +3523,18 @@ DOC_END
 NAME: maximum_single_addr_tries
 TYPE: int
 LOC: Config.retry.maxtries
-DEFAULT: 3
+DEFAULT: 1
 DOC_START
        This sets the maximum number of connection attempts for a
        host that only has one address (for multiple-address hosts,
        each address is tried once).
 
-       The default value is three tries, the (not recommended)
+       The default value is one attempt, the (not recommended)
        maximum is 255 tries.  A warning message will be generated
        if it is set to a value greater than ten.
+
+       Note: This is in addition to the request reforwarding which
+       takes place if Squid fails to get a satisfying response.
 DOC_END
 
 NAME: snmp_port
@@ -3543,6 +3546,10 @@ DOC_START
        Squid can now serve statistics and status information via SNMP.
        By default it listens to port 3401 on the machine. If you don't
        wish to use SNMP, set this to "0".
+
+       Note: If you want Squid to use parents for all requests then see
+       the never_direct directive. prefer_direct only modifies how Squid
+       acts on cachable requests.
 DOC_END
 
 NAME: snmp_access
index d74ec3334d6c95bdb053459d83e0ee3afe02b7b8..fe6e5aa1764b2952a7fb6d9ccd7180833fd00131 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: comm.cc,v 1.393 2004/03/01 01:37:34 adrian Exp $
+ * $Id: comm.cc,v 1.394 2004/04/03 14:07:38 hno Exp $
  *
  * DEBUG: section 5     Socket Functions
  * AUTHOR: Harvest Derived
@@ -66,7 +66,6 @@ public:
     CallBack<CNCB> callback;
 
     struct in_addr in_addr;
-    int locks;
     int fd;
     int tries;
     int addrcount;
@@ -1304,7 +1303,6 @@ commConnectStart(int fd, const char *host, u_short port, CNCB * callback, void *
     cs->port = port;
     cs->callback = CallBack<CNCB>(callback, data);
     comm_add_close_handler(fd, commConnectFree, cs);
-    cs->locks++;
     ipcache_nbgethostbyname(host, commConnectDnsHandle, cs);
 }
 
@@ -1312,8 +1310,6 @@ static void
 commConnectDnsHandle(const ipcache_addrs * ia, void *data)
 {
     ConnectStateData *cs = (ConnectStateData *)data;
-    assert(cs->locks == 1);
-    cs->locks--;
 
     if (ia == NULL) {
         debug(5, 3) ("commConnectDnsHandle: Unknown host: %s\n", cs->host);
@@ -1466,6 +1462,13 @@ commRetryConnect(ConnectStateData * cs)
     return commResetFD(cs);
 }
 
+static void
+commReconnect(void *data)
+{
+    ConnectStateData *cs = (ConnectStateData *)data;
+    ipcache_nbgethostbyname(cs->host, commConnectDnsHandle, cs);
+}
+
 /* Connect SOCK to specified DEST_PORT at DEST_HOST. */
 void
 ConnectStateData::Connect (int fd, void *me)
@@ -1512,8 +1515,7 @@ ConnectStateData::connect()
             netdbDeleteAddrNetwork(S.sin_addr);
 
         if (commRetryConnect(this)) {
-            locks++;
-            ipcache_nbgethostbyname(host, commConnectDnsHandle, this);
+            eventAdd("commReconnect", commReconnect, this, this->addrcount == 1 ? 0.05 : 0.0, 0);
         } else {
             callCallback(COMM_ERR_CONNECT, errno);
         }
index 6b276f659f56d68ca047b30716ca023c686471dc..81a215da8290155330d636ce02fdf98bde7b0104 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: forward.cc,v 1.115 2003/11/09 11:05:24 hno Exp $
+ * $Id: forward.cc,v 1.116 2004/04/03 14:07:39 hno Exp $
  *
  * DEBUG: section 17    Request Forwarding
  * AUTHOR: Duane Wessels
@@ -164,6 +164,9 @@ fwdCheckRetry(FwdState * fwdState)
     if (fwdState->n_tries > 10)
         return 0;
 
+    if (fwdState->origin_tries > 2)
+        return 0;
+
     if (squid_curtime - fwdState->start > Config.Timeout.connect)
         return 0;
 
@@ -220,6 +223,7 @@ fwdServerClosed(int fd, void *data)
     fwdState->server_fd = -1;
 
     if (fwdCheckRetry(fwdState)) {
+        int originserver = (fwdState->servers->_peer == NULL);
         debug(17, 3) ("fwdServerClosed: re-forwarding (%d tries, %d secs)\n",
                       fwdState->n_tries,
                       (int) (squid_curtime - fwdState->start));
@@ -241,11 +245,12 @@ fwdServerClosed(int fd, void *data)
                 /* Use next. The last "direct" entry is retried multiple times */
                 fwdState->servers = fs->next;
                 fwdServerFree(fs);
+                originserver = 0;
             }
         }
 
-        /* use eventAdd to break potential call sequence loops */
-        eventAdd("fwdConnectStart", fwdConnectStart, fwdState, 0.0, 0);
+        /* use eventAdd to break potential call sequence loops and to slow things down a little */
+        eventAdd("fwdConnectStart", fwdConnectStart, fwdState, originserver ? 0.05 : 0.005, 0);
 
         return;
     }
@@ -589,8 +594,14 @@ fwdConnectStart(void *data)
             debug(17, 3) ("fwdConnectStart: reusing pconn FD %d\n", fd);
             fwdState->server_fd = fd;
             fwdState->n_tries++;
+
+            if (!fs->_peer)
+                fwdState->origin_tries++;
+
             comm_add_close_handler(fd, fwdServerClosed, fwdState);
+
             fwdDispatch(fwdState);
+
             return;
         }
     }
@@ -627,6 +638,10 @@ fwdConnectStart(void *data)
 
     fwdState->server_fd = fd;
     fwdState->n_tries++;
+
+    if (!fs->_peer)
+        fwdState->origin_tries++;
+
     /*
      * stats.conn_open is used to account for the number of
      * connections that we have open to the peer, so we can limit
@@ -809,6 +824,9 @@ fwdReforward(FwdState * fwdState)
     if (fwdState->n_tries > 9)
         return 0;
 
+    if (fwdState->origin_tries > 1)
+        return 0;
+
     if (fwdState->request->flags.body_sent)
         return 0;
 
index 11c822729445c689c713021763ea574fc688e0bb..dac8c3dfddf059e11f31cbf825f4bd198d12c10c 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: neighbors.cc,v 1.324 2003/10/16 21:40:16 robertc Exp $
+ * $Id: neighbors.cc,v 1.325 2004/04/03 14:07:39 hno Exp $
  *
  * DEBUG: section 15    Neighbor Routines
  * AUTHOR: Harvest Derived
@@ -55,8 +55,7 @@ static void neighborAliveHtcp(peer *, const MemObject *, const htcpReplyData *);
 static void neighborCountIgnored(peer *);
 static void peerRefreshDNS(void *);
 static IPH peerDNSConfigure;
-static void peerProbeConnect(peer *);
-static IPH peerProbeConnect2;
+static int peerProbeConnect(peer *);
 static CNCB peerProbeConnectDone;
 static void peerCountMcastPeersDone(void *data);
 static void peerCountMcastPeersStart(void *data);
@@ -794,21 +793,17 @@ peerDigestLookup(peer * p, HttpRequest * request)
     if (!p->digest) {
         debug(15, 5) ("peerDigestLookup: gone!\n");
         return LOOKUP_NONE;
-    } else if (!peerHTTPOkay(p, request)) {
-        debug(15, 5) ("peerDigestLookup: !peerHTTPOkay\n");
-        return LOOKUP_NONE;
-    } else if (p->digest->flags.usable) {
-        debug(15, 5) ("peerDigestLookup: usable\n");
-        /* fall through; put here to have common case on top */
-        ;
     } else if (!p->digest->flags.needed) {
         debug(15, 5) ("peerDigestLookup: note need\n");
         peerDigestNeeded(p->digest);
         return LOOKUP_NONE;
-    } else {
+    } else if (!p->digest->flags.usable) {
         debug(15, 5) ("peerDigestLookup: !ready && %srequested\n",
                       p->digest->flags.requested ? "" : "!");
         return LOOKUP_NONE;
+    } else if (!peerHTTPOkay(p, request)) {
+        debug(15, 5) ("peerDigestLookup: !peerHTTPOkay\n");
+        return LOOKUP_NONE;
     }
 
     debug(15, 5) ("peerDigestLookup: OK to lookup peer %s\n", p->host);
@@ -1230,8 +1225,8 @@ int
 neighborUp(const peer * p)
 {
     if (!p->tcp_up) {
-        peerProbeConnect((peer *) p);
-        return 0;
+        if (!peerProbeConnect((peer *) p))
+            return 0;
     }
 
     if (p->options.no_query)
@@ -1356,8 +1351,8 @@ peerRefreshDNS(void *data)
     eventAddIsh("peerRefreshDNS", peerRefreshDNS, NULL, 3600.0, 1);
 }
 
-void
-peerConnectFailed(peer * p)
+static void
+peerConnectFailedSilent(peer * p)
 {
     p->stats.last_connect_failure = squid_curtime;
 
@@ -1366,7 +1361,6 @@ peerConnectFailed(peer * p)
         return;
     }
 
-    debug(15, 1) ("TCP connection to %s/%d failed\n", p->host, p->http_port);
     p->tcp_up--;
 
     if (!p->tcp_up) {
@@ -1376,6 +1370,13 @@ peerConnectFailed(peer * p)
     }
 }
 
+void
+peerConnectFailed(peer *p)
+{
+    debug(15, 1) ("TCP connection to %s/%d failed\n", p->host, p->http_port);
+    peerConnectFailedSilent(p);
+}
+
 void
 peerConnectSucceded(peer * p)
 {
@@ -1389,42 +1390,51 @@ peerConnectSucceded(peer * p)
     p->tcp_up = PEER_TCP_MAGIC_COUNT;
 }
 
-/*
- * peerProbeConnect will be called on dead peers by neighborUp 
- */
 static void
+peerProbeConnectTimeout(int fd, void *data)
+{
+    peer * p = (peer *)data;
+    comm_close(fd);
+    p->test_fd = -1;
+    peerConnectFailedSilent(p);
+}
+
+/*
+* peerProbeConnect will be called on dead peers by neighborUp 
+*/
+static int
 peerProbeConnect(peer * p)
 {
     int fd;
+    time_t ctimeout = p->connect_timeout > 0 ? p->connect_timeout
+                      : Config.Timeout.peer_connect;
+    int ret = squid_curtime - p->stats.last_connect_failure > ctimeout * 10;
 
     if (p->test_fd != -1)
-        return;                        /* probe already running */
+        return ret;/* probe already running */
 
-    if (squid_curtime - p->stats.last_connect_probe < 1)
-        return;                        /* don't probe to often */
+    if (squid_curtime - p->stats.last_connect_probe == 0)
+        return ret;/* don't probe to often */
 
     fd = comm_open(SOCK_STREAM, IPPROTO_TCP, getOutgoingAddr(NULL),
                    0, COMM_NONBLOCKING, p->host);
 
     if (fd < 0)
-        return;
+        return ret;
+
+    commSetTimeout(fd, ctimeout, peerProbeConnectTimeout, p);
 
     p->test_fd = fd;
 
     p->stats.last_connect_probe = squid_curtime;
 
-    ipcache_nbgethostbyname(p->host, peerProbeConnect2, p);
-}
-
-static void
-peerProbeConnect2(const ipcache_addrs * ianotused, void *data)
-{
-    peer *p = (peer *)data;
     commConnectStart(p->test_fd,
                      p->host,
                      p->http_port,
                      peerProbeConnectDone,
                      p);
+
+    return ret;
 }
 
 static void
@@ -1435,7 +1445,7 @@ peerProbeConnectDone(int fd, comm_err_t status, int xerrno, void *data)
     if (status == COMM_OK) {
         peerConnectSucceded(p);
     } else {
-        peerConnectFailed(p);
+        peerConnectFailedSilent(p);
     }
 
     comm_close(fd);
index 86761ed5f5b08fc1f47de4838e6178225c793f04..69cd4ee34a7baf67a397f5da81c50ee844d1e9bf 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: structs.h,v 1.484 2003/10/20 12:33:01 robertc Exp $
+ * $Id: structs.h,v 1.485 2004/04/03 14:07:39 hno Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -1841,6 +1841,7 @@ struct _FwdState
     ErrorState *err;
     time_t start;
     int n_tries;
+    int origin_tries;
 #if WIP_FWD_LOG
 
     http_status last_status;