GeoIP Blocking/Large IP Blocklist

Has anyone configured a way to efficiently implement GeoIP blocking and/or managing large IP groups in the configuration? I’d imagine that an IP group with thousands of addresses may become a bit unwieldy in the text configuration and wasn’t sure if there were any best practices for accomplishing this.

Thank you!

For that you have the CIDR notation.

Apparently if one configures firewall group address-group <name> ..., that would result in an actual Linux “IP-set” (an managed by the ipset tool.) (Bellow is a redacted example from my own configuration.)

$ ipset list
Name: <name>
Type: hash:ip
Revision: 4
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 232
References: 1

Therefore if you don’t want to pollute your config file with all those IP addresses, you can easily define such an empty “group”, use it in your firewall via the VyOS config system, and then use the regular ipset command to update it.

(Note however that the changes wouldn’t persist after reboot, and you’ll have to be careful that any change to the configuration might reset your addresses in that group.)

That being said, the next step is how to “produce” the list of addresses belonging to a particular country, especially since they could change “daily”. (If you don’t have this covered, I can try to provide you with some sh snippets to build such a list, but you’ll have to integrate it yourself in the VyOS setup.)

Thank you for the detailed response! I knew the act of populating the dynamic lists would be an issue - I’d love to see the sh snippets you referenced.

This is basically the easiest way to do it; I’ve implemented this exactly as [ciprian.craciun] has described.

Say you wanted to geoblock, using the lists at

#Purpose: Block all traffic from countries (ipdeny + iso country name)
#/sbin/iptables -A INPUT -m set --match-set geoblock src -j DROP

ISO="af al ao az ba bh bd by bj bo bg bf bi bw bn kh cm cv cf td cn cg ci dj dz 
eg gq er et ga gm gh gn gw hr ht in jo kz ke kw la lb ls lr ly mg mw ml mr mu mn
ma mm na ne ng om qa ro rs ru rw sa sc sd sl so za lk sz sy tj tz tg tn tr tm ug ua ae uz vn ye zm zw" 
# use /tmp

# update the  zone files
wget -O /tmp/all-zones.tgz

# make the zonefile directory
mkdir /tmp/zones

# extract the all-zones file into the zones directory

tar xzCf /tmp/zones /tmp/all-zones.tgz

# flush the geoblock ipset
/sbin/ipset flush geoblock

# run the loop over the ISO codes, adding the entries to the geoblock list

for i in $ISO
        for j in `cat /tmp/zones/$`
            /sbin/ipset add geoblock $j

# remove the zonefile directory and source tarfile

rm -rf /tmp/zones /tmp/all-zones.tgz

Now, this script can be run adhoc, because it always flushes the ipset before attempting to load the new one. So, you could set up a cron job to run once daily, or however often you wanted to update. I have a couple of network groups, one for each that I want to block (Emerging Threats, VoIP, Geo, etc). Now, if I could only easily get it to run at boot, after vyos has configured itself…

1 Like

This is exactly what I’m looking for - thank you!

Just so I’m clear, in your standard VyOS configuration, did you create a blank address group named “geoblock” and apply that group to your firewall rules (while the group is then populated via the bash script)?

set firewall group network-group geoblock description 'GeoBlocked Networks'

set firewall name Internet_In rule 3 action 'drop'
set firewall name Internet_In rule 3 description 'Block Networks based on Geo-Location'
set firewall name Internet_In rule 3 protocol 'all'
set firewall name Internet_In rule 3 source group network-group 'geoblock'
set firewall name Internet_In rule 3 state established 'disable'
set firewall name Internet_In rule 3 state new 'enable'
set firewall name Internet_In rule 3 state related 'disable'

As you might imagine, I have 2 other network groups before the GeoBlocked ones, configured similarly…

Most efficient of course would be to take all of your CIDR ranges obtained from different lists, and generate a single ipset with sort and uniq, and feed that into the set

1 Like

Hi. I use this repo for ubnt/EdgeOS from Github(Credits: WaterByWind), which works with almost no modifications.
It has a reboot script that loads the last fetched list on startup and integrates perfectly in VyOS.
Fetches and blocks ~42K ip addresses in under 5 seconds!! (see log)

Starting at 22:05:49 CEST Wed 08 May 2019
Fetching ''
Fetching ''
Fetching ''
Fetching ''
Fetching ''
Fetching ''
Fetching ''
Processing block file list (IPv4): ' 01_rules.emergingthreats.net_emerging-Block-IPs.txt 02_www.spamhaus.org_drop.txt 03_www.spamhaus.org_dropv6.txt 04_www.spamhaus.org_edrop.txt 05_lists.blocklist.de_all.txt 06_iplists.firehol.org_firehol_level1.netset'
Applying IPset (IPv4)
IPv4 blocklist items fetched: 39954, unique: 35239, final: 42518
Total IPv4 prefix length count (including hosts): 4
Finished at 22:05:53 CEST Wed 08 May 2019

### ___ END LOG ___
1 Like

Out of curiosity, what do the last three configuration commands accomplish?

set firewall name Internet_In rule 3 state established 'disable'
set firewall name Internet_In rule 3 state new 'enable'
set firewall name Internet_In rule 3 state related 'disable'

depends on if you have and use a default firewall state policy; I dont, so I explictly have the state policy in each rule. I tried to use a default firewall state policy, but it got in my way more often than I liked, so I stopped using it, and put the state policy back into each rule.

Thanks all - I have this up and running successfully. I utilized the repo mentioned by krassle ( in addition to the rules by panachoi.

My question is this - I presently have the rule applied to traffic hitting my VyOS from the external/WAN interface. I only restrict outgoing DNS and SMTP from the internal interface. Is there a way to drop all replies to an established connection originating from the internal interface with the external rule?

In other words, say a device was compromised inside my network and initiated a conversation with an IP in the blocklist. My current internal interface firewall rule would allow it as it’s an established connection and any traffic/replies would be allowed to flow back. Is it possible to drop that traffic from the external rule despite the fact that it was an established connection? Here’s my external rule for reference - thanks all as always!

rule 4 {
        action drop
        description "Block networks based on Geo-Location and Malware"
        protocol all
        source {
            group {
                network-group Nets4-BlackList