Skip to content

Instantly share code, notes, and snippets.

@Pandry
Last active May 2, 2024 20:18
Show Gist options
  • Star 22 You must be signed in to star a gist
  • Fork 15 You must be signed in to fork a gist
  • Save Pandry/21fc0e30abbfd0579ec69c491b99a446 to your computer and use it in GitHub Desktop.
Save Pandry/21fc0e30abbfd0579ec69c491b99a446 to your computer and use it in GitHub Desktop.
Block countries IPs via Firewalld
#!/bin/bash
##
# Name: GeoIP Firewall script
# Author: Pandry
# Version: 0.1.1
# Description: This is a simple script that will set up a GeoIP firewall blocking all the zones excecpt the specified ones
# it is possible to add the whitelisted zones @ line 47
# Additional notes: Usage of [iprange](https://github.com/firehol/iprange) is suggested
# for best performances
##
BLACKLIST_NAME="geoblacklist"
TMPDIR="/tmp/geoip"
if [ $(which yum) ]; then
echo -e "[\e[32mOK\e[39m] Detected a RHEL based environment!"
echo -e "[\e[93mDOING\e[39m] Making sure firewalld is installed..."
yum -y install firewalld > /dev/null 2> /dev/null
if [[ $? -eq 0 ]];then
echo -e "[\e[32mOK\e[39m] firewalld is installed!"
systemctl enable --now firewalld > /dev/null 2> /dev/null
else
echo -e "[\e[31mFAIL\e[39m] Couldn't install firewalld, aborting!"
exit 1
fi
elif [ $(which apt) ]; then
echo -e "[\e[32mOK\e[39m] Detected a Debian based environment!"
echo -e "[\e[93mDOING\e[39m] Making sure firewalld is installed..."
apt -y install firewalld > /dev/null 2> /dev/null
if [[ $? -eq 0 ]];then
echo -e "[\e[32mOK\e[39m] firewalld is installed!"
systemctl enable --now firewalld > /dev/null 2> /dev/null
else
echo -e "[\e[31mFAIL\e[39m] Couldn't install firewalld, aborting!"
exit 1
fi
elif [ $(which apk) ]; then
echo -e "[\e[31mFAIL\e[39m] Alpine Linux is not supported yet!"
exit 1
else
echo -e "[\e[31mFAIL\e[39m] Couldn't determine the current OS, aborting!"
exit 1
fi
#Create the blacklist (only if necessary)
#200k should be enough - $(find . -name "*.zone" | xargs wc -l) gives 184688 lines without the it zone
firewall-cmd --get-ipsets| grep "$BLACKLIST_NAME" > /dev/null 2> /dev/null
if [[ $? -ne 0 ]];then
echo -e "[\e[93mDOING\e[39m] Creating "
firewall-cmd --permanent --new-ipset="$BLACKLIST_NAME" --type=hash:net --option=family=inet --option=hashsize=4096 --option=maxelem=200000 > /dev/null 2> /dev/null
if [[ $? -eq 0 ]];then
echo -e "[\e[32mOK\e[39m] Blacklist $BLACKLIST_NAME successfully created!"
else
echo -e "[\e[31mFAIL\e[39m] Couldn't create the blacklist $BLACKLIST_NAME, aborting!"
exit 1
fi
fi
#create the folder
mkdir -p $TMPDIR
#Downloads the GeoIP database
if [[ $? -eq 0 ]];then
echo -e "[\e[93mDOING\e[39m] Downloading latest ip database... "
curl -L -o $TMPDIR/geoip.tar.gz http://www.ipdeny.com/ipblocks/data/countries/all-zones.tar.gz > /dev/null 2> /dev/null
if [[ $? -eq 0 ]];then
echo -e "[\e[32mOK\e[39m] Database successfully downloaded!"
else
echo -e "[\e[31mFAIL\e[39m] Couldn't download the database, aborting!"
exit 1
fi
else
echo -e "[\e[31mFAIL\e[39m] Couldn't create the $TMPDIR directory!"
exit 1
fi
#Extract the zones in the database
tar -xzf $TMPDIR/geoip.tar.gz -C $TMPDIR
#Remove all the zones you want to allow
rm $TMPDIR/it.zone $TMPDIR/eu.zone
#Add the IPs to the blacklist
for f in $TMPDIR/*.zone; do
echo -e "[\e[93mDOING\e[39m] Adding lines from $f ..."
firewall-cmd --permanent --ipset="$BLACKLIST_NAME" --add-entries-from-file=$f > /dev/null
if [[ $? -eq 0 ]];then
echo -e "[\e[32mOK\e[39m] Added $f with no issues";
else
echo -e "[\e[31mFAIL\e[39m] Some errors verified while adding the $f zone";
fi
echo ""
done
# Drop the IPs
firewall-cmd --permanent --zone=drop --add-source="ipset:$BLACKLIST_NAME" > /dev/null
#Reload the firewall
firewall-cmd --reload
cd ~
# Remove the traces
rm -rf /tmp/geoip
@chr00ted
Copy link

chr00ted commented Sep 9, 2020

I was using this script and it had stopped working, I ended up having to add "-L" to curl command to follow the links.
so instead of: curl -o $TMPDIR/geoip.tar.gz http://www.ipdeny.com/ipblocks/data/countries/all-zones.tar.gz > /dev/null 2> /dev/null
I'm now using: curl -L -o $TMPDIR/geoip.tar.gz http://www.ipdeny.com/ipblocks/data/countries/all-zones.tar.gz > /dev/null 2> /dev/null

@Pandry
Copy link
Author

Pandry commented Sep 10, 2020

I was using this script and it had stopped working, I ended up having to add "-L" to curl command to follow the links.
so instead of: curl -o $TMPDIR/geoip.tar.gz http://www.ipdeny.com/ipblocks/data/countries/all-zones.tar.gz > /dev/null 2> /dev/null
I'm now using: curl -L -o $TMPDIR/geoip.tar.gz http://www.ipdeny.com/ipblocks/data/countries/all-zones.tar.gz > /dev/null 2> /dev/null

Hey!
Thanks for the fix

Happy to know that some people are using this! 😄

@pegxit
Copy link

pegxit commented Oct 13, 2020

Hi, thanks for a brilliant piece of work!! Shouldn't line 82 read "Remove all the zones you DO NOT want to blacklist"?

@Pandry
Copy link
Author

Pandry commented Oct 14, 2020

Hi pegxit!
You're right!
I've corrected it, thanks!
Also I appreciate you liked it 😄

@tasosxynos
Copy link

Seems exactly what I wanted! Has anyone tested how CPU demanding the firewalld becomes after blocking all but one country? I wanted to avoid to use fail2ban to protect my server from ddos (and other) attacks from specific countries.

@chr00ted
Copy link

chr00ted commented Dec 3, 2020

I was using this script and it had stopped working, I ended up having to add "-L" to curl command to follow the links.
so instead of: curl -o $TMPDIR/geoip.tar.gz http://www.ipdeny.com/ipblocks/data/countries/all-zones.tar.gz > /dev/null 2> /dev/null
I'm now using: curl -L -o $TMPDIR/geoip.tar.gz http://www.ipdeny.com/ipblocks/data/countries/all-zones.tar.gz > /dev/null 2> /dev/null

Hey!
Thanks for the fix

Happy to know that some people are using this! 😄

Its a great tool, thank you for the script!

@chr00ted
Copy link

chr00ted commented Dec 3, 2020

Seems exactly what I wanted! Has anyone tested how CPU demanding the firewalld becomes after blocking all but one country? I wanted to avoid to use fail2ban to protect my server from ddos (and other) attacks from specific countries.

I'm using this on a few servers blocking everything but US addresses and server seems to run fine for 2-3 years now and haven't noticed any issues. VM is as spunky as it ever was.

@Pandry
Copy link
Author

Pandry commented Dec 4, 2020

Seems exactly what I wanted! Has anyone tested how CPU demanding the firewalld becomes after blocking all but one country? I wanted to avoid to use fail2ban to protect my server from ddos (and other) attacks from specific countries.

Hey @tasosxynos!
Glad you found out what you were searching for! 😄
A couple of think I would like to highlight (please notice that I am nowhere near being an expert, and I might be completely wrong):

I wanted to avoid to use fail2ban to protect my server from ddos (and other) attacks from specific countries.

I don't think that using a firewall on the server itself could prevent a DDoS attack, that usually lies on the idea of saturating or abusing something somewhere between the layer (2,) 3, 4 and 7 on the WAN.
e.g. If you have a 1gbps NIC (and uplink) and you receive a 2gbps L3/L4 attack, there's nothing the CPU can do to prevent the traffic from flowing in the NIC.
This will instead help against some L4 (like port exhaustion) to L7 (like slow loris) (Distributed-ish)DoS attacks (from the blacklisted countries, of course) of which you can manage the bandwidth.

Talking about the CPU usage, I use the ipset which is, AFAIK, the most efficient way to manage groups of IPs, so I don't think it can get any better.

Its a great tool, thank you for the script!

You're welcome!
Thanks for the feedback @chr00ted!

server seems to run fine for 2-3 years now

Are you running the script on a repetitive basis? This is because the IPs use to change from time to time.
In the past I used to have a cronjob and running the script on a weekly basis; May be helpful 😉

@chr00ted
Copy link

chr00ted commented Dec 4, 2020

Are you running the script on a repetitive basis? This is because the IPs use to change from time to time.
In the past I used to have a cronjob and running the script on a weekly basis; May be helpful 😉

Yes I am. I also had an issue where I needed to allow a remote employee from another country access and I had to first clear/remove all ipsets in order for the new country to take affect. I was allowing the second country, reloading iptables and having him test access unsatisfactory. Finally, after removing all ipset list, and then re-running the script, he was able to ssh in satisfactory. That was followed by 2FA training for the user...

@chr00ted
Copy link

chr00ted commented Dec 4, 2020

Off topic: Pandry, where in Italy are you located? I lived in Gaeta for 4 years and loved Italy.

@Pandry
Copy link
Author

Pandry commented Dec 5, 2020

I also had an issue where I needed to allow a remote employee from another country access and I had to first clear/remove all ipsets in order for the new country to take affect

Oh! Well, in that case, I think you could have just "open" the firewall only for its IP/it's AS IPs and manage the priority of the rule

where in Italy are you located

Right now I'm kinda free-roaming 😂 (also thanks to my new remote job)
My home is near Milan (I live alone), but due to pandemic my parents wanted me to be near them, so right now I'm with them in the Marche (excuse me but I have no idea about how to translate Italian names)

@chr00ted
Copy link

chr00ted commented Dec 6, 2020

I also had an issue where I needed to allow a remote employee from another country access and I had to first clear/remove all ipsets in order for the new country to take affect

Oh! Well, in that case, I think you could have just "open" the firewall only for its IP/it's AS IPs and manage the priority of the rule

Unfortunately they had a DHCP address from their ISP, so that was a no-go

@mweishaar
Copy link

Still working in 2022 on Fedora 35 with a couple of tweaks:
Line 49: firewall-cmd --permanent --get-ipsets| grep "$BLACKLIST_NAME" > /dev/null 2> /dev/null
Line 67: curl -k -L -o $TMPDIR/geoip.tar.gz http://www.ipdeny.com/ipblocks/data/countries/all-zones.tar.gz > /dev/null 2> /dev/null
^ Due to expired SSL certificate

Thanks for the work - just what I was looking for on a new web proxy!

@chr00ted
Copy link

chr00ted commented Oct 4, 2022

Hello again pandry, I've been using your script for years. I changed ISP's and now I'm being blocked. If I search the ipset, I dont see my ip listed. but whenever that ipset is enabled, I'm dropped by firewalld. If I disable that ipset, and reload firewalld, I can get in without issue. I have destroyed the ipset, recreated it and same issue. Its really odd because my ip is not in the list, yet whenever the ipset is enabled, no go. I have checked the ipset list for the ip I'm ssh'ing in from as well as the ip of the new server and both are not in the ipset...

IN_drop_DROP: IN=eth0 OUT= MAC=52:5********:00 SRC=1***4 DST=13 LEN=52 TOS=0x00 PREC=0x00 TTL=106 ID=27926 DF PROTO=TCP SPT=61300 DPT=22 WINDOW=64240 RES=0x00 SYN URGP=0 (I replaced my info with *****.

Any help would be appreciated. If I ssh in internally, its fine....

@Pandry
Copy link
Author

Pandry commented Oct 4, 2022

Hi @chr00ted! Glad to hear you’re still using the script!

DISCLAIMER: I’m from mobile at the moment and had no time to check the actual code and firewalld documentation. The script is old and I don’t use it from a long time.

So, the script works by blacklisting a lot of IPs, but the firewall remains in allow-by-defaullt (for a couple of reason out of scope right now).
If you encountered an issue since when you changed your ISP, it sounds to me like the CIRD your ISP has assigned to you belongs to a country you’re blacklisting.
It may be either wrong data, old data or maybe the ISP you have operates on multiple countries.
Anyway, my approach would be to whitelist the CIDR your ISP has

I’d start with checking the CIDR assigned to you at the moment, and checking if I can find it in the zone files.
For instance, I use the service https://ipinfo.io/ and from the homepage I can see info on the provider I’m surfing the web from:

You can try to grep it in the zones folder:

DIR=$(mktemp)
cd $DIR
curl -SL -o ./geoip.tar.gz http://www.ipdeny.com/ipblocks/data/countries/all-zones.tar.gz   
tar -zxv geoip.tar.gz
grep “194.110.113.0/24” *.zone # ⚠️ Replace this with your CIDR
#
# do your checks
#
cd
rm -rf $DIR 

If this is the case, one or more subnet of your AS may be incorrectly reported

To fix it, you could try to add this at the end of the script to allow the CIDR(s) of your ISP

firewall-cmd --zone=public --add-source=194.110.113.0/24 --add-source=194.110.114.0/24
# If the above works:
firewall-cmd --permanent --zone=public --add-source=194.110.113.0/24 --add-source=194.110.114.0/24
firewall-cmd --reload

I would look at the ISP’s AS and whitelist all the subnets, if I were you (PLEASE check the code and ensure it works before adding it to the script)

@chr00ted
Copy link

chr00ted commented Oct 4, 2022

Thank you @Pandry, I will give that a shot and let you know.

@alvin275
Copy link

Hello, would you suggest how this script can be tweaked to restrict country access to only http/https and dovecot (ports 587, 993, 995), but still allow mail delivery on port 25 from anywhere (anti-spam is handled using other methods). Thanks!

@kiraitachi
Copy link

kiraitachi commented Nov 20, 2022

Hey! How is this supposed to run? Just saved onto a .sh script an run it? No arguments? How can I add zones or remove? I was looking to only block Australia and China as its not under their Google Cloud free tier policy. I think this script has lots of potential for this specific use case.

@Pandry
Copy link
Author

Pandry commented Jan 14, 2023

Hi guys!
Sorry for reaching out that late, I've got stuff to do and this completely got off of my mind.

Hello, would you suggest how this script can be tweaked to restrict country access to only http/https and dovecot (ports 587, 993, 995), but still allow mail delivery on port 25 from anywhere (anti-spam is handled using other methods). Thanks!

Hi @alvin275, yes, this could be used for such a purpose, but there's some editing required!
Being more specific, the command at line 98 needs to be changed to specify the services you wish to block (appending something like --service=http --service=https --service=imap; Keep in mind that every service not appended here will be exposed world-wide).
I haven't tried this specifically, but it should suffice

Hey! How is this supposed to run? Just saved onto a .sh script an run it? No arguments? How can I add zones or remove? I was looking to only block Australia and China as its not under their Google Cloud free tier policy. I think this script has lots of potential for this specific use case.

Hi @kiraitachi!
Yes, ideally this should be put in something like a cronjob (the GeoIP DB changes from time to time), but can as well be a one-off script.
There are no arguments as of now (I'm also not using this script anymore, just providing support from time to time), BUT you need to edit the script once to set the nations you DON'T want to block.
This will block all the IPs in the GeoIP database except the ones you 'whitelist'.
The 'whitelisting' is done by deleting the zones you want to allow traffic from (look at line 83 in this case)

Sorry again for being so late

@Talisker69
Copy link

Hi All,
I don't no if someone have try this script recently but for me it's not working and break firewalld on Fedora37 when using nftables (that is the default settings). I'm interested by your feedback on this distrib. But thanks a lot anyway for the script workflow.

@Pandry
Copy link
Author

Pandry commented Mar 1, 2023

Hi @Talisker69!
Unfortunately I’m not using nor maintaining the script from a long time, but I try to offer support from time to time.

break firewalld on Fedora37 when using nftables

Can you be a bit more specific? Maybe posting the errors you are encountering.
I suspect it may be an ipset-related issue (in fact i found an issue about its support )
If that’s the case, I’ve found some info on the nftables website

@Talisker69
Copy link

Talisker69 commented Mar 2, 2023

Hi @Pandry,
Please find below the trace of errors. I confirm that the problem come from the backend not from firewalld, so if your are using iptables as backend you should not have this problem. Firewalld is just the frontend. So after summit the blacklist to the drop zone the cpu rise up (1 theard at 100%), the box refuse all connexion to stop all ports, hopefully I don't loose my ssh connection and I rebooted. After the reboot the firewalld refuse to startup due to errors and reload the default config. So I remove all files in /etc/firewalld/ipsets .... and reboot again so every back to normal. By the way, i'm using selinux just for the record ...

Mar  1 19:09:03 odroid01 firewalld[818]: ERROR: INVALID_IPSET: blacklist
Mar  1 19:17:34 odroid01 audit[818]: NETFILTER_CFG table=firewalld_policy_drop:22 family=1 entries=16 op=nft_register_chain pid=818 subj=system_u:system_r:firewalld_t:s0 comm="firewalld"
Mar  1 19:17:34 odroid01 audit[818]: NETFILTER_CFG table=firewalld:23 family=1 entries=260 op=nft_unregister_table pid=818 subj=system_u:system_r:firewalld_t:s0 comm="firewalld"
Mar  1 19:17:34 odroid01 audit[818]: NETFILTER_CFG table=firewalld:24 family=1 entries=1 op=nft_register_table pid=818 subj=system_u:system_r:firewalld_t:s0 comm="firewalld"
Mar  1 19:36:15 odroid01 systemd[1]: Stopping firewalld.service - firewalld - dynamic firewall daemon...
Mar  1 19:37:46 odroid01 systemd[1]: firewalld.service: State 'stop-sigterm' timed out. Killing.
Mar  1 19:37:46 odroid01 systemd[1]: firewalld.service: Killing process 818 (firewalld) with signal SIGKILL.
Mar  1 19:37:46 odroid01 systemd[1]: firewalld.service: Killing process 914 (gmain) with signal SIGKILL.
Mar  1 19:37:46 odroid01 systemd[1]: firewalld.service: Main process exited, code=killed, status=9/KILL
Mar  1 19:37:46 odroid01 systemd[1]: firewalld.service: Failed with result 'timeout'.
Mar  1 19:37:46 odroid01 systemd[1]: Stopped firewalld.service - firewalld - dynamic firewall daemon.
Mar  1 19:37:46 odroid01 systemd[1]: firewalld.service: Consumed 20min 11.543s CPU time.
Mar  1 19:37:46 odroid01 audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=firewalld comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=failed'
Mar  1 19:38:14 odroid01 systemd[1]: Starting firewalld.service - firewalld - dynamic firewall daemon...
Mar  1 19:38:14 odroid01 systemd[1]: Started firewalld.service - firewalld - dynamic firewall daemon.
Mar  1 19:38:14 odroid01 audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=firewalld comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
Mar  1 19:38:15 odroid01 audit[815]: NETFILTER_CFG table=firewalld:2 family=1 entries=1 op=nft_register_table pid=815 subj=system_u:system_r:firewalld_t:s0 comm="firewalld"
Mar  1 19:38:27 odroid01 NetworkManager[824]: <warn>  [1677695907.6278] firewalld: [d13620f7af927370,change:"enp1s0"]: complete: request failed (Timeout was reached)
Mar  1 19:38:27 odroid01 NetworkManager[824]: <warn>  [1677695907.7908] firewalld: [73161c0c3b87df87,change:"enp2s0"]: complete: request failed (Timeout was reached)
Mar  1 19:52:13 odroid01 systemd[1]: Stopping firewalld.service - firewalld - dynamic firewall daemon...
Mar  1 19:52:13 odroid01 systemd[1]: firewalld.service: Deactivated successfully.
Mar  1 19:52:13 odroid01 systemd[1]: Stopped firewalld.service - firewalld - dynamic firewall daemon.
Mar  1 19:52:13 odroid01 audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=firewalld comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
Mar  1 19:52:13 odroid01 systemd[1]: firewalld.service: Consumed 13min 55.506s CPU time.
Mar  1 20:03:40 odroid01 systemd[1]: Starting firewalld.service - firewalld - dynamic firewall daemon...
Mar  1 20:03:40 odroid01 systemd[1]: Started firewalld.service - firewalld - dynamic firewall daemon.
Mar  1 20:03:40 odroid01 audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=firewalld comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
Mar  1 20:03:41 odroid01 firewalld[3540]: ERROR: Failed to load user configuration. Falling back to full stock configuration.
Mar  1 20:03:41 odroid01 audit[3540]: NETFILTER_CFG table=firewalld:3 family=1 entries=1 op=nft_register_table pid=3540 subj=system_u:system_r:firewalld_t:s0 comm="firewalld"
Mar  1 20:03:41 odroid01 audit[3540]: NETFILTER_CFG table=firewalld:3 family=1 entries=1 op=nft_unregister_table pid=3540 subj=system_u:system_r:firewalld_t:s0 comm="firewalld"
Mar  1 20:03:41 odroid01 audit[3540]: NETFILTER_CFG table=firewalld:4 family=1 entries=234 op=nft_register_chain pid=3540 subj=system_u:system_r:firewalld_t:s0 comm="firewalld"
Mar  1 20:03:41 odroid01 firewalld[3540]: ERROR: INVALID_IPSET: geoblacklist
Mar  1 20:03:41 odroid01 audit[3540]: NETFILTER_CFG table=firewalld:5 family=1 entries=6 op=nft_register_rule pid=3540 subj=system_u:system_r:firewalld_t:s0 comm="firewalld"
Mar  1 20:03:41 odroid01 audit[3540]: NETFILTER_CFG table=firewalld:6 family=1 entries=394 op=nft_register_obj pid=3540 subj=system_u:system_r:firewalld_t:s0 comm="firewalld"
Mar  1 20:03:41 odroid01 audit[3540]: NETFILTER_CFG table=firewalld:6 family=1 entries=103 op=nft_register_chain pid=3540 subj=system_u:system_r:firewalld_t:s0 comm="firewalld"
Mar  1 21:06:28 odroid01 firewalld[3540]: ERROR: INVALID_IPSET: geoblacklist
Mar  1 21:25:44 odroid01 systemd[1]: Stopping firewalld.service - firewalld - dynamic firewall daemon...
Mar  1 21:25:44 odroid01 audit[3540]: NETFILTER_CFG table=firewalld:7 family=1 entries=394 op=nft_unregister_obj pid=3540 subj=system_u:system_r:firewalld_t:s0 comm="firewalld"
Mar  1 21:25:44 odroid01 audit[3540]: NETFILTER_CFG table=firewalld:7 family=1 entries=258 op=nft_unregister_table pid=3540 subj=system_u:system_r:firewalld_t:s0 comm="firewalld"
Mar  1 21:25:44 odroid01 systemd[1]: firewalld.service: Deactivated successfully.
Mar  1 21:25:44 odroid01 systemd[1]: Stopped firewalld.service - firewalld - dynamic firewall daemon.
Mar  1 21:25:44 odroid01 audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=firewalld comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
Mar  1 21:25:52 odroid01 systemd[1]: Starting firewalld.service - firewalld - dynamic firewall daemon...
Mar  1 21:25:52 odroid01 systemd[1]: Started firewalld.service - firewalld - dynamic firewall daemon.
Mar  1 21:25:52 odroid01 audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=firewalld comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
Mar  1 21:25:52 odroid01 audit[5530]: NETFILTER_CFG table=firewalld:8 family=1 entries=1 op=nft_register_table pid=5530 subj=system_u:system_r:firewalld_t:s0 comm="firewalld"
Mar  1 21:25:52 odroid01 firewalld[5530]: ERROR: Failed to load user configuration. Falling back to full stock configuration.
Mar  1 21:25:52 odroid01 audit[5530]: NETFILTER_CFG table=firewalld:9 family=1 entries=1 op=nft_register_table pid=5530 subj=system_u:system_r:firewalld_t:s0 comm="firewalld"
Mar  1 21:25:52 odroid01 audit[5530]: NETFILTER_CFG table=firewalld:9 family=1 entries=1 op=nft_unregister_table pid=5530 subj=system_u:system_r:firewalld_t:s0 comm="firewalld"
Mar  1 21:25:52 odroid01 audit[5530]: NETFILTER_CFG table=firewalld:10 family=1 entries=234 op=nft_register_chain pid=5530 subj=system_u:system_r:firewalld_t:s0 comm="firewalld"
Mar  1 21:25:52 odroid01 firewalld[5530]: ERROR: INVALID_IPSET: geoblacklist

@Talisker69
Copy link

@Pandry I don't run the script just added 2 countries in the geoblacklist and affect it to the drop zone like you are doing in your script. I don't think that there is any mistake in your script is just my configuration that is a little bit different. But after the years iptables will be deprecated in many linux distributions so be careful.

@Pandry
Copy link
Author

Pandry commented Mar 5, 2023

Yeah, unfortunately this script is pretty old and did not stand to the test of time.
I should look into how to use the nftables backend but I'm not even using CentOS anymore
I'll eventually give it a look, don't count on that

@Talisker69
Copy link

@Pandry
Don't worry pandry I switch to another solution. I prefer now use geoip at the http level (7) with maxmind database (it's free). The problem with nftables finally is Firewalld because the best practice is to use directly nftables (wihout ipset) so you will be obliged to disabled Firewalld so you will have new problems. So it's that why I use blacklist at the level 7 and not at the network level. I don't publish any service at this level. Anyway thanks for you script that en-light me on that technology.

@snarl817
Copy link

I am unable to use this to block countries. I HAD been using iptables with the xt_geoip addon on CentOS 7, and it works fine. BUT, I need to migrate my jump host to a more modern distro, so I installed Fedora 37. Using this script as a starting point (I just have a list of country codes to block), I create an IPSet in firewalld, but when the script attempts to activate the rules, I get a timeout from dbus. Watching the system performance, firewalld spikes the CPU as soon as the ipset is added.

I searched, and apparently this is a known issue: the daemon checks for overlap in the IPSet, and that check is VERY CPU intensive.
firewalld/firewalld#881
This was SUPPOSEDLY fixed last year, but it seems to still be broken. I cloned the current firewalld repo and built from source, but the size of the block ipset still hangs the daemon.

@snarl817
Copy link

Ok, I've done some more digging, and debugging, and the issue is nftables is TERRIBLE at managing large ipsets when using firewalld as a frontend. There are two solutions for this:

  1. Switch the FirewallBackend from nftables to iptables in /etc/firewalld/firewalld.conf
  2. Use nftables to load the the ipset outside of firewalld.

I'm having difficulty locating documentation on HOW to implement #2, so I just switched the backend to iptables. Yes, it's deprecated and will be going away "soon", but I'd imagine that they'll keep it around until libnftables gets fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment