mod_leech: Per-user download limits for Apache 1.3.x

By Abhijit Menon-Sen <ams@toroid.org>

2007-09-29

mod_leech is an Apache 1.3.x module which uses a MySQL database to enforce per-user download and concurrent-login quotas.

The module uses the following table to track and limit the activity of users identified by HTTP basic authentication:

create table users (
    user varchar(32) not null primary key,
    -- How many concurrent connections does this user have?
    logins bigint,
    -- How many bytes has this user downloaded?
    bytes bigint,
    -- How many of each are allowed?
    maxlogins bigint,
    maxbytes bigint
);

When a user exceeds either quota, mod_leech can redirect them to an error page (à la ErrorDocument), providing "user=name" and "quota=logins" or "quota=bytes" parameters to enable customised error handling.

The module maintains a pool of active database connections, and shares them between Apache processes. (The size of the pool is configurable, but only globally.)

All other configuration (which database server to talk to, how to authenticate, which table to use, and where to redirect) is per-VirtualHost.

Source code

Download mod_leech.tar.gz

This code is provided here with no warranty, and may be freely used, modified, or redistributed provided that derivative works are clearly identified as being different from the original, and copyright notices in the source are preserved. (The package includes a complete license statement.)

The package includes portions of Konstantin Knizhnik's very useful POSIX.1b emulation code, because FreeBSD didn't (at the time) provide a native implementation of the semaphore operations I was using.

The package also includes a (FreeBSD-specific) patch to implement a highly dubious "copy protection" feature that compares the MAC address of the first Ethernet interface to an address stored in the source code, and refuses to load if they are not the same. Please ignore this patch (but see the history section below if you're curious about its origins).

Status

At the time this module was written (in October 2001), it was the only one I could find that implemented database connection pooling directly (that is, not counting things like Apache::DBI under mod_perl).

The module is preserved here because I think it's an interesting example (and because I put a lot of effort into it, and like the way it turned out), and not because I expect anyone will want to use it.

That said, the module worked perfectly the last time I tested it, which was in 2002 under Apache 1.3.2x (under Linux and FreeBSD). I have not tried to compile it against a recent Apache, but I would be surprised if there were any non-trivial problems.

(If you want to try it, for some reason, I'd be happy to help.)

A related (but not quite the same) module is mod_bandwidth, which can impose per-IP bandwidth and connection limits.

History

On the 29th of September, 2001 (exactly six years ago), I wrote to David Aninowsky of Choopa, LLC. He wanted an Apache module written, and a friend had referred me as someone who could do the job. This module was developed as a result.

Mr. Aninowsky and I reached an agreement over the next month, and I sent him a signed contract by FedEx near the end of October. Here's a summary of the terms of our proposed contract:

I started working on the module soon afterwards, but the advance payment (which was delayed by Mr. Aninowsky's work and travel schedules) arrived only on the 30th of November. I delivered an initial release for testing on the 3rd of December, despite the fact that I had not yet received my copy of the contract.

(An aside: Mr. Aninowsky insisted on my including a "copy protection" feature, whereby the module would refuse to load if the MAC address of the first Ethernet card did not match an address stored in the source. I advised him against it, but eventually implemented the check anyway.)

The subsequent testing period extended far beyond what we had originally planned (partly because I was on vacation in December, but also because we had to recompile Apache and so on), but I fixed a number of bugs we found while testing. On the 23rd of February 2002 (after a number of updates), I delivered a version with working connection pooling and all known bugs fixed. During this time, we would occasionally talk on EFnet IRC, and I explained a number of times how to compile, install, and configure the module, and discussed testing strategies.

At this point, Mr. Aninowsky had still not executed and returned the contract, despite repeated reminders. He was still testing the module occasionally, but the only substantial problem he reported was because of his FreeBSD kernel had SEMMNI set too low. I recommended setting the "LeechPool" to 8 for testing, and verified that this worked. I did not make any changes to the module after April 2002, because I had fixed all the bugs that had been reported.

After mid-April, Mr. Aninowsky stopped responding to email from me. I sent him mail on the 15th, 20th, 24th, and 28th of April, then on the 7th and 9th of May. On the 21st of May, I sent the following message:

Hi.

David, I think you're being very unprofessional by not replying to my
email, not talking to me on IRC, and not sending me the money (or the
paperwork) I'm owed. I realise that you must be busy with other work,
but that doesn't mean that you can ignore commitments you have made.

I've enjoyed working on mod_leech, and I don't want our relationship
soured. Please write back to me soon, and let us clear this matter up
amicably.

He responded on the same day:

Sorry for the misunderstanding I guess, I've been super busy and I am
closing on my house this month, so I've been running around doing that
plus building the datacenter out with another 30 racks.  If you want I
can fax you the contract and I will wire you the funds shortly,  I never
rip anyone off and I really do apologize for the delay in getting
everything done... I haven't even had a chance to beta test the darn
module yet!  Its disappointing to me because this will be huge when I
launch it.

I sent him a fax number and repeated the instructions on how to transfer money to my bank account. A week later, neither contract nor money had arrived. On the 14th of June (after three reminders by email, and many attempts to contact him on IRC), I sent the following:

Three weeks. Still no money, no fax, no email...

His response was classic.

Yea I'm afraid to send money to India they'll think I'm funding
terrorists.

I had no remaining illusions about Mr. Aninowsky's integrity, so I spoke to a friend of mine who practices law in Massachusetts. It was clear to me that pursuing any legal claims against Choopa would be too expensive to consider, and I had already written off the money owed to me, but I wanted to see what my options were.

We agreed that she (my lawyer friend, for whose help I am very grateful) would write to him stating our case, and that we would let the matter rest if he didn't respond favourably. Among other things, she wrote:

Mr. Menon-Sen informs me that you have expressed concern about paying
him because he resides in India. If this is what is impeding payment,
you may send a check made out to me or a money order to my office in
Boston. I will then forward the payment to Mr. Menon-Sen.

Mr. Aninowsky's response was, not surprisingly, belligerent and full of bluster.

Dear Sir/Madam,

Mr Menon-Sen was asked to do a small project for us, with a payment of
$1,000.00USD placed up front.    As far as I'm concerned we should be
going after him for the $1,000 and the loss of business due to the fact
that the project was never completed as promised by him. The work was
never completed to a satisfactory level and the fact that there was no
contract between Mr Menon-Son and our company meant we could take no
action to have the work completed in a timely and correct fashion.  Any
legal claims your client has are fruitless.

Good Day,
David Aninowsky
President
Choopa, LLC

Of course, the only reason we didn't have a contract was because he refused to sign and return the one I sent him; and the fact that he reported no problems with the module after April 2002 rather belies his claim that it was never completed.

Conclusion

David Aninowsky is the CEO of Choopa, LLC, a co-location and hosting provider. Based on his irresponsible and unprofessional behaviour, and what seems to be a pattern of ignoring problems and hoping they go away, I cannot recommend that anyone do business with him.

I am glad that I got to write mod_leech, but I would have been happier still if my work had not been wasted.

Thank you, Dave. You taught me a valuable lesson.