LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Server
User Name
Password
Linux - Server This forum is for the discussion of Linux Software used in a server related context.

Notices


Reply
  Search this Thread
Old 01-31-2015, 10:05 AM   #1
Sabinou
Member
 
Registered: Jan 2006
Location: France
Distribution: Debian Wheezy, Webmin + Virtualmin (remote dedi)
Posts: 214

Rep: Reputation: 30
Blocking countries with geoIP, with a website's PHP


Hello !

Please, could I humbly ask for help with banning a country on a website level with PHP, using Maxmind's GeopIP database ?

My purpose : to block China.
(Let's skip on the "but it's bad!" discussion, in my case it is necessary.)

My server : Debian Wheezy with LAMP, PHP version 5.4.36-0+deb7u3 more precisely, good hardware, IPtables, and Virtualmin+Webmin as panel.

My limitations : I'll skip on doing it with iptables and Apache module, to my humble but honest shame. That's too much complexity and possibilities to be sure I'm not screwing up something.
I want the filtering to be done by PHP, in the very first steps when visitors just arrived;

On my server, I see that I have 2 available packages, already installed (the server has been installed over a year ago for me by a professional, I asked to be able to recognize visitors based on their country).
These packages are : php5-geoip, and geoip-database
Just in case, I attached to my post a screenshot of their description, have a look

The fundamental doc I found : http://php.net/manual/en/function.ge...de-by-name.php

Please, could you tell me if the following code,
if placed in a website's index.php file,
will be able to block all the Chinese visitors,

Code:
<?
$hostname = gethostbyaddr($_SERVER['REMOTE_ADDR']);
$country = geoip_country_code_by_name($_SERVER['REMOTE_ADDR']);
$redirect=false;
if (strstr(strtolower($hostname), ".cn")) { $redirect = true; };
if (strtolower($country) == "cn") { $redirect = true; };

if ($redirect) {
  header ("Location: http://www.example.com") };
?>
I am not entirely sure it would really properly redirect, for instance, what if a website has a search.php file, will the index.php be checked firstly, or should I find a way to force checking on all the site's php pages... You see what I mean ?

Sorry for the generic and newbie questions, I hope you can tell me if that will work as it is !

Kind regards!
Attached Thumbnails
Click image for larger version

Name:	del.jpg
Views:	104
Size:	89.5 KB
ID:	17473  

Last edited by Sabinou; 01-31-2015 at 04:15 PM.
 
Old 02-01-2015, 05:39 AM   #2
unSpawn
Moderator
 
Registered: May 2001
Posts: 29,415
Blog Entries: 55

Rep: Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600
Quote:
Originally Posted by Sabinou View Post
My limitations : I'll skip on doing it with iptables and Apache module, to my humble but honest shame. That's too much complexity and possibilities to be sure I'm not screwing up something.
First of all this has nothing to do with any security issues, right? Just checking...

Secondly in terms of security, performance and maintenance the right order of blocking things should be:
0) block at the edge router (provided you have one ;-p),
1) load balancer or reverse proxy in front of setup,
2) host-based firewall,
3) well-established, supported and maintained, commonly used measures like mod_security or fail2ban, and only then
4) anything else at the application level.

If I can allay any fears you might have with respect to "iptables complexity" (and since you prolly don't have an edge router or load balancer to play with) would you be willing to try the host-based firewall? If so:
A) please post output of running 'iptables-save'. That was we can check the rule set for errors and optimize it before adding the one single rule we need, and
B) check if you have the 'ipset' package installed. That's a default Wheezy package so you won't experience any problems like having to build a custom kernel or something like that.
 
1 members found this post helpful.
Old 02-02-2015, 02:12 AM   #3
TenTenths
Senior Member
 
Registered: Aug 2011
Location: Dublin
Distribution: Centos 5 / 6 / 7
Posts: 3,475

Rep: Reputation: 1553Reputation: 1553Reputation: 1553Reputation: 1553Reputation: 1553Reputation: 1553Reputation: 1553Reputation: 1553Reputation: 1553Reputation: 1553Reputation: 1553
Quote:
Originally Posted by Sabinou View Post
Please, could you tell me if the following code,
if placed in a website's index.php file,
will be able to block all the Chinese visitors,
Looks pretty much like it, yes.


Quote:
Originally Posted by Sabinou View Post
I am not entirely sure it would really properly redirect, for instance, what if a website has a search.php file, will the index.php be checked firstly, or should I find a way to force checking on all the site's php pages... You see what I mean ?
If the request is for search.php then index.php will NOT be "checked" first. You will therefore have to put your country checking code in all accessible pages of your site. Also this will not stop anyone from your chosen countries accessing non-php files on your site.

Also note that doing it this way has an overhead, in that every single IP and page access is checked.

If you are intent on banning countries and can only do it at server level then as has been previously mentioned you should look at doing it at the local firewall level with IPTABLES.

You could make use of the data on http://www.ipdeny.com to create rule sets for each country.

In the past I've used their files to create apache directives to deny from the network blocks for certain countries. I even had a script to regularly update the relevant files (I used a file as an Include in the Virtual Host / Directory directives, although this did mean doing a graceful restart of apache whenever the ban list changed.)

Currently (among other things) I make use of fail2ban to detect typical "bad" behaviour, for example multiple registration attempts, multiple login attempts, etc. and ban the IP on a temporary basis regardless of origin country.
 
Old 02-02-2015, 07:36 AM   #4
Sabinou
Member
 
Registered: Jan 2006
Location: France
Distribution: Debian Wheezy, Webmin + Virtualmin (remote dedi)
Posts: 214

Original Poster
Rep: Reputation: 30
Hello !

Quick replies, thank you for your time, UnSpawn, TenTenths

- Thanks for the confirmation my script would be working but not protecting all the files, TenTenths !

- I *can* try banning with IPtables, finally, if you are patient and promise I don't risk to nuke a production server by accident *_*
And for this help, I truly am grateful.

- The reason I was shying away from the IPtables route is the complexity.

The guides I found to install the geoip Apache module so that IPtables can drop packets from certain countries were downright terrifying, because almost none of them were telling the same thing.
Plenty of different versions, with plenty of different explanations. No way to tell which one would be the good one for me. Get this, or that, or that, or that. Or get that... and the "that" link is a page to a github index page project with numerous various files.
Recompile the kernel. Compile this program. Install dependencies. Not these dependencies, those other ones. Recompile that. Add new rules.
... For Pete's sake I never recompiled my kernel. I didn't install my server myself, I trusted for this a skilled professional that earned every single and yet abundant euro I paid him. My linuxian skill, although growing (I love learning) is limited to managing on a day-to-day basis something already existing, and tuning the system with php/mysql/various configurations depending on the needs, sometimes writing small scripts for various uses (I'm not totally alien to shell), plus monitoring and small repairs, while my time is not so abundant I can experiment around all day (that, is a matter of regret, wish I had more time).

I'll add this is a production server, with websites I want to keep online without interruption, because either I hold them dear, or because they belong to friends and family to whom I offer free hosting. So, I can't go and take the risk to nuke everything by accident. (Yes, I have backups.)

- I have no edge router, no load balancer, just a standalone good server with a good company (if you wonder about the specs, it's what the OVH hosting company calls a Host-32).
I already have Fail2Ban (around 500 hosts banned per month, in average), but most of my Chinese problems come from individuals, not fully automated systems

- Allright then, taking up on UnSpawn's offer, thank you VERY MUCH !

My iptables-save : http://pastebin.com/4kHPiqMf

I don't think I have ipset on my Wheezy :
# dpkg-query -l '*ipset*'
dpkg-query: no packages found matching *ipset*
# dpkg-query -l 'ipset'
dpkg-query: no packages found matching ipset

My panel, virtualmin/webmin, shows ipset is available among the packets that can be installed. Three fully matching results : ipset, libipset-dev : "development files for IP sets", and libipset2 : "library for IP sets"

Could TenTenth's mention of ipdeny.com's list be used, perhaps ?
 
Old 02-02-2015, 09:55 AM   #5
TenTenths
Senior Member
 
Registered: Aug 2011
Location: Dublin
Distribution: Centos 5 / 6 / 7
Posts: 3,475

Rep: Reputation: 1553Reputation: 1553Reputation: 1553Reputation: 1553Reputation: 1553Reputation: 1553Reputation: 1553Reputation: 1553Reputation: 1553Reputation: 1553Reputation: 1553
Here's a script that builds a script....

It downloads IP blocks from ipdeny, works through a list of two letter country codes to create a bash script that will:

Delete an existing iptables chain.
Creates a new chain "BadCountry".
Adds this to the top of the INPUT chain to pass anything on port 80 to the BadCountry chain.
Adds all the IP blocks in the relevant countries to the BadCountry chain with a reject/unreachable.

Feel free to adapt it to your needs.

(Oh, and you can also call the script with the parameter undo and it'll delete the chain.)

Code:
#!/bin/bash

PARAM=${1}

if [ "${PARAM}" == "undo" ] ; then

  iptables -D INPUT -p tcp -m tcp --dport 80 -j BadCountry
  iptables --flush BadCountry
  iptables -X BadCountry

else

  echo $(date) IP Blocking GLOBAL START
  
  #First call ourselves to undo (delete the chain)
  ${0} undo

  #This is where the executable script that does the table update will live.
  TABLESCRIPT=/root/scripts/countrytables.sh

  #Change this to a folder you can write to
  cd /root/ipblocks
  
  #and delete any zone file tar/zip files  
  rm -f all-zones.tar.*

  echo $(date) Download Countries START

  wget "http://www.ipdeny.com/ipblocks/data/countries/all-zones.tar.gz"

  tar -zxvf all-zones.tar.gz > /dev/null

  echo $(date) Download Countries FINISH

  echo $(date) Build Countries START

  echo "#!/bin/bash" > ${TABLESCRIPT}

  echo "iptables -N BadCountry" >> ${TABLESCRIPT}

  echo "iptables -I INPUT -p tcp -m tcp --dport 80 -j BadCountry" >> ${TABLESCRIPT}

  echo "iptables -A BadCountry -j RETURN" >> ${TABLESCRIPT}

  for COUNTRY in kh cn in id kr my ph tw th vn pk ; do
    awk {'print "iptables -I BadCountry -s "$1" -j REJECT --reject-with icmp-port-unreachable"'} ${COUNTRY}.zone >> ${TABLESCRIPT}
  done

  echo $(date) Build Countries FINISH

  echo $(date) Updating iptables START

  #Make our script executable
  chmod 700 ${TABLESCRIPT}

  #And now execute it
  ${TABLESCRIPT}

  echo $(date) Updating iptables FINISH

fi

# Elvis Has Left The Server.

Last edited by TenTenths; 02-02-2015 at 09:57 AM.
 
1 members found this post helpful.
Old 02-02-2015, 05:41 PM   #6
unSpawn
Moderator
 
Registered: May 2001
Posts: 29,415
Blog Entries: 55

Rep: Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600
Quote:
Originally Posted by Sabinou View Post
- I *can* try banning with IPtables, finally, if you are patient and promise I don't risk to nuke a production server by accident *_*
I am patient and I promise you won't risk nuking your production server. Simple as that. Why? Because using ipset is easy.


Quote:
Originally Posted by Sabinou View Post
I already have Fail2Ban (around 500 hosts banned per month, in average), but most of my Chinese problems come from individuals, not fully automated systems
Note fail2ban already contains functionality to use ipset, see: /etc/fail2ban/action.d/iptables-ipset-proto6.conf.


Quote:
Originally Posted by Sabinou View Post
I don't think I have ipset on my Wheezy :
# dpkg-query -l '*ipset*'
dpkg-query: no packages found matching *ipset*
# dpkg-query -l 'ipset'
dpkg-query: no packages found matching ipset

My panel, virtualmin/webmin, shows ipset is available among the packets that can be installed. Three fully matching results : ipset, libipset-dev : "development files for IP sets", and libipset2 : "library for IP sets"
Try
Code:
apt-get install ipset
If that command executes OK then proceed, else don't. (Not that you'll be b0rking your server in the next step, it's just futile.)


Quote:
Originally Posted by Sabinou View Post
Could TenTenth's mention of ipdeny.com's list be used, perhaps ?
We will! Run his 'wget' command and extract the tar ball, then run this:
Code:
# This will create the "container" in which the IP ranges will be held: 
ipset create china nethash
# This will populate it:
cat ./cn.zone | while read RANGE; do ipset add china $RANGE; done
# Test the result:
]# ipset list -t china
]# ipset list china | wc -l
The last two commands should return something like this:
Code:
Name: china
Type: hash:net
Revision: 4
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 62928
References: 0
and this:
Code:
5283
Now save that ip set in the plain text file "/etc/china.ipset" for later use:
Code:
umask 0027; ipset save china -file /etc/china.ipset
If all went well (and how could it go wrong? ;-p) now you have an active ip set in memory and a copy saved on disk. Acknowledge that and we'll proceed to actually using the thing.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
GeoIP Blocking HariharanV Linux - Software 0 02-05-2011 10:41 PM
Blocking countries from accessing my server? arashi256 Linux - Newbie 4 06-03-2010 03:19 PM
Blocking Countries via pf firewall Schiz0 Linux - Networking 4 10-15-2007 05:27 AM
My website is not accessible from particular countries gubak Linux - Networking 10 11-02-2006 02:34 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Server

All times are GMT -5. The time now is 11:14 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration