Recipe 6.28 Restricting Range Requests
Problem
You want to prevent clients from requesting
partial
downloads of documents within a particular scope, forcing them to
request the entire document instead.
Solution
You can overload ErrorDocument
403 to make it handle range requests. To do this, put the
following into the appropriate <Directory>
container in your httpd.conf file or in the
directory's .htaccess file:
SetEnvIf "Range" "." partial_requests
Order Allow,Deny
Allow from all
Deny from env=partial_requests
ErrorDocument 403 /forbidden.cgi
Then put the following into a file named
forbidden.cgi in your server's
DocumentRoot:
#! /usr/bin/perl -w
use strict;
my $message;
my $status_line;
my $body;
my $uri = $ENV{'REDIRECT_REQUEST_URI'} || $ENV{'REQUEST_URI'};
my $range = $ENV{'REDIRECT_HTTP_RANGE'} || $ENV{'HTTP_RANGE'};
if (defined($range)) {
$body = "You don't have permission to access "
. $ENV{'REQUEST_URI'}
. " on this server.\r\n";
$status_line = '403 Forbidden';
}
else {
$body = "Range requests disallowed for document '"
. $ENV{'REQUEST_URI'}
. "'.\r\n";
$status_line = '416 Range request not permitted';
}
print "Status: $status_line\r\n"
. "Content-type: text/plain;charset=iso-8859-1\r\n"
. "Content-length: " . length($body) . "\r\n"
. "\r\n"
. $body;
exit(0);
Or use mod_rewrite to catch requests with a
Range header. To do this, put the following into
the appropriate <Directory> container in
your httpd.conf file or in the
directory's .htaccess file:
RewriteEngine On
RewriteCond "%{HTTP:RANGE}" "."
RewriteRule "(.*)" "/range-disallowed.cgi" [L,PT]
Then put the following into a file named
range-disallowed.cgi in your
server's DocumentRoot:
#! /usr/bin/perl -w
use strict;
my $message = "Range requests disallowed for document '"
. $ENV{'REQUEST_URI'}
. "'.\r\n";
print "Status: 416 Range request not permitted\r\n"
. "Content-type: text/plain;charset=iso-8859-1\r\n"
. "Content-length: " . length($message) . "\r\n"
. "\r\n"
. $message;
exit(0);
Discussion
Both of these solutions are a bit sneaky about how they accomplish
the goal.
The first overloads an ErrorDocument 403 script so
that it handles both real "access
forbidden" conditions and range
requests. The
SetEnvIf directive sets the
partial_request environment variable if the
request header includes a Range field, the
Deny directive causes the request to be answered
with a 403 Forbidden status if the
environment variable is set, and the ErrorDocument
directive declares the script to handle the 403 status. The script
checks to see whether there was a Range field in
the request header so it knows how to answer—with a
"you can't do
Range requests here" or with a
real "document access forbidden"
response.
The second solution uses
mod_rewrite to
rewrite any requests in the scope that include a
Range header field to a custom script that handles
only this sort of action; it returns the appropriate status code and
message. The "sneaky" aspect of
this solution is rewriting a valid and successful request to
something that forces the response status to be
unsuccessful.
See Also
|