What's new

how to block ip addresses after "x" number of failed attempts, or by geo-location

  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

v1k0d3n

Occasional Visitor
has anyone attempted to use iptables to block based on geolocation or by failed attempts on an asus router (either with merlin build or otherwise). i can't think of a more handy tool to have, honestly! i know in the normal linux world this is possible, but i haven't tried [yet] with the asus-wrt builds yet.

any input, experience or guidance would be most helpful!
 
block based on geolocation
Take a look on ipset. You can easily block whole countries or custom IP ranges.
or by failed attempts
I'm not sure about Asuswrt-Merlin, but you can try iptables rules like
Code:
-A INPUT -p tcp -m tcp --dport 22 --tcp-flags FIN,SYN,RST,ACK SYN -j BRUTE
...
-A BRUTE -m recent --update --seconds 600 --hitcount 5 --name BRUTE --rsource -j DROP
-A BRUTE -m recent --set --name BRUTE --rsource -j ACCEPT
 
RMerlin,

it may be difficult to do (i'm not sure of the work involved), but can you add this feature to the gui? this would be an awesome feature to have included with your build!
 
This feature is already there in the GUI.

In Administration Menu, System Tab, "Enable SSH Brute Force Protection" option.

It just uses a lot more relaxed timings than in the example above, which is why I also use manual setup via firewall init script:
Code:
admin@censored:/tmp/home/root# cat /jffs/scripts/firewall-start
#!/bin/sh
iptables -I INPUT 6 -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -I INPUT 7 -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 300 --hitcount 6 --rttl --name SSH -j DROP
admin@censored:/tmp/home/root#

//edit: older versions of merlin firmware also required to add the xt_recent module to the kernel first:
modprobe xt_recent
 
Last edited:
Would you care to post up an idiots guide to implementing this? I'd love to, but have never tried scripting...

Thanks!


This feature is already there in the GUI.

In Administration Menu, System Tab, "Enable SSH Brute Force Protection" option.

It just uses a lot more relaxed timings than in the example above, which is why I also use manual settup via firewall init script:
Code:
admin@censored:/tmp/home/root# cat /jffs/scripts/firewall-start
#!/bin/sh
iptables -I INPUT 6 -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -I INPUT 7 -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 300 --hitcount 6 --rttl --name SSH -j DROP
admin@censored:/tmp/home/root#

//edit: older versions of merlin firmware also required to add the xt_recent module to the kernel first:
modprobe xt_recent
 
First to clarify what my example actually does, since it is not exactly what the OP asked for. The iptables rules in my firewall-start script simply start to drop incoming ssh connections from a certain IP if there was more than 5 new connections from the same IP in last 300 seconds. And as mentioned above, the same functionality is available via GUI, but the time window and number of connections is different and cannot be "tuned" via GUI.

That being said, you can add this way any iptables firewall rules you want/need to achieve desired outcome.

As for a "howto":
1. You need command line access to your router, either via telnet, or via ssh (I assume you got this, why else would you want to block ssh brute force attacks).

2. You must have jffs partition enabled/formatted on your router. Merlin's wiki describes this quite well: https://github.com/RMerl/asuswrt-merlin/wiki/JFFS

3a. You create your script and give it executable permissions:
Code:
mkdir -p /jffs/scripts/
touch /jffs/scripts/firewall-start
chmod 755 /jffs/scripts/firewall-start

3b. You edit the file and put in there rules you want. The only available editor on the router is vi I am afraid, which can be a bit tedious to use for a beginner:
Code:
vi /jffs/scripts/firewall-start

In case you just want the same rules as I have then enter input mode in vi by pressing the "i" key. And paste the bellow rules into the the file (shift+insert or mouse right click in putty):
Code:
#!/bin/sh
iptables -I INPUT 6 -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -I INPUT 7 -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 300 --hitcount 6 --rttl --name SSH -j DROP

Hit Esc to exit input mode in vi and save the file using :wq (the colon is important)

More info on the jffs scripts and configs again on Merlin's wiki:
https://github.com/RMerl/asuswrt-merlin/wiki/User-scripts
https://github.com/RMerl/asuswrt-merlin/wiki/Custom-config-files

4. reboot the router and you are done. You can check the current firewall rules that are in use by issuing the following command:
Code:
iptables -L -v --line-numbers
 
Last edited:
RMerlin,

it may be difficult to do (i'm not sure of the work involved), but can you add this feature to the gui? this would be an awesome feature to have included with your build!

I want to avoid overcrowding the webui like other third party firmwares have done over time, as it only ends up confusing the average user, and most of the times there are so many pages of settings that people lose track of them, or they don't even notice that a specific setting actually exist, drownded amongst the other settings. And this is something easily achieved through a custom script.
 
pretty excited about ipset...didn't realize it was included! i did however start using it, only to find that there is no data in the country lst files. any clue as to why? i went to the website (http://www.ipdeny.com/ipblocks/) and nothing is included in any of the files....

the torstatus works find though for individual ip's...it's just blocking the country ranges that appear to be broken?
 
I want to avoid overcrowding the webui like other third party firmwares have done over time, as it only ends up confusing the average user, and most of the times there are so many pages of settings that people lose track of them, or they don't even notice that a specific setting actually exist, drownded amongst the other settings. And this is something easily achieved through a custom script.

i guess...but then again, i wouldn't think that the "average" user would be downloading the firmware to begin with. but i definitely understand where you're coming from and after all...it would take some work to do (which means more to maintain, etc). i get it.
 
pretty excited about ipset...didn't realize it was included! i did however start using it, only to find that there is no data in the country lst files. any clue as to why? i went to the website (http://www.ipdeny.com/ipblocks/) and nothing is included in any of the files....

the torstatus works find though for individual ip's...it's just blocking the country ranges that appear to be broken?

Check out ryzhov_al's guide he posted on the Wiki (https://github.com/RMerl/asuswrt-merlin/wiki/Using-ipset) - it might help you get it up and running.
 
i guess...but then again, i wouldn't think that the "average" user would be downloading the firmware to begin with. but i definitely understand where you're coming from and after all...it would take some work to do (which means more to maintain, etc). i get it.

You'd be surprised at some of the users that are using my firmware. They specifically do so because it's as easy to use as Asuswrt, they don't even need to reconfigure or use any special procedure to flash it. They are mostly interested in the bugfixes and minor tweaks, and they find the learning curve for Tomato or DD-WRT too steep for them.

The average user is specifically the one I target with this project, and I point more advanced users who need more advanced features to alternatives such as Tomato or DD-WRT. I do keep a few doors open here and there with the custom config and custom user scripts to still allow more advanced users to tinker with their router's behaviour, without encumbering the web interface. I think it's a good compromise.
 

yeah, i agree with you. some users will download it just because they can. i'm 100% with you on "why run something with a bunch of features you don't need". the build you're providing has more than i need. i was surprised you were using ipset actually...even better than i expected, and i hadn't even tried it before asking about it! your build is perfect for what i need...i'm a net/sec developer for a large telecom comp in the US...i don't want more things that could break and i DEFINITELY don't want boatware on my firewall! lean and mean is what i prefer.

great job on the build btw. thanks for the hard work!
 
that's exactly what i used. i traced it down to the wget...apparently the files are empty on http://www.ipdeny.com/ipblocks/data/countries/*.zone.

i tried several of them and then started looking at the site itself. same. anyone else having this issue as well?

Looks like an issue with their file generation, because the webpage itself reports actual filesizes for those files that are 0 bytes in size:

http://www.ipdeny.com/ipblocks/

They have a contact form on their site, I suggest dropping them a note about this.
 
my apologies for reviving this thread; as it has already been somewhat answered.

my lists are rather extensive and take quite a long time to load (about 15 minutes perhaps?). it appears to be working though, and pretty well.

question though; how does this impact performance? i have thousands of net ranges spanning across several countries. does this impact performance? where are the lists stored (memory assuming)? attached below is my edited script. i like it a little better, because you can search for items in each ipset list separately.

by default, logs will not be generated to a syslog server (in my case, splunk), which is what i want. however, if i want to see a "hit" against an ACL...how would i do this with ipset? can i even do this somehow?

also, is there a way to get these to load faster? i still kind of wish there would be some sort of geo-location blocking, but perhaps the ipset list would be quicker than checking against geo-location all of the time. not sure...either way...i'm looking for the most optimized approach.

here's my script:
Code:
#!/bin/sh
# FIRST, LET'S MAKE SURE THAT OUTBOUND TRAFFIC IS LOGGED FOR OUR SPLUNK REPORTING SERVER:
iptables -I INPUT -i br0                                        -j logaccept
#
# NOW, LET'S MAKE SURE THAT OUR CUSTOM RULES GET LOADED INTO IPTABLES FIRST:
/jffs/firewall/fw_auto_customblock.fw
/jffs/firewall/fw_auto_anomalyblock.fw
#
#
# LET'S CREATE OUR IPSET LIST(S).
# FIRST, WE NEED TO PREPARE THE IPSET MODULE:
lsmod | grep "ipt_set" > /dev/null 2>&1 || \
for module in ip_set ip_set_nethash ip_set_iphash ipt_set
do
        insmod $module
done
#
# NOW LET'S PREPARE THE DIRECTORY WHERE WE WANT TO SAVE OUR IPSET NETWORK LIST(S):
IPSET_LISTS_DIR=/jffs/ipset_lists
[ -d "$IPSET_LISTS_DIR" ] || mkdir -p $IPSET_LISTS_DIR
#
#
#
# IT WAS RECOMMENDED TO BLOCK STEALTHY TOR NODES (MAY REMOVE LATER, AS I MAY WISH TO USE TOR MYSELF):
if [ "$(ipset --swap list_tornodes list_tornodes 2>&1 | grep 'Unknown set')" != "" ]
then
        ipset -N list_tornodes iphash
        [ -e $IPSET_LISTS_DIR/tor.lst ] || wget -q -O $IPSET_LISTS_DIR/tor.lst http://torstatus.blutmagie.de/ip_list_all.php/Tor_ip_list_ALL.csv
        for IP in $(cat $IPSET_LISTS_DIR/tor.lst)
        do
                ipset -A list_tornodes $IP
        done
fi
[ -z "$(iptables-save | grep list_tornodes)" ] && iptables -I INPUT -m set --set list_tornodes src -j DROP
#
#
#
# NOW FOR THE FUN PART; LET'S BLOCK COUNTRIES THAT SEND US THE MOST "SCRIPTY" PROBES, OR COUNTIES THAT WE FEEL ARE "SUSPICIOUS" IN NATURE: 
# (See other countries code at http://www.ipdeny.com/ipblocks/)
# (or https://www.countryipblocks.net/country_selection.php)
# EDIT COUNTRY ZONES WITH SPACES ONLY BELOW (1 OF 2):
for country in af br cl cn de fr hk hu il iq ir it kp kr pk ro ru sa tr tw
do
if [ "$(ipset --swap list_$country list_$country 2>&1 | grep 'Unknown set')" != "" ]
then
        ipset -N list_$country nethash
fi
done
#
# EDIT COUNTRY ZONES WITH SPACES ONLY BELOW (2 OF 2):
for country in af br cl cn de fr hk hu il iq ir it kp kr pk ro ru sa tr tw
do
        [ -e $IPSET_LISTS_DIR/$country.lst ] || wget -q -O $IPSET_LISTS_DIR/$country.lst http://www.ipdeny.com/ipblocks/data/countries/$country.zone
        for IP in $(cat $IPSET_LISTS_DIR/$country.lst)
        do
                ipset -A list_$country $IP
                [ -z "$(iptables-save | grep list_$country)" ] && iptables -I INPUT -m set --set list_$country src -j DROP
        done
done
#
#
# AND IF THIS DOESN'T WORK, LET'S HAVE A FALLBACK SCRIPT PREPARED AS A PRECAUTION:
#/jffs/firewall/fw_auto_countryblock.fw

now i can search for things like so:
Code:
#######@RT-AC66R:/tmp/home/root# iptables -nL | grep list_
DROP       all  --  0.0.0.0/0            0.0.0.0/0           set list_tw src 
DROP       all  --  0.0.0.0/0            0.0.0.0/0           set list_tr src 
DROP       all  --  0.0.0.0/0            0.0.0.0/0           set list_sa src 
DROP       all  --  0.0.0.0/0            0.0.0.0/0           set list_ro src 
DROP       all  --  0.0.0.0/0            0.0.0.0/0           set list_pk src 
DROP       all  --  0.0.0.0/0            0.0.0.0/0           set list_kr src 
DROP       all  --  0.0.0.0/0            0.0.0.0/0           set list_kp src 
DROP       all  --  0.0.0.0/0            0.0.0.0/0           set list_ir src 
DROP       all  --  0.0.0.0/0            0.0.0.0/0           set list_iq src 
DROP       all  --  0.0.0.0/0            0.0.0.0/0           set list_il src 
DROP       all  --  0.0.0.0/0            0.0.0.0/0           set list_hu src 
DROP       all  --  0.0.0.0/0            0.0.0.0/0           set list_hk src 
DROP       all  --  0.0.0.0/0            0.0.0.0/0           set list_de src 
DROP       all  --  0.0.0.0/0            0.0.0.0/0           set list_cn src 
DROP       all  --  0.0.0.0/0            0.0.0.0/0           set list_cl src 
DROP       all  --  0.0.0.0/0            0.0.0.0/0           set list_br src 
DROP       all  --  0.0.0.0/0            0.0.0.0/0           set list_af src 
DROP       all  --  0.0.0.0/0            0.0.0.0/0           set list_tornodes src 
#######@RT-AC66R:/tmp/home/root# ipset -L | grep Name
Name: list_tornodes
Name: list_af
Name: list_br
Name: list_cl
Name: list_cn
Name: list_de
Name: list_fr
Name: list_hk
Name: list_hu
Name: list_il
Name: list_iq
Name: list_ir
Name: list_it
Name: list_kp
Name: list_kr
Name: list_pk
Name: list_ro
Name: list_ru
Name: list_sa
Name: list_tr
Name: list_tw
#######@RT-AC66R:/tmp/home/root# ipset -L list_cn | grep 101.102.64.
101.102.64.0/19
#######@RT-AC66R:/tmp/home/root#
 
Last edited:
IPSET for ftp protocol

I would like to use ipset to restrict certain countries to access my ftp server, but I don't want to block traffic to my torrents. Is that possible with ipset and how do I implement that?

I don't want to disable my ftp server, so if this works then that would be great.

I can't find that in using-ipset tutorial.
 
I've implemented ryzhov_al's guide to implement the ipset on my AC66U and it works, but now I want to change that script to block countries when they try to access with the ftp protocol.

I know that's pretty easy, but I'm not familiar with linux programming. Thx for the help.
 
No one knows how to do that?
 
I need to know how to modify this part to check for country and ftp protocol (port 21).


Code:
# Block incoming traffic from some countries. cn and pk is for China and Pakistan. See other countries code at http://www.ipdeny.com/ipblocks/
if [ "$(ipset --swap BlockedCountries BlockedCountries 2>&1 | grep 'Unknown set')" != "" ]
then
    ipset -N BlockedCountries nethash
    for country in af al br bg cl cn de dk fr fi gb hk hu il iq ir it jp kp kr pk ro ru sa se ua tr tw
    do
        [ -e $IPSET_LISTS_DIR/$country.lst ] || wget -q -O $IPSET_LISTS_DIR/$country.lst http://www.ipdeny.com/ipblocks/data/countries/$country.zone
        for IP in $(cat $IPSET_LISTS_DIR/$country.lst)
        do
            ipset -A BlockedCountries $IP
        done
    done
fi
[ -z "$(iptables-save | grep BlockedCountries)" ] && iptables -I INPUT -m set --set BlockedCountries src -j DROP
If anyone knows how to change that, plz post it here.
 
Last edited:

Similar threads

Latest threads

Support SNBForums w/ Amazon

If you'd like to support SNBForums, just use this link and buy anything on Amazon. Thanks!

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!

Staff online

Top