Update .htaccess with Dynamic DNS IP Address to Prevent Password Protection
I was working on a password protected site that needed to allow one specific user access without requiring a login/password to access it. The site was already using .htaccess to password protect the entire site so the quickest solution was to use the following type of setup in the htaccess file:
Order deny,allow Deny from all AuthGroupFile /dev/null AuthName "A Blog" AuthType Basic AuthUserFile /home/admin/domains/domain.com/.htpasswd/public_html/.htpasswd require valid-user Allow from person.getmyip.com Satisfy Any
The main addition that I added to the password protection is line 8 "Allow from". This line allows a specific IP address or host to have access without requiring password protection.
However, the host that needed to be used was a Dynamic DNS hostname. This creates a problem as Apache takes the following steps when the user requests access.
- Grab IP from user requesting access
- Do a reverse DNS lookup
- Compare the results to the host in the Allow from line (person.getmyip.com)
In this case when a reverse DNS lookup is completed on the users IP address it will not find the Dynamic DNS hostname. Instead, it will find the hostname that is associated with your ISP which might look something like this 8.sub-79-231-223.myvzw.com.
There are a number of ways to get around this issue. In my case I wanted to use a small script to dynamically populate the .htaccess file with the correct IP address.
Below is the following PHP script that handles updating .htaccess with the latest IP address. The main requirement is that there is a comment "# Allow from person.getmyip.com" somewhere in the .htaccess file. This line tells the script where to insert the IP address on the very next line.
<?php
// Rewrites the entire htaccess file. When a line starts with '# Allow from brett.getmyip.com' the
// very next line will be replaced with the actual ip associated with brett.getmyip.com
$htaccessFile = "/home/admin/domains/batie.com/public_html/.htaccess";
$handle = fopen($htaccessFile, "r");
if ($handle) {
$previous_line = $content = '';
while (!feof($handle)) {
$current_line = fgets($handle);
if(stripos($previous_line,'# Allow from person.getmyip.com') !== FALSE)
{
$output = shell_exec('host person.getmyip.com');
if(preg_match('#([0-9]{1,3}\.){3}[0-9]{1,3}#',$output,$matches))
{
$content .= 'Allow from '.$matches[0]."\n";
}
}else{
$content .= $current_line;
}
$previous_line = $current_line;
}
fclose($handle);
$tempFile = tempnam('/tmp','allow_');
$fp = fopen($tempFile, 'w');
fwrite($fp, $content);
fclose($fp);
rename($tempFile,$htaccessFile);
chown($htaccessFile,'admin');
chmod($htaccessFile,'0644');
}
?>
I quickly wrote this script and realize that there is room for improvement. However, this meet the need and solved the problem.
After the script was completed adding a simple line to the crontab (crontab -e) file got it running on a regular basis to automatically update the file with the current IP.
# Script to update ip access for dynamic dns host - it allows person.getmyip.com */5 * * * * /usr/local/bin/php /home/admin/scripts/allow_person.php >/dev/null 2>&1

April 25th, 2011 at 9:00 am
I've having exactly the same problem as yours, and I'm updating my dynamic IP manually for a few years using FTP lol.
Your great blog enlightened me, but sadly my webhost doesn't allow shell_exec so I wrote a simple perl script instead, hope reader here find it useful.
My perl doing exactly the same as your php, however, instead of reading a live .htaccess file, my perl read from a template instead, of course, if you assign a live .htaccess as a template, it works as well.
Once it found the template file, it looks for any line(s) contains the word @@@DYNAMIC@@@ and then replace it with a new line below
allow from 1.2.3.4
The perl script is already running on my shared web hosting account :)
#!/usr/bin/perl $htaccess = "/volume1/web/test/.htaccess"; $template = "/volume1/web/test/template"; # get ip address $result=`host myhome.somedomain.com`; @sp = split(/ /,$result); $size = @sp; $ip = $sp[$size-1]; open(TEMPLATE, $template) || die("Could not open file!"); @raw_data=; close(TEMPLATE); open(NEW, ">$htaccess") || die("Could not create file!"); foreach $line (@raw_data){ if($line =~ /\@\@\@DYNAMIC\@\@\@/){ print NEW "allow from $ip\n"; }else{ print NEW $line; } } close(NEW);