Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 18 Feb 2007 23:02:21 +0400
From:      admin <admin@azuni.net>
To:        freebsd-questions@freebsd.org
Cc:        Kees Plonsz <dit-is-een-zinloze-spampoging@jeremino.homeunix.net>
Subject:   Re: ipfw limit src-addr woes
Message-ID:  <45D8A2BD.2020903@azuni.net>

Next in thread | Raw E-Mail | Index | Archive | Help
> admin wrote in msgid:
> <list.freebsd.questions#45D85EA3.2050102@azuni.net>
> 
>> Hi, I'm trying to use ipfw's limit clause to limit the number of
>> connections a single IP can have at the same time in a transparent
>> web-proxy environment:
>> 
>> 00350 skipto 401 tcp from x.x.x.x/x,y.y.y.y/y,z.z.z.z/z to any dst-port
>> 80 in via if0 setup limit src-addr 10
>> 00401 fwd local.ip.ad.dr,8080 tcp from x.x.x.x/x to any dst-port 80
>> ... the rest fwd...
>> 
>> as I understand the manpage, when the current number of connectiions is
>> below 10, the action "skipto" is performed, else, the packet is dropped
>> and the search terminates. But...
>> 
>> the problem is that the src-addr limit is not enforced as some clients
>> somehow open a huge number (3-5 times the prescribed value) of
>> www-connections to some single address Out There, forcing you to bump up
>> certain sysctl variables (such as kern.ipc.nmbclusters,
>> kern.ipc.maxsockets, etc.) to mitigate the DOS effects. What might be
>> going on? Is ipfw broken, or am I misusing it?
>> 
>> OS: FreeBSD 6.2
> 
> 
> I tested ipfw with the "limit" option and it works just fine.
> I can open only one http connection from "194.109.21.3" and hangs on
> opening a second one with an error in the logfile.
> 
> 
> rule:
> # add 03000 allow log logamount 50 tcp from any to any dst-port 80 in limit dst-addr 1
> 
> My logfile:
> Feb 18 16:16:57 jeremino kernel: ipfw: 3000 Accept TCP 194.109.21.3:3626 10.0.0.6:80 in via dc1
> Feb 18 16:16:58 jeremino kernel: drop session, too many entries

You get the point. I know, indeed it works just great for many clients, 
including myself, but *some* clients manage to ignore the firewall rule 
and open many more connections in the ESTABLISHED state than allowed and 
eat up lots of memory with their send/recv queues... Instead of knocking 
my head on the wall I opted for posting here for help ;-)

I've decided to prove that I'm not crazy. This little code utilizes the 
BSD sockets API trying to open many connections to some outside web-site 
but just halts after crossing the limit (assuming the connections get 
transparently proxied by the problem firewalled-FreeBSD-proxy box on its 
path).

The question remains: why could some clients be immune to the limit?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define NUM_CONNS_TO_TRY_TO_OPEN 150

int main(void)
{
         struct sockaddr_in sock_addr;
         struct in_addr in_addr;
         int i;

         if (inet_aton("66.94.234.13", &in_addr) == 0) {
                 perror("inet_aton");
                 return EXIT_FAILURE;
         }

         sock_addr.sin_family = AF_INET;
         sock_addr.sin_addr = in_addr;
         sock_addr.sin_port = htons(80);
         for (i = 0; i < NUM_CONNS_TO_TRY_TO_OPEN; i++) {
                 int s;

                 if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == 
-1) {
                         perror("socket");
                         return EXIT_FAILURE;
                 }
                 if (connect(s, (struct sockaddr *) &sock_addr, sizeof 
sock_addr) != -1) {
                         fprintf(stderr, "%d ", i);
                 } else {
                         perror("connect");
                         return EXIT_FAILURE;
                 }
         }
         getchar();

         return 0;
}




Want to link to this message? Use this URL: <http://docs.FreeBSD.org/cgi/mid.cgi?45D8A2BD.2020903>