Bulk-Adding IPTables Rules
I’ve been using my mod of this handy script to block countries with iptables. One issue with the script is that it is adding rules one-by-one using the iptables -A syntax. This is the proper way to add rules, but it does take a long while. And here’s how you can make it orders of magnitude faster.
Here’s the basic process in the original script:
for each country_code
do
download zone file
get a list of all IPs
for each IP in the list
do
add a logging rule to iptables
add a block rule to iptables
done
done
Here’s what I have in my revised version:
save current iptables config
copy saved config to a temp file
remove (but remember) the COMMIT footer at the end of the config file
for each country_code
do
download zone file
get a list of all IPs
for each IP in the list
do
echo logging rule to temp file
echo block rule to temp file
done
done
move temp file to iptables config file
reload iptables
The iptables command is called after all the rules are already in the config file, and not for every single rule, of which there may be tens of thousands.
Here’s the actual code for this:
function func_add_rules() {
iptables-save > /etc/sysconfig/iptables
tmpfile3=$(mktemp)
/bin/cp -p /etc/sysconfig/iptables ${tmpfile3}
footer="$(sed -n '/^COMMIT/{:a;n;/*$/b;p;ba}' ${tmpfile3})"
sed -i "/^COMMIT/,/*$/d" ${tmpfile3}
for country_code in af cn ua jp
do
wget -O /root/${country_code}.zone ${download_url}/${country_code}.zone
log_msg="${country_code} CountryDrop"
banned_ips=$(grep -Ev "^#|^$" /root/${country_code}.zone)
for ban_ip in ${banned_ips}
do
echo "-A ${chain_name} -s ${ban_ip} -j LOG --log-prefix ${log_msg}" >> ${tmpfile3}
echo "-A ${chain_name} -s ${ban_ip} -j DROP" >> ${tmpfile3}
done
done
echo COMMIT >> ${tmpfile3}
echo "${footer}" >> ${tmpfile3}
awk '/^COMMIT$/ { delete x; }; !x[$0]++' ${tmpfile3} > /etc/sysconfig/iptables
iptables-restore < /etc/sysconfig/iptables
/sbin/service iptables reload
/sbin/service iptables save
}

