From owner-freebsd-net@FreeBSD.ORG Sun Aug 3 13:44:16 2008 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 138A0106568A for ; Sun, 3 Aug 2008 13:44:16 +0000 (UTC) (envelope-from mtm@wubethiopia.com) Received: from dire.wubethiopia.com (j071.v.rootbsd.net [208.79.82.223]) by mx1.freebsd.org (Postfix) with ESMTP id CA1938FC15 for ; Sun, 3 Aug 2008 13:44:15 +0000 (UTC) (envelope-from mtm@wubethiopia.com) Received: from rogue.mike.lan (unknown [213.55.65.140]) by dire.wubethiopia.com (Postfix) with ESMTPSA id 45F184FDA214; Sun, 3 Aug 2008 13:44:09 +0000 (UTC) Message-ID: <4895B799.6070508@wubethiopia.com> Date: Sun, 03 Aug 2008 16:50:17 +0300 From: Mike Makonnen User-Agent: Thunderbird 2.0.0.12 (X11/20080323) MIME-Version: 1.0 To: Ian Smith References: In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Cc: Patrick Tracanelli , freebsd-net@freebsd.org Subject: Re: Application layer classifier for ipfw X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 Aug 2008 13:44:16 -0000 Ian Smith wrote: > On Fri, 1 Aug 2008, Mike Makonnen wrote: > > Patrick Tracanelli wrote: > > > Mike Makonnen escreveu: > > >> Hi, > > >> > > >> An Internet Cafe I do some work for was recently having problems with > > >> very slow internet access. It turns out customers were running P2P > > >> file sharing applications which were hogging all the bandwidth. I > > >> looked for programs that would allow me to shape traffic according > > >> to the application layer protocol, but couldn't find any for FreeBSD. > > >> I found a couple: l7-filter and ipp2p, but these are Linux specific. > > >> So, I decided to write one. The result is ipfw-classifyd : > > >> http://people.freebsd.org/~mtm/ipfw-classifyd.tar.bz2 > > This is great, Mike. I've been 'waiting for this' for a very similar > situation for months now, getting by with dummynet bandwidth limiting > and wondering about weighted queuing, but this is a much sharper tool. > > > >> As the name implies it uses ipfw(4) to implement a userland daemon > > >> that classifies TCP and UDP packets according to regular expression > > >> patterns for various protocols. It's intended to be used with > > >> divert(4) sockets and dummynet(4) so you can do traffic shaping > > >> depending on the application level protocol. The protocol patterns > > >> are from the l7-filter project. > > Any GPL issues with using these patterns? > I don't believe so. > > >> Basically, you use ipfw(8) to divert tcp/udp packets to the damon. It > > >> reads its configuration file for a list of protocols and ipfw(8) > > >> rules. Then, when it detects a matching session it re-injects the > > >> packet back at the specified rule number. The tarball has a sample > > >> configuration file and firewall script to get you started. > > I was confused by 'back at the specified rule number' too, especially as > you used a rule 1000 in the example, being the rule handling NON matched > packets. So I had a browse through the code, finding: > > /* > * Inform divert(4) what rule to send it to by > * modifying the port number of the associated sockaddr_in > * structure. Note: we subtract one from the ipfw(4) rule > * number because processing in ipfw(4) will start with > * the next rule *after* the supplied rule number. > */ > if (flow->if_fwrule != 0) { > pkt->fp_saddr.sin_port = flow->if_fwrule; > goto enqueue; > } > > and noticed that we weren't subtracting one .. > The comment is wrong. It was for a prior version of the code. Initially, I had the configuration file specify the rule number that passes the diverted packets to dummynet(4). The code (as the comment says) would subtract 1 from the number when it wrote the packet back, but I wasn't sure how ipfw(4) would react to a possibly non-existant rule so changed it to its current form. However, after thinking about it some more I think it is more intuitive and easier to understand if the configuration file specified the rule that passes the diverted packet to the pipe or queue. > I don't believe it's quite correct to say 'ipfw will start with the next > rule after the supplied rule number'. If there were (legitimately) > multiple rules having the same number (either divert rules themselves or > at the target rule), the ipfw divert-return code skips past duplicates > to the next rule that has a higher rule number, which may not amount to > the same thing. > > (Sorry, Julian made me study ipfw execution behaviour months ago :) > > I thought at first that this behaviour is fine, and just needed a bit > better describing. But I'm starting to wonder if subtracting one isn't > really a better idea? > I'm leaning in the same direction. > > >> While I have not done extensive testing, preliminary tests are > > >> encouraging and it seems to work, so I thought I'd announce it to the > > >> rest of the world in case anyone else is interested in this kind of > > >> application. > > >> > > >> Comments and suggestions highly appreciated. > > >> > > >> Cheers. > > > > > > Wont compile on RELENG_6 but is working perfectly on REL_7. I am > > > trying hard with ssh, soulseek and msn. Its working like a charm with > > > the suggested rc.firewall. > > Can you email me the compile error? > > I'd like to run it on a 4.8 filtering bridge .. ah, never mind :) > > > > I have configured ipfw-classfyd.conf changing the rules, for a number > > > of L7 patterns, and now I try to understand why the "diverted" rules > > > only match if the rule number is 1 after the configured, ie, I put > > > soulseek to 65530 and a rule wont match there, but the very same rule > > > matches 65531. I will read the code, but it seems that reinjection of > > > the packet is made +1, correct? > > > > > The application doesn't do that, it's the firewall that does that. > > Basically, when > > ipfw(4) diverts a packet to the application it includes the rule > > that caused the packet to be diverted (so that when it gets it back it knows > > where to continue processing from). When it gets the packet back it > > continues > > processing the packet at the rule *after* the one that caused it to be > > diverted > > Rather, 'at the first rule having a higher rule number than the one ..' > > > (otherwise the packet would get diverted in an endless loop). In the sample > > script rule 1000 is the rule that passes the packets that do not get > > diverted, so > > I configured ipfw-classifyd to modify the information that comes with the > > packet to point to rule 1000 (in classifyd.conf). So, when ipfw(4) gets the > > packet back it continues processing it at the next rule after 1000, which is > > the rule that sends all diverted packets through the pipe. > > Yeah figuring out how rule 1000 had anything to do with it confused me > at first, when any number after the divert rule/s would do. I think it > may need stating really explicitly, something perhaps better put than: > > The rule number configured for the specified traffic type is that of > the last rule number *before* the target ipfw rule for a match. > > Which is still harder to describe (or get one's head around) than being > able to specify the desired target rule number in the config file? > > As long as you don't subtract one for the non-match packets reinjected > normally, and do subtract one from the matching packet's config rule, > so directly skipping to the specified rule, it would need an awful lot > less explaining to users .. > > > Hope that helps. > > Oh yes :) Might even have to upgrade that bridge at long last. > > Glad to hear people are finding it useful :-) Cheers. -- Mike Makonnen | GPG-KEY: http://people.freebsd.org/~mtm/mtm.asc mtm @ FreeBSD.Org | AC7B 5672 2D11 F4D0 EBF8 5279 5359 2B82 7CD4 1F55 FreeBSD | http://www.freebsd.org