This is what I did.
Move the PHP files out of the public folder except for one gateway file
scripts/
prepend.php
a.php
b.php
public_html/
gateway.php
html files
css files
js files
I use .htaccess to redirect all requests for my PHP scripts to gateway.php
. This file does the rest: to get a.php
, the browser needs to request url /php/a
. /php/b
will be forwarded to b.php
...
RewriteEngine On
RewriteBase /
RewriteRule ^php/(.*) gateway.php?file=$1.php [END,QSA,NC]
END
means to stop looking for more redirect rules. NC
means case-insensitive match. QSA
means to attach query parameters if any to the redirect destination.
In php.ini
, I set auto_prepend_file
to point to a file in the scripts folder. This file is run before all PHP scripts, so I can use it to do some configuration. In part, it has a list of allowed PHP scripts.
prepend.php
//the only scripts that will be allowed to run (besides gateway.php)
Const SAFE_SCRIPTS = '"/path/to/gateway.php","/path/to/a.php" ...';
Const SCRIPTS_PATH = __DIR__; //this file should be in the scripts directory
//block unnknown files. This will prevent a malicious file from running
$file = $_SERVER['SCRIPT_FILENAME'];//should be /path/to/gateway.php
if(strpos(SAFE_SCRIPTS,"\"$file\"")===false) {http_response_code(404);exit;}
gateway.php is in charge of making sure the requested PHP file is on the allowed list and of forwarding the request to the right file
//get the file requested. Comes from the htaccess rule
$file = SCRIPTS_PATH.'/'.$_GET['file'];
//if file is not in the allowed list, abort
if(strpos(SAFE_SCRIPTS,"\"$file\"")===false) {http_response_code(404);exit;}
//load the file that will handle the request
require SCRIPTS_PATH.'/'.$file;
My setup is slightly more complicated but you get the idea. Keeps my scripts outside of the public web folder.