Limiting access to your 
Perl/CGI scripts by host

This article introduces a simple Perl subroutine that you can use to limit user's access to your Perl/CGI programs. The subroutine limits access by checking the value of the REMOTE_HOST environment variable. If you're not logged in from the right host, you're not allowed to run the CGI program.


If you've ever run your own web site using Apache, you know that you can limit access to certain files and directories using the .htaccess file. But suppose you forget to put a .htaccess file in a directory, or you configure it wrong? That leaves open the possibility that somebody outside your Internet domain can run your CGI programs. Not always a pretty thought, eh?

As an extra layer of security, I've created a very simple Perl subroutine that I use in my important Perl/CGI programs. This routine checks the REMOTE_HOST environment variable. If the user accessing the script isn't logged in from the proper remote host, the script won't run.

Easy to use

I wanted to make the subroutine easy to use in my Perl/CGI programs. Using the subroutine involves just two steps:
    1. Use the require statement to include the myutils.lib library in your program.
    2. Call the limitHostAccess subroutine.
Here's a simple "Hello, world" CGI program that shows how to include the library and call the subroutine:

require "myutils.lib";    # include the library  #

print "Content-type: text/html";

&limitHostAccess;        # program exits here if REMOTE_HOST is wrong  #

print "<H3>Hello, world that I trust</H3>\n";


Listing 1:  Here's a modified HelloWorld.cgi program that shows how the limitHostAccess subroutine should be called. 
If a user invokes the CGI program while they're logged into the proper REMOTE_HOST, they'll see the "Hello, world that I trust" output. Otherwise, they won't see anything except a blank browser screen.

What's in the subroutine

Listing 1 showed how to include the library in your Perl/CGI program, and how to call the subroutine. But how does the subroutine work?

Listing 2 shows the Perl source code for the limitHostAccess subroutine.

# myutils.lib
#---------------------------<<  limitHostAccess  >>--------------------------#
#                                                                            #
#  PURPOSE:  Only let users from certain domains access Perl/CGI programs.   #
#                                                                            #

sub limitHostAccess {

   $trustedHosts = "|";      # define your domain here
   $remoteHost   = $ENV{'REMOTE_HOST'};

   if ( $remoteHost =~ /$trustedHosts$/i ) {
   } else {
      print "\n";
      exit 1;


Listing 2:  The limitHostAccess subroutine exits if the REMOTE_HOST does not match the patterns defined in the list of "trusted hosts". 

How it works

The limitHostAccess routine works by comparing the value of the REMOTE_HOST environment variable to the list of trusted hosts that you define. If REMOTE_HOST is in the list, the subroutine returns and the rest of your program continues. If REMOTE_HOST is not in the list, the subroutine calls "exit", which terminates your entire CGI program.

The meat of the program is in this comparison statement:

Here, we're comparing the value of $remoteHost to the list of trusted hosts. $remoteHost is given to your CGI program through your web server (in the environment variable named REMOTE_HOST), while you specify the value for the variable named $trustedHosts.

The $ symbol (the end-of-line pattern-matching symbol) at the end of the $trustedHosts variable specifies that the domain name must be at the end of the name. This means that names like will pass the test, but a name like will fail the test.

Also, the "i" after the final forward-slash makes the comparison case-insensitive. In every test I ran this was not needed, but I left it in just in case this condition was unique to my particular configuration.

As a final note, if you only log onto the Internet through one domain, such as, instead of multiple domains, just make your $trustedHosts definition look like this:

Where this routine is bad

This routine won't help much if you approve a domain like AOL.COM, which has 20 million or more users. (On the other hand, if only approve a domain like FRED.COM, you'll know that there are 20M+ AOL users that can't see the output of your CGI scripts.)

This routine will also fail if a hacker spoofs your domain name. But my guess is that if somebody is willing to go through that effort, they'll probably be able to bypass your other security measures as well.

How this technique can be improved/expanded

This is a very simple technique that can be used to add a little more security to your Perl/CGI programs. I wouldn't count on it as your only line of defense, but it can be a helpful layer of protection. Used as shown in Listing 1, it gives the appearance that the CGI program ran, but returned no results. This basic technique limits user access to your Perl/CGI scripts by looking at the domain name of the user.

If you're interested in expanding this technique, look at the environment variables available to your Perl/CGI programs, and decide how else you want to limit access. As an example you can also limit access by these variables:

In each case, the programming technique is the same. Define the acceptable values, and exit the program if the environment variable doesn't match what you expected.

Limiting access by REMOTE_PORT might be a little tricky (requiring configuration on the client-side of the equation), but can be worth the effort if you really want to tie down your scripts. Most people might think is a little overboard, but if I'm running Yahoo, E-Trade, or Amazon, I'd certainly think about it.


If you know how to use the .htaccess file with your Apache web server, by all means use it as your first line of defense. (If you want to learn more about Apache, check out the Apache home page.) But if you don't know how to use .htaccess, or you use another web server, or you want another line of defense for your CGI programs, consider this subroutine as a possible security option.