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