Application layer classifier for ipfw

Mike Makonnen mtm at wubethiopia.com
Sun Aug 3 13:44:16 UTC 2008


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



More information about the freebsd-net mailing list