Block Countries from my Website

  • devilwood
  • Silver Member
  • Silver Member
  • User avatar
  • Posts: 437

Post 3+ Months Ago

Until recently I've never even considered blocking other countries. However, our servers have been having issues from some Russian/Ukrainian IP addresses. When I gave my report to my bosses they were dumbfounded cause our service is USA specific and we have ZERO desire to reach a Russian market. I figured there had to be some solution out there to lock my web server down to the USA population because we are not concerned with Europe to the Philippines and if we could block them altogether that's just less we have to worry about. I first spoke to our server people to see what solutions they could provide and they were not much help. They mentioned an apache mods but the memory usage and overhead was too great and they said we would see a noticeable difference in our website speed. Also, some users who are connecting through proxies could get blocked.... we are not worried about them. There were some others that used a database but I was worried about lookup speed, db optimization, accuracy, and out-dated information.

This got me thinking...

After looking at IP blocks by country I noticed the first octet differs by country. So, 207.xxx.xxx.xxx will be USA.

Could I just make a small table with just the US first octets? Then, using PHP get the user's IP address by using $_SERVER["REMOTE_ADDR"];. Next, I could explode the user's IP at the decimals. Lastly, I could compare the user's IP first octet with small database of US octets.

Would this work? Am I right in assuming the first octet is country specific? Also, how often do IP blocks by country change?

Thanks for any help or advice. There really should be an easier way to connect a web server to a specific area only. It's stupid that someone on the other side of the planet has access to your server and can attempt to manipulate/sabotage the server as much as they want.
  • devilwood
  • Silver Member
  • Silver Member
  • User avatar
  • Posts: 437

Post 3+ Months Ago

I've been looking more into this today and found a service called Cloudflare.com which takes over the DNS for your domain and your host records. I'm using it on a test site to gauge the performance and features with the free account but it looks promising. My DNS just updated so I'm about to play with it some more.

The GeoIP API service from Maxmind has to be configured with your webserver in order to work. Just for PHP I noticed they had a PECL and PEAR extension which is nice but still requires more configuration than I want to do. I noticed they do have a GeoIP Country Web Service for a small fee where 200,000 queries will run about $20. If my math is right then this should last us about 30 years.

I did find a free API web service called hostip.info. I wrote a small CURL call with PHP to send the GET request. I tested a few IPs from other countries and they returned accurately but my own IP is not in their database. The country code it returns is XX. This may still work. I would just have to use any country that is XX or US.


I would still like to know the accuracy of the first octet as it relates to the country. It seems a table of US only first octets would be fairly small.
  • Bigwebmaster
  • Site Admin
  • Site Admin
  • User avatar
  • Posts: 9101
  • Loc: Seattle, WA & Phoenix, AZ

Post 3+ Months Ago

Hi Devilwood

Before you posted your 2nd post, I was going to respond to let you know we use Maxmind for blocking certain countries from registering at Ozzu. We use the Apache GeoIP module, and have noticed no slow downs as far as performance. It works quite well as Maxmind has mapped out everything for the most part and what IP blocks belong to what countries.

Just for your information, we use the free database through Maxmind, and that has been by far more than sufficient for our needs. I wrote down notes for my own reference on what I need to do to install GeoIP on a Cpanel Server, as well as where the free databases are located. So I will provide that in this post in case it proves useful for you or anyone else:

Install GeoIP on CPanel server



Download more databases from MaxMind and put them into:

/opt/geoip/share/GeoIP/:

The databases are located here:

http://geolite.maxmind.com/download/geoip/database/

Get latest database version for Country and City (all that we use):
http://geolite.maxmind.com/download/geo ... oIP.dat.gz
http://geolite.maxmind.com/download/geo ... ity.dat.gz

Install CPanel EasyApache GeoIP module:

* View details: http://docs.cpanel.net/twiki/bin/view/E ... CustomMods
* Download mod_GeoIP:

wget http://docs.cpanel.net/twiki/pub/EasyAp ... oip.tar.gz

tar -C /var/cpanel/easy/apache/custom_opt_mods -xzf custom_opt_mod-mod_geoip.tar.gz

* Run EasyApache and select mod GeoIP:

/scripts/easyapache

Configure GeoIP by adding to httpd.conf (or pre_virtualhost_global.conf):

* /usr/local/apache/conf/httpd.conf
* /usr/local/apache/conf/includes/pre_virtualhost_global.conf

GeoIPEnable On
GeoIPDBFile "/opt/geoip/share/GeoIP/GeoIP.dat"
GeoIPDBFile "/opt/geoip/share/GeoIP/GeoCity.dat"

Restart Apache:

/scripts/restartsrv_apache

Here is a very quick and dirty test PHP script to see if its working correctly:

PHP Code: [ Select ]
$cont="$_SERVER[GEOIP_CONTINENT_CODE]";
$country="$_SERVER[GEOIP_COUNTRY_CODE]";
$country_name="$_SERVER[GEOIP_COUNTRY_NAME]";
$region="$_SERVER[GEOIP_REGION]";
$regionname="$_SERVER[GEOIP_REGION_NAME]";
$city="$_SERVER[GEOIP_CITY]";
$areacode="$_SERVER[GEOIP_AREA_CODE]";
$geolat="$_SERVER[GEOIP_LATITUDE]";
$geolong="$_SERVER[GEOIP_LONGITUDE]";
$postalcode="$_SERVER[GEOIP_POSTAL_CODE]";
// a standard Apache environment variable
$rem="$_SERVER[REMOTE_ADDR]";
// output the data
echo "Continent: $cont | Country Abbrev: $country | Name: $country_name<br>";
echo "Region: $region | Region Name: $regionname | City: $city<br>";
echo "Area Code: $areacode | Postal code/Zip: $postalcode<br>";
echo "Latitude: $geolat | Longitude: $geolong<br>";
echo "Ip: $rem<br>";
echo "<hr></center>";
exit;
  1. $cont="$_SERVER[GEOIP_CONTINENT_CODE]";
  2. $country="$_SERVER[GEOIP_COUNTRY_CODE]";
  3. $country_name="$_SERVER[GEOIP_COUNTRY_NAME]";
  4. $region="$_SERVER[GEOIP_REGION]";
  5. $regionname="$_SERVER[GEOIP_REGION_NAME]";
  6. $city="$_SERVER[GEOIP_CITY]";
  7. $areacode="$_SERVER[GEOIP_AREA_CODE]";
  8. $geolat="$_SERVER[GEOIP_LATITUDE]";
  9. $geolong="$_SERVER[GEOIP_LONGITUDE]";
  10. $postalcode="$_SERVER[GEOIP_POSTAL_CODE]";
  11. // a standard Apache environment variable
  12. $rem="$_SERVER[REMOTE_ADDR]";
  13. // output the data
  14. echo "Continent: $cont | Country Abbrev: $country | Name: $country_name<br>";
  15. echo "Region: $region | Region Name: $regionname | City: $city<br>";
  16. echo "Area Code: $areacode | Postal code/Zip: $postalcode<br>";
  17. echo "Latitude: $geolat | Longitude: $geolong<br>";
  18. echo "Ip: $rem<br>";
  19. echo "<hr></center>";
  20. exit;


And here is a perl script that you can use or port to keep the Maxmind database updated:

PERL Code: [ Select ]
#!/usr/bin/perl
    use strict;
    our $VERSION = '0.01';
    use LWP::Simple qw/ mirror RC_NOT_MODIFIED RC_OK $ua /;
    use File::Copy  qw/ mv /;
    use File::Spec;
    use PerlIO::gzip;
 
    # --- maxmind.com - please send comments to support@maxmind.com
    #
    # mirror various maxmind databases from geolite.maxmind.com.
    # The script download only changed files, unzip the files and
    # move it into the desired directory.
    #
    # Here is a sample cron entry that check daily for new files.
    # 34 15 * * * /usr/local/bin/geolite-mirror-simple.pl
 
    # adjust the path to your needs. Make sure the directories exists
    -d ( my $download_dir = '/opt/geoip/share/GeoIP/download' ) or die $!;
    -d ( my $dest_dir     = '/opt/geoip/share/GeoIP' )          or die $!;
 
    # --- remove lines you do not need
    # geoip customers should rename or remove GeoIP.dat.gz and GeoIPCity.dat.gz
    # >>> This example overwrite your GeoIPCity.dat database! <<<
 
    my %mirror = (    # local-filename       geolite-name
                   'GeoIP.dat.gz'      => 'GeoLiteCountry/GeoIP.dat.gz',
                   'GeoIPCity.dat.gz'  => 'GeoLiteCity.dat.gz',
                   'GeoIPv6.dat.gz'    => 'GeoIPv6.dat.gz',
                   'GeoIPASNum.dat.gz' => 'asnum/GeoIPASNum.dat.gz'
    );
 
    $ua->agent("MaxMind-geolite-mirror-simple/$VERSION");
    my $dl_path = 'http://geolite.maxmind.com/download/geoip/database/';
 
    chdir $download_dir or die $!;
    for my $f ( keys %mirror ) {
      my $rc = mirror( $dl_path . $mirror{$f}, $f );
      next if $rc == RC_NOT_MODIFIED;
      if ( $rc == RC_OK ) {
        ( my $outfile = $f ) =~ s/.gz$//;
        open my $in,  '<:gzip', $f       or die $!;
        open my $out, '>',      $outfile or die $!;
        print $out $_ or die $! while <$in>;
        mv( $outfile, File::Spec->catfile( $dest_dir, $outfile ) ) or die $!;
      }
    }
    exit 0;
  1. #!/usr/bin/perl
  2.     use strict;
  3.     our $VERSION = '0.01';
  4.     use LWP::Simple qw/ mirror RC_NOT_MODIFIED RC_OK $ua /;
  5.     use File::Copy  qw/ mv /;
  6.     use File::Spec;
  7.     use PerlIO::gzip;
  8.  
  9.     # --- maxmind.com - please send comments to support@maxmind.com
  10.     #
  11.     # mirror various maxmind databases from geolite.maxmind.com.
  12.     # The script download only changed files, unzip the files and
  13.     # move it into the desired directory.
  14.     #
  15.     # Here is a sample cron entry that check daily for new files.
  16.     # 34 15 * * * /usr/local/bin/geolite-mirror-simple.pl
  17.  
  18.     # adjust the path to your needs. Make sure the directories exists
  19.     -d ( my $download_dir = '/opt/geoip/share/GeoIP/download' ) or die $!;
  20.     -d ( my $dest_dir     = '/opt/geoip/share/GeoIP' )          or die $!;
  21.  
  22.     # --- remove lines you do not need
  23.     # geoip customers should rename or remove GeoIP.dat.gz and GeoIPCity.dat.gz
  24.     # >>> This example overwrite your GeoIPCity.dat database! <<<
  25.  
  26.     my %mirror = (    # local-filename       geolite-name
  27.                    'GeoIP.dat.gz'      => 'GeoLiteCountry/GeoIP.dat.gz',
  28.                    'GeoIPCity.dat.gz'  => 'GeoLiteCity.dat.gz',
  29.                    'GeoIPv6.dat.gz'    => 'GeoIPv6.dat.gz',
  30.                    'GeoIPASNum.dat.gz' => 'asnum/GeoIPASNum.dat.gz'
  31.     );
  32.  
  33.     $ua->agent("MaxMind-geolite-mirror-simple/$VERSION");
  34.     my $dl_path = 'http://geolite.maxmind.com/download/geoip/database/';
  35.  
  36.     chdir $download_dir or die $!;
  37.     for my $f ( keys %mirror ) {
  38.       my $rc = mirror( $dl_path . $mirror{$f}, $f );
  39.       next if $rc == RC_NOT_MODIFIED;
  40.       if ( $rc == RC_OK ) {
  41.         ( my $outfile = $f ) =~ s/.gz$//;
  42.         open my $in,  '<:gzip', $f       or die $!;
  43.         open my $out, '>',      $outfile or die $!;
  44.         print $out $_ or die $! while <$in>;
  45.         mv( $outfile, File::Spec->catfile( $dest_dir, $outfile ) ) or die $!;
  46.       }
  47.     }
  48.     exit 0;


Store the above script at:

/scripts/updategeoipdata

or put in /etc/cron.daily/updategeoipdata

chmod 755

You may need to install PerlIO::gzip with:

/scripts/perlinstaller PerlIO::gzip

to get the script to work correctly.
  • devilwood
  • Silver Member
  • Silver Member
  • User avatar
  • Posts: 437

Post 3+ Months Ago

Wow. Thanks BWM.

So, do you just call the GeoIP Country Code server variable in each script and then IF/ELSE it. Like:

Code: [ Select ]
$country="$_SERVER[GEOIP_COUNTRY_CODE]";

if ($country == "US") {
// run script
} else {
exit();
}
  1. $country="$_SERVER[GEOIP_COUNTRY_CODE]";
  2. if ($country == "US") {
  3. // run script
  4. } else {
  5. exit();
  6. }


I'm still concerned with performance, but maybe the performance affects were mainly based on the point of restriction. For instance, if the restriction was used in the example above or if an htaccess file was used or if apache handled the restriction??


Thanks a ton for the writeup. It greatly demystified the setup. I don't see any reason why I can't follow those instructions. They look to be in my wheelhouse. Also, thanks for the last perl script as keeping it up-to-date was a major concern as well.

Lastly, my last problem was with AOL users and proxies. Maxmind is saying on their site they return US for all AOL users which is a big plus. Do you know of any problems with this statement or any inaccuracies? We were at the point that we didn't care about any AOL users that were connecting using proxies in other countries, but this is a big advantage of GeoIP if it handles them correctly that we now don't have to exclude them.
  • Bigwebmaster
  • Site Admin
  • Site Admin
  • User avatar
  • Posts: 9101
  • Loc: Seattle, WA & Phoenix, AZ

Post 3+ Months Ago

Yeah so all I do in the .htaccess file is this:

GeoIPEnable On

Since I actually disable it for any domains on the server unless explicitly enabled. That itself may save on a bit of performance I am guessing. Then just like in your example script, a simple if statement can be used. In my case I do something like this:

PHP Code: [ Select ]
'BANNED_COUNTRY'                => (isset($_SERVER['GEOIP_COUNTRY_CODE']) && preg_match("/^(BD|ID|IN|PK|PH)$/",$_SERVER['GEOIP_COUNTRY_CODE']) ? true : false),


That basically sets another variable "BANNED_COUNTRY" to be true if it matches BD, ID, IN, PK, or PH. Your example was more simplified and can be used that way was well.

So in my case I simply use .htaccess to enable it, and then the rest is handled via PHP's $_SERVER variable.

As far as AOL, I believe you are correct that they simply return one location for all of them. For our situation this was fine as well, I believe if you pay for the commercialized version then they will provide you further information on those users if you really need that. In my case the free version by far does what we need so lumping all of the AOL users into one location was no problem for us.

Glad some of this could be of help, I try to keep notes on certain things from time to time, and this was one of them :)

Post Information

  • Total Posts in this topic: 5 posts
  • Users browsing this forum: No registered users and 63 guests
  • You cannot post new topics in this forum
  • You cannot reply to topics in this forum
  • You cannot edit your posts in this forum
  • You cannot delete your posts in this forum
  • You cannot post attachments in this forum
 
 

© 1998-2014. Ozzu® is a registered trademark of Unmelted, LLC.