A small side project I am working on requires some very simple IP whitelisting in order to restrict access. The side project isn’t particularly sensitive, but placing the restriction allows me to more easily set it and forget it while also being a better net citizen (think custom DNS resolvers). Only a small group of personal contacts will be using the whitelisting API, but they will have dynamic IPs and I want to make the process of whitelisting as painless as possible. While this ‘whitelist API’ is far from best practice or Enterprise ready, for my purposes I believe it is sufficiently secure and adds minimal complexity for the end users.

With the idea of making this API as simple for myself create as it is for people to use, I decided to stick with PHP and avoid using a database. I also wanted users to be able to whitelist themselves simply by visiting a bookmark in their web browser of choice. Eg:

https://exampledomain.com/whitelist-url.php?user=XYZ&auth=123

User Authentication

So let’s get started. It makes sense to begin with the PHP authorization code, as nothing else should happen until the users have successfully validated. Note that If I were writing a proper web application, I would not pass data using query strings. However in this case I wanted to keep it nice and simple for the end users and I ensure that a valid SSL certificate is installed on the website so that the username and passwords are not transmitted in plain text.

if ( !isset($_GET['user']) || !isset($_GET['auth']) ) 
{ 
	header('HTTP/1.0 403 Forbidden');
	echo 'You are forbidden!';
	exit;
}

This is a basic check to make sure that the request has set a user and auth value in the query string. If they have not submitted these required authentication details then the request will receive a 403 response.

$user = $_GET['user'];
$pass = $_GET['auth'];
$auth_file = "data/auth/{$user}";
$whitelist_file = "data/ip-data/{$user}";
$current_ip = $_SERVER['REMOTE_ADDR'];
$whitelist_max = 5;

Now that we know the required values have been submitted we can set some variables. As I mentioned earlier, I wanted to avoid using a database, and I also did not want to hard code the authorization details in PHP either. So to make it quick and nasty I opted to store the user authorization details in files. The filename corresponds to the username and the file content is the password. A similar scheme has been used to save the whitelisted IPs. Each user has their own file and the file is a list of their whitelisted IPs.

So to breakdown the above code, the first two lines are defining the user submitted username and password data. The third and forth lines define the authorization file and whitelist file that should exist for a valid user. The fifth line defines the IP of the user making the request and the sixth line sets the maximum number of IPs that can be whitelisted for a user at any one time.

if (!file_exists($auth_file)) {
	header('HTTP/1.0 403 Forbidden');
	echo 'You are forbidden!';
	exit;
}

$userauth = file_get_contents($auth_file);

If the $auth_file does not exist then the username is invalid and the request fails authentication. Once the username is known to be valid then you can get the file contents for their password.

if ( $userauth != $pass ) {
	header('HTTP/1.0 403 Forbidden');
	echo 'You are forbidden!';
	exit;
}

This checks that the file contents matches the password submitted by the user.

Now this actually ended up being much wordier than I was expecting, so I will end part 1 here. In part 2 of this tutorial I will show how I am saving the whitelisted IPs.