I needed a quick script to provide 'Anti-Leeching' for some of my files. (Leeching is a method of stealing someone else's bandwidth by linking to their files instead of downloading the files to your own site.)
After several iterations, I finally have something that works pretty well for my .zip files.
Just put the hostname and the IP in the @HOSTS array for all your hosts that will use this script. As merlyn mentioned in one of his articles, everyone has a drawer where they keep miscellaneous items, this one belongs in your virtual drawer for that time when you need a quick anti-leech sub.
-- hiseldl What time is it? It's Camel Time!
Update: changed grep pattern because of merlyn's comment about reverse DNS. Thanks merlyn!
#!/usr/bin/perl -w
use strict;
use CGI qw/:standard/;
$|=1;
my $DIR = param('d') || './'; # default dir
my $FILE = param('f') || 'xyz.zip'; # default file
my @HOSTS = (
'www.myotherhost.com',
'10.0.0.2',
'www.myhost.com',
'10.0.0.1',
);
print header('text/plain'), "No access to $FILE"
unless DownloadFile($DIR, $FILE, \@HOSTS);
exit 0;
sub DownloadFile
{
my ($dir, $filename, $hosts) = @_;
my $remote = remote_host();
#### the following is bad because it is not an exact
#### match nor is it anchored
#### return(0) unless grep /$remote/, @$hosts;
# the following suggested by [merlyn]
return 0 unless grep $remote eq $_, @$hosts;
my $filesize = -s "$dir/$filename";
# print full header
print "Content-disposition: filename=$filename\n";
print "Content-Length: $filesize\n";
print "Content-Type: application/octet-stream\n\n";
# open in binmode
open(READ,$filename) || die;
binmode READ;
# stream it out
binmode STDOUT;
while (<READ>) { print; }
close(READ);
# should always return true
return(1);
}
•Re: anti leech CGI
by merlyn (Sage) on Oct 30, 2002 at 07:06 UTC
|
my $remote = remote_host();
return(0) unless grep /$remote/, @$hosts;
So, I just set my reverse DNS to return "." for my host, and I'm in. Some security.
Better yet, I set it to return "((.)*)*FOO", and it goes into a deep deep loop, burning CPU for some long-ish time.
What problem exactly were you trying to solve again?
If you want host-based authentication, use it. Don't try to reinvent it. Use your htaccess file to control the access to your URL.
-- Randal L. Schwartz, Perl hacker
Be sure to read my standard disclaimer if this is a reply.
| [reply] [d/l] |
|
While true that reinventing the wheel is a bad idea, wouldn't this work ok if it were just IP based?:
my $remote = $ENV{REMOTE_ADDR};
return(0) unless grep /$remote/, @$hosts;
BTW, wouldn't taint have caught this? He's trusting user supplied data (DNS name) in an unsafe way.
Update: See merlyn's reply on how to do this right.
-- Dan
| [reply] [d/l] |
|
my $remote = $ENV{REMOTE_ADDR};
return 0 unless grep $remote eq $_, @$hosts;
wouldn't taint have caught this? He's trusting user supplied data (DNS name) in an unsafe way.
No, because simply doing a regex match isn't considered
"external" enough for tainted data to abort it.
-- Randal L. Schwartz, Perl hacker
Be sure to read my standard disclaimer if this is a reply. | [reply] [d/l] [select] |
|
Nice! I would like to see what your comments are about 90% of the other 'anti-leech' scripts out there. None of the scripts that I have seen have any taint checking nor 'use strict.'
What problem exactly were you trying to solve again?
The problem I want to solve is to stop other sites from using my bandwidth; they can link to my images, or zip files from their site, hence using my bandwidth for downloading files. This is not an 'authorization' issue. I also cannot use an Apache module since I do not have root access because my ISP is rather strict about who gets root access.
These two lines form the 'gatekeeper' aspect of the sub:
my $remote = remote_host();
return(0) unless grep /$remote/, @$hosts;
...reverse DNS lookup, I hadn't thought of that. I think what you're getting at is that I have to 'untaint' $remote.
my $remote = remote_host();
# a domain or an ip can be letters or numbers seperated
# with '.' and there must be at least one char followed
# by a '.' with at least one char following
$remote =~ /([A-Za-z0-9\.]*[A-Za-z0-9]+\.[A-Za-z0-9]+)/;
return (0) unless length($remote) > 3;
return (0) unless grep /$remote/, @$hosts;
...I haven't tested this yet, but am I on the right track?
-- hiseldl What time is it? It's Camel Time! | [reply] [d/l] [select] |
|
| [reply] [d/l] [select] |
Re: (Funny) anti leech CGI
by shotgunefx (Parson) on Oct 30, 2002 at 10:10 UTC
|
I remember some time back that a site was linking to a Yahoo! Store's images of Rolexes. The site owner contacted Y! to complain. (Was showing up in the referers)
The images are named dynamically after each "publish" so an engineer manually installed images of Mickey Mouse watches and obscene things. The leech didn't notice for a couple of days. :)
-Lee
"To be civilized is to deny one's nature." | [reply] |
Re: anti leech CGI
by erasei (Pilgrim) on Oct 30, 2002 at 14:21 UTC
|
If you are just trying to keep people from linking directly to your images, then there is a great module for Apache called AccessRefer. This uses the referrer to validate where the image is being loaded from. This has the added bonus of being able to be configured for your virtual hosts, thus giving each of your sites their own "access list".
As with anything coming from the user, REFER can be forged, but for the most part, this is a pretty good way of doing it. | [reply] |
|
I would love to use an Apache module, but my ISP won't let me have root access. :(
-- hiseldl What time is it? It's Camel Time!
| [reply] |
Re: anti leech CGI
by hacker (Priest) on Oct 30, 2002 at 14:54 UTC
|
What color would you like that wheel you're about to reinvent? chrome? wood? rubber?
There's no need to push this down into the perl side of things, when Apache has facilities built-in that can handle this at the request level. Look into mod_rewrite, and more specifically, the URL Rewriting Guide, specifically the "Blocked Inline-Images" section about 80% of the way down. I use this method on several of my sites, and it works wonderfully (it's not just for images).
To summarize: <Directory /path/to/domain.org/>
AllowOverride None
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://domain.org/.*$ [NC]
RewriteRule .*\.(png|gz|zip|)$ http://domain.org/no.png [R]
</Directory>
| [reply] [d/l] |
|
What if your wheel doesn't fit? See my reply to erasei.
Thanks for the summary of the Apache config though.
-- hiseldl What time is it? It's Camel Time!
| [reply] |
|
|