Silent Ninja

Well-Known Member
Apr 18, 2006
196
0
166
Buenos Aires, Argentina
I'm trying to block some asian countries from accessing my server via FTP (Pure-FTPd), since most of the time they login on it is to try dictionary passwords, or to hack somebody.

I've already tried editing /etc/hosts.deny and using "Host Access Control" on WHM denying my IP address on both for the FTP service, but I was still able to connect to the FTP port as usual.

I'm using CSF which already have an option to block IP ranges by countries, but it blocks them completely which is not what I'm looking for; also when I choose too many countries, it exceeds the iptables rules limit and I'm pretty sure it will slow things down a lot.

I've also thought about doing it with GeoIP like some users did with Bind (different zones per country), but I would need to compile my own Pure-FTPd with a patch to do so. I'm not that good at programming, and also cPanel will step over it everytime it updates so perhaps it's not that good idea either.

¿Is there a simple way to avoid the users from a country (eg. China) to login via FTP without using iptables?

Here's the IP ranges list: http://www.ipdeny.com/ipblocks/data/countries/cn.zone
 

Silent Ninja

Well-Known Member
Apr 18, 2006
196
0
166
Buenos Aires, Argentina
There are new Country options in the latest CSF which allow you to block ( for example) all connections to port 21 from Country code ( ) all other connections are allowed through.
I know but choosing only China and Rusia, my iptables gets huge and it can't be good to have that many filters to check on each connection... or is it? There must be a rule limit.
 

Silent Ninja

Well-Known Member
Apr 18, 2006
196
0
166
Buenos Aires, Argentina
The http://www.blockcountryip.com website have lists of IP addresses from all countries. Download their database and get those IP address blocks and DENY each block. Block it in .htaccess or server's apache config file.
Cheers!!!
Apache only handles HTTP requests... not FTP ones. I'll contact the CSF team to see if they come up with something less invasive than blocking multiple countries with iptables.
 

InterServed

Well-Known Member
Jul 10, 2007
266
8
68
cPanel Access Level
DataCenter Provider
I personally like and use ipset. In case you are interested:
Some more details/comparison between iptables and ipset: Mass-blocking IP addresses with ipset » d(a)emonkeeper's purgatory

1) install requirements (ipset): yum install ipset ipset-devel -y
2) create ipset chain: ipset -N geoblocklist nethash
3) firewall script (i personally use it):
Code:
#!/bin/bash
# log= where to log ; wdir=working directory , where to save the downloaded zones ;
# list= where to download the ip zones from
log=/var/log/ipset-drop.log
wdir=/root/ipset-drop
list='http://www.ipdeny.com/ipblocks/data/countries'

# Flush iptables INPUT Chain
iptables -F INPUT

# local ftp bruteforce block ( you may wanna remove this rule )
iptables -A INPUT -s 127.0.0.0/8 -d 0/0 -p tcp --dport 21 -j DROP

# iptables match-set for geoblocklist (block multiple ports rule - ftp,apache,mysql,cpanel ports)
iptables -I INPUT -p tcp -m multiport --dports 21,80,443,3306,8081,2082,2083,2086,2087 -m set --match-set geoblocklist src -j DROP

# log $1
function log_this() {
        printf '%s: %s\n' "$(date --rfc-3339=seconds)" "$1" >> $log
}


cd $wdir || exit 1

# if the ipset is missing, it's useless to download anything
ipset -L geoblocklist > /dev/null 2>&1
if [ $? -ne 0 ]; then
        log_this 'error in ipset -L geoblocklist'
        exit 1
fi

curl_flags='--silent --show-error --remote-name --remote-time --max-time 150
        --write-out %{http_code}'

if [ "$1" = "-v" ]; then
        curl_flags="--verbose $curl_flags"
        curl_keep_stderr=true
fi

new_files=""
old_files=""
# download file, name must not be null, and must have no spaces (urlencode).
# existing files are downloaded only if newer.
# new_ and old_ files are updated according to the result.
# stderr displays normally when -v (verbose) is given on the command line
function run_curl() {
        local name=$1 existing="" time_cond="" rtc=""
        if [ -f $name ]; then
                time_cond="--time-cond $name"
                existing=$name
        fi
        if [ -n "$curl_keep_stderr" ]; then
                rtc=$(curl $curl_flags $time_cond $list/$name)
        else
                rtc=$(curl $curl_flags $time_cond $list/$name 2>&1)
        fi
        if [ $? -eq 0 ]; then
                if [ "$rtc" = "200" -a -f $name ]; then
                        new_files+="${new_files:+ }$name"
                        existing=''
                elif [ "$rtc" != "304" ]; then
                        log_this "http $rtc for $name"
                fi
        else
                log_this "${rtc:-curl: $?} for $list/$name"
        fi
        test -n "$existing" && old_files+="${old_files:+ }$existing"
}

# define what files to process
do_ipset=""
if [ -f no-download ]; then
        do_ipset=$(<no-download)
        log_this "no-download${do_ipset:+: $do_ipset}"
else
# download China,Korea,Taiwan,Hong-Kong zones (edit the following per your needs):
        run_curl cn.zone
        run_curl kr.zone
        run_curl tw.zone
        run_curl hk.zone

        log_this "download: ${new_files:-none}${old_files:+, existing: $old_files}"
        do_ipset=${new_files:+$new_files $old_files}  # do both if any is new
fi

# process blocks, if any
if [ -n "$do_ipset" ]; then
        ipset -X temp  > /dev/null 2>&1
        ipset -N temp nethash

        perl -e 'while(<>){s/;.*//; s/\s//g; print $_, "\n" unless /^$/;}' \
                $do_ipset |
                (
                        blockcount=0;
                        errcount=0
                        while read block; do
                                err=$(ipset -A temp $block 2>&1)
                                if [ $? -ne 0 ]; then
                                        (( ++errcount < 6 )) && log_this "$block $err"
                                else
                                        (( ++blockcount ))
                                fi
                        done
                        test $errcount -gt 6 &&
                                log_this "$errcount errors in $do_ipset"
                        log_this "$blockcount blocks set from $do_ipset"
                )

        service iptables save
        ipset -W temp geoblocklist
        ipset -X temp
        ipset save > /dev/null 2>&1

fi
Warning: Running this script will Flush your iptables INPUT Chain , you must edit the script if you desire different.
Warning: Running this script will block China,Korea,Taiwan and Hong-Kong from reaching your server on multiple ports - ftp,apache,mysql,cpanel ports
Disclaimer: I'm not responsible for any damage this may cause , you are responsible from reading and understanding the code or adjust it to your exact needs.

Tested on RHEL6 based distributions (RHEL,CentOS,CLoudLinux).
Addition: you can add this script as a cron job to update the zone/ip blocks automatically if they change.
 
Last edited:

arunsv84

Well-Known Member
Oct 20, 2008
373
1
68
127.0.0.1
cPanel Access Level
Root Administrator
Apache only handles HTTP requests... not FTP ones. I'll contact the CSF team to see if they come up with something less invasive than blocking multiple countries with iptables.
Yes. I didn't notice that you need to block ftp requests only. Sorry for not reading your request completely. :)
 

georgeb

Well-Known Member
May 23, 2010
49
1
58
Montreal, QC, Canada
cPanel Access Level
Root Administrator
I'm trying to block some asian countries from accessing my server via FTP (Pure-FTPd), since most of the time they login on it is to try dictionary passwords, or to hack somebody.
I think you can achieve this using "pure-uploadscript". mod_geoip and GeoIp.dat from MaxMinds. You can setup a script to run every time a file is uploaded to your server and remove the file (block the IP) if the IP is from a blocked country. And using mod_geoip you don't have to load all the denied ips in your firewall

Maybe I didn't understand correctly what you want...

Regards
 
  • Like
Reactions: Silent Ninja

Silent Ninja

Well-Known Member
Apr 18, 2006
196
0
166
Buenos Aires, Argentina
I think you can achieve this using "pure-uploadscript". mod_geoip and GeoIp.dat from MaxMinds. You can setup a script to run every time a file is uploaded to your server and remove the file (block the IP) if the IP is from a blocked country. And using mod_geoip you don't have to load all the denied ips in your firewall
Wow, I've never thought of that, it seems a really good idea, since it will only act on uploads which is what I want to avoid

I'll see what I can do in that script, thanks a lot
 

lbeachmike

Well-Known Member
Dec 27, 2001
306
1
316
Long Beach, NY
cPanel Access Level
Root Administrator
Wow, I've never thought of that, it seems a really good idea, since it will only act on uploads which is what I want to avoid

I'll see what I can do in that script, thanks a lot
Hi there -

This is what I've wanted to accomplish as well, though preferably with the ability to whitelist a country for a particular user account. For example, let's say that I'm blocking all uploads from China, but I have one hosted Chinese client and thus want to allow them to be able to upload from within China to their account.

Have you made any progress with any of the ideas discussed here?

Thanks.

Mike