I know this is an old question. If you're on shared hosting, as you're suggesting, you may be limited to having to redirect all traffic through a script.
I had to do this once. For a WordPress site that was getting hacked, I needed to determine how it was being attacked. Like you said, I redirected all requests with an .htaccess file to a single PHP script that would render a simple "Site is under Maintenance" page, but that also would record that request – the post data, cookies, upload filenames – pretty much anything I wanted to observe.
Conveniently, though, the site was also under Cloudflare protection; thus by doing so, Cloudflare ended up seeing the 503 Unavailable on the maintenance page, and served cache instead, thus keeping the site up almost completely. Better, the maintenance page was still able to record requests.
My .htaccess file appeared something like the following:
RewriteEngine On
RewriteRule ^index-maintenance\.php$ - [L]
RewriteRule .* /index-maintenance.php [L]
Then, the index-maintenance.php file looked something like:
<?php
$record = TRUE; // whether or not to record requests
header('HTTP/1.1 503 Service Unavailable', TRUE, 503);
header('Retry-After: 18000');
if($record) {
// Get remote IP
// If the site uses cloudflare, the true remote IP is served
// in the HTTP_CF_CONNECTING_IP server var:
$ip = isset($_SERVER['HTTP_CF_CONNECTING_IP'])
? $_SERVER['HTTP_CF_CONNECTING_IP']
: $_SERVER['REMOTE_ADDR'];
ob_start();
// Request date / IP / URL
echo date('Y-m-d H:i:s: ')
. 'Remote IP: ' . $ip
. ' - ' . $_SERVER['REQUEST_METHOD']
. ' ' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']
. "\r\n";
// User agent
echo $_SERVER['HTTP_USER_AGENT'] . "\r\n";
// If you needed all headers:
# foreach(getallheaders() as $header => $value)
# echo "$header: $value\r\n";
// If you wanted raw request data vs. parsed POST data:
# $postdata = file_get_contents('php://input');
# if(strlen($postdata)) echo $postdata."\r\n";
// Post data / Cookies / Files
if(count($_POST) || count($_COOKIE)) {
ob_start();
echo "POST\n";
var_dump($_POST);
echo "COOKIES\n";
var_dump($_COOKIE);
echo "FILES\n";
var_dump($_FILES);
$postdata = ob_get_clean();
echo str_replace("\n","\r\n",$postdata);
}
echo "\r\n";
// usage of random character string discourages guessing
// the url if the directory is web-accessible; but, if at
// all possible, make it inaccessible:
file_put_contents('../requests_n5io09d21mkp.log',ob_get_clean(),FILE_APPEND);
}
// then, a simple maintenance page:
?>
<!DOCTYPE html>
<html>
<head>
<title>Site Under Maintenance</title>
</head>
<style type="text/css">
body {
margin: 0;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.notice {
color: #808080;
font: bold 20px/1.6em sans-serif;
text-align: center;
}
</style>
<body>
<p class="notice">
We're sorry. The site is under maintenance.<br/>Please check back later.
</p>
</body>
</html>