Blocking countries with geoIP, with a website's PHP
Linux - ServerThis forum is for the discussion of Linux Software used in a server related context.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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
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 !
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.
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
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.
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 !
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 ?
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.
- 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
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
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
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.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.