msgbartop
MAC OS X, Linux, Windows and other IT Tips and Tricks
msgbarbottom

23 May 17 Disabling the admin security password confirmation in Jira and Confluence

Introduction:
Although in Jira and Confluence the WebSudo, requesting the confirmation of the administrator’s password, are neat security features if you are working in a company where the chances of someone fiddling around with your computer are high. BUT in a very small company, where this risk is almost none, this feature has proven very annoying for me. So I did some research to disable these features in both Jira and Confluence.

Assumptions:
Jira Version: 7.x
Confluence: 6.x

Methods:

In Jira:

– Edit the file /opt/atlassian/jira/atlassian-jira/WEB-INF/classes/jpm.xml
– Look for the property: jira.websudo.is.disabled and set all is values to true as follows:
.....
<property>
<key>jira.websudo.is.disabled</key>
<default-value>true</default-value>
<type>boolean</type>
<admin-editable>true</admin-editable>
<sysadmin-editable>true</sysadmin-editable>
</property>
......

In Confluence

– Edit the file /opt/atlassian/confluence/bin/setenv.sh
– Close to the end where there is a list of multiple components of the variable
CATALINA_OPTS=....
CATALINA_OPTS=....

– Add the following line after this list but before the line: export CATALINA_OPTS
CATALINA_OPTS="-Dpassword.confirmation.disabled=true ${CATALINA_OPTS}"

———-
Note: After these changes Jira and Confluence need to be restarted as follows:
service jira stop
service confluence stop
service jira start
service confluence start

16 May 17 Hardening the SSL security in Apache, Dovecot and Postfix

Introduction:

After having gotten a report from OpenVAS that my SSL security level of the mail server were medium, I looked for ways to improve this.
I found very good sites which helps me making these improvements:
https://weakdh.org/sysadmin.html
https://wiki.dovecot.org/SSL/DovecotConfiguration
https://bettercrypto.org/static/applied-crypto-hardening.pdf
Based on this site and extending to cover dovecot mail service here is the result:

Hardening Apache:

In /etc/apache2/mods-available/ssl.conf
Change the following parameters as follows:
SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!DH+3DES:!RSA+3DES
SSLHonorCipherOrder on

Hardening Dovecot:

Note: you should have openssl >=1.0.0 dovecot >=2.1.x required, better dovecot >=2.2.x because of ECDHE support Dovecot tryies to use PFS by default, so besides the enabled SSL almost no actions are required change the log settings to see the cipher, grep for a login_log_format_elements in dovecot configs and add %k to it
eg:
login_log_format_elements = "user=< %u> method=%m rip=%r lip=%l mpid=%e %c %k"
Configure the allowed ciphers. Server side enforcement works only for dovecot >=2.2.6
In /etc/dovecot/conf.d/ssl.conf
Change some parameters as follows:
ssl_cipher_list = EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH+aRSA+RC4:EECDH:EDH+aRSA:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4
#only for dovecot >=2.2.6, enforce the server cipher preference
ssl_prefer_server_ciphers = yes
#disable SSLv2 and SSLv3
ssl_protocols = !SSLv2 !SSLv3

Add the following parameter:
ssl_dh_parameters_length = 2048
Delete the file /var/lib/dovecot/ssl-parameters.dat
and restart Dovecot service:
service dovecot restart
Dovecote seeing that the Diffie Hellman parameters are assigned to be 2048 bits long and that its file is just been deleted, will regenerate a new one in the background.

Hardening Postfix

In /etc/postfix/main.cf
Change or add the following configuration parameters:
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
smtpd_tls_mandatory_ciphers=high
tls_high_cipherlist=EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA
smtpd_tls_exclude_ciphers = aNULL, eNULL, EXPORT, DES, RC4, MD5, PSK, aECDH, EDH-DSS-DES-CBC3-SHA, EDH-RSA-DES-CBC3-SHA, KRB5-DES, CBC3-SHA
smtpd_tls_dh1024_param_file=/etc/ssl/dh2048.pem

Generate a new Diffie Hellman parameters file as follows:
openssl dhparam -out /etc/ssl/dh2048.pem 2048

21 Jan 17 Mounting a remote directory using SSHFS in Debian Jessie

Introduction:
If you want to mount a directory on a remote server via Internet NFS can be quite a challenge to protect. A good solution would then be to use SSHFS. Here is a shot Howto for Debian Jessie.

Note: In Wheezy and in Jessie before I did an upgrade to the kernel 3.16.0-4-amd64, the following entry in /etc/fstab was working:
sshfs#root@remote.server.com:/remote_dir /local_dir fuse defaults 0 0
BUT, as soon as upgraded Jessie to the kernel 3.16.0-4-amd64, I could not boot any more and the system went into an emergency mode signalizing that I should give the root password or press Ctrl-D to continue. Ctrl-D brought to nowhere and the system just crashed. It was also suggested that I should give the command ‘journalctl -xb’ to find out what was wrong after I had given the root password. This command gave me the indication that ‘process /bin/plymouth could not be executed’. Well, the message is quite misleading since the error was that the new kernel was no more supporting the above older method of mounting a filesystem using SSHFS in /etc/fstab. Commenting this entry in /etc/fstab allowed me to boot and later to change the entry for a new one that worked which follows.

First install the needed package:
apt-get install sshfs
Then considering the two scenarios:
1 – User mount: Mounting a remote directory belonging to user ‘media’ using SSHFS and the ssh keys. User ‘media’ was configured in both servers to have the same UID.
2 – Root mount: Mounting a remote directory belonging to root using SSHFS and the ssh keys.

Scenario 1:(user mount)

On remote server run the command:
useradd -d /home/media/ -u 2017 -s /bin/bash media
passwd media (give any password, that will need to be deleted later anyway)
mkdir -p /home/media/share1
chown -R media: /home/media/share1

On local server run the commands:
useradd -d /home/media/ -u 2017 -s /bin/bash media
mkdir -p /home/media/share1
chown -R media: /home/media/share1
su - media
ssh-keygen -t rsa (press <Enter> to all questions)
ssh-copy-id media@remote.server.com (enter media user's temporary password of remote server)

Enter in /etc/fstab:
media@remote.server.com:/home/media/share1 /home/media/share1 fuse.sshfs noauto,x-systemd.automount,_netdev,user,idmap=user,follow_symlinks,identityfile=/home/media/.ssh/id_rsa,allow_other,default_permissions,uid=2017,gid=2017 0 0
Back on remote server, disable the user’s password using the command:
passwd -l media
———- End scenario 1 ———–

Scenario 2 (root mount)

ssh-copy-id root@remote.server.com (enter 'root' password of remote server)
Enter in /etc/fstab:
root@remote.server.com:/share2 /share2 fuse.sshfs noauto,x-systemd.automount,_netdev,user,idmap=user,follow_symlinks,identityfile=/root/.ssh/id_rsa,allow_other,default_permissions,uid=0,gid=0 0 0
———- End scenario 2 ———–
Then reboot the system
reboot
After reboot you won’t see yet any mount entry if you give the command ‘mount’. It will only appear after the first attempt to access the mount point in the local server. This mount is governed by systemd. You can’t quite control manually the mounting and unmounting of this new method since it’s controlled by systemd. I’m still looking for ways to manually mount/unmount this systemd controlled mount. Any suggestions is welcome.

19 Jan 17 Installing TeamPass in Debian Jessie

Introduction:
TeamPass is a very good Web application which can store securely Passwords for single person or teams. Here are the steps I used to install it in Debian Jessie. These instructions can also be used with no or minimal changes to install TeamPass in other Debian or Ubuntu systems.
These instruction are partly based on this site:
http://teampass.net/2013-12-31-installation-on-linux-server
and these
http://bourntech.com/blog/install-teampass-on-ubuntu-14-6lts/
https://github.com/nilsteampassnet/TeamPass/

Steps:
Create the user that will be used as owner of the TeamPass htdocs and Apache TeamPass requests processes.
useradd -d /opt/teampass/ -s /bin/false passwords
Prepare the teampass home directories
mkdir -p /var/www/teampass/fcgi/tmp
mkdir /var/www/teampass/logs
mkdir /var/www/teampass/auth
cd /var/www/teampass/
#Get the latest released software:
wget --no-check-certificate https://github.com/nilsteampassnet/TeamPass/archive/master.zip
unzip master.zip

Install the required packages:
apt-get install php5-mcrypt php5-mysqlnd php5-gd openssl apache2-suexec-custom apache2-mpm-prefork libapache2-mod-fcgid libapache2-mod-php5 php5-cgi mariadb-server
In order to allow Apache to modify files inside the TeamPass htdocs we use FCGI/suexec Modules.
a2enmod fcgid
a2enmod suexec
a2enmod ssl

Create the fcgi_wrapper script:
touch /var/www/teampass/fcgi/php-fcgi-starter
mcedit /var/www/teampass/fcgi/php-fcgi-starter

Content:
#!/bin/sh
export PHPRC=/var/www/teampass/fcgi/
export PHP_FCGI_CHILDREN=2
export PHP_FCGI_MAX_REQUESTS=500
exec /usr/bin/php5-cgi

Make it runnable but not for others:
chmod 750 /var/www/teampass/fcgi/php-fcgi-starter
Copy the php.ini from system to /var/www/teampass/fcgi/
cp /etc/php5/apache2/php.ini /var/www/teampass/fcgi/
Adapt the php.init to the site:
mcedit /var/www/teampass/fcgi/php.ini
Add the following 2 lines at the end:
upload_tmp_dir = /var/www/teampass/fcgi/tmp
session.save_path = /var/www/teampass/fcgi/tmp

And look for the configuration: max_execution_time and change its value from 30 to 60. Eg.
max_execution_time = 60
Create the Apache2 configuration:
Content of config file in /etc/apache2/sites-available/teampass.mydomain.com.conf:
# ============ https://teampass.mydomain.com ==================
<virtualhost *:443>
ServerName teampass.mydomain.com
DocumentRoot /var/www/teampass/TeamPass-master
SuexecUserGroup passwords passwords
<directory /var/www/teampass/TeamPass-master>
Options -Indexes +FollowSymLinks +ExecCGI
FCGIWrapper /var/www/teampass/fcgi/php-fcgi-starter .php
AddHandler fcgid-script .php
DirectoryIndex index.php
Require 192.168. granted
AuthType Basic
AuthName "Private area"
AuthUserFile /var/www/teampass/auth/web.auth
Require valid-user
Satisfy all
</directory>
SSLEngine On
SSLCertificateFile /etc/letsencrypt/live/teampass.mydomain.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/teampass.mydomain.com/privkey.pem
SSLCACertificateFile /etc/letsencrypt/live/teampass.mydomain.com/chain.pem
ErrorLog /var/www/teampass/logs/error_log
CustomLog /var/www/teampass/logs/access_log combined
</virtualhost>

Create the first layer(BASIC) Authentication credentials for first user:
htpasswd -c /var/www/teampass/auth/web.auth username
Give the whole directory ownership to ‘passwords’ user
chown -R passwords: /var/www/teampass/
NOTE: Before you restart your Apache2 service, make sure the Certificate is been issue and installed in the directory: /etc/letsencrypt/live/teampass.mydomain.com/
You can use the instructions on this link to install LetsEncrypt software:
//tipstricks.itmatrix.eu/?s=letsencrypt&x=0&y=0

Enable Apache’s new configuration:
a2ensite teampass.mydomain.com
Restart Apache to activate it’s new configuration:
service apache2 restart
Prepare the suexec permissions files
echo "/var/www/teampass" >> /etc/apache2/suexec/www-data
echo "/var/www/teampass" > /etc/apache2/suexec/passwords
echo "TeamPass-master" >> /etc/apache2/suexec/passwords

IMPORTANT: We need to make sure that the cgi-script called by suexec is residing under the Server’s DocumentRoot for suexec to be allowed to run, therefore we installed the site under /var/www/teampass(which is located under the Server’s DocumentRoot(/var/www/) NOT meaning the VirtualHost’s DocumentRoot. A symlink is allowed here.

Preparing the MySQL database:

Create the new Database in MySQL:
Follow theses instructions:
1) Connect to mysql as root:
mysql -p -u root
PW: ******

2) Create the DB, user and user access rights:
CREATE DATABASE pwdb CHARACTER SET utf8 COLLATE utf8_bin;
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,ALTER,INDEX on pwdb.* TO 'pwuser'@'localhost' IDENTIFIED BY 'password';
flush privileges;

Quit Mysql:
quit;
3) Tip: To confirm if the permissions were granted successfully, log into the DB server with the PWDB DB user(pwuser) and run the command below:
SHOW GRANTS FOR 'pwuser'@'localhost';
4) Quit Mysql:
quit;
Installing TeamPass via the web interface:
In the browser:
https://teampass.mydomain.com/install/install.php
Fill-in the appropriate, paths, MySQL credentials and extra settings and save this configuration.
You are then ready to use TeamPass

19 Jan 17 SSH doesn’t accept my key since upgrade Mac OS X to Sierra

Introduction:
I have two MacBooks. One that still has Mavericks OS X and one that I just upgrade to Sierra OS X.
Since the upgrade I can’t connect via SSH to one of my Linux servers using the RSA/DSA Keys any more.
It always asks for a password. After adding the ‘-v’ option to the ssh command line, to see the handshaking, I noticed the following line:
debug1: Skipping ssh-dss key /Users/michel/.ssh/id_dsa - not in PubkeyAcceptedKeyTypes
After doing some research in Google, it was said that the DSA keys are no more ‘secure’.
In order to make it work again against the same DSA keys it was suggested to do the following which worked:

Note: This solution is not recommended to be used because of the old DSA keys.
Solution:
In MAC edit(or create if not existing) the file ~/.ssh/config and add the following line:
PubkeyAcceptedKeyTypes +ssh-dss

13 Dec 16 Changing Linux system password in bash script

Introduction:
I created a script that creates a full email account for a new user including setting the password.
I was looking for a way to change/set the password programmatically in the script using clear text passwords provided in variables.
I took this information for the man page of chpasswd

Some solution examples:
Changing/setting the password using the existing encryption provided by PAM system:
echo 'username:cleartext_password' | chpasswd
Changing/setting the password using a different encryption method(Not recommended)
echo 'username:cleartext_password' | chpasswd -c METHOD
METHODS:
Use the specified method to encrypt the passwords.
The available methods are DES, MD5, NONE, and SHA256 or SHA512 if your libc support these methods.

Changing/setting the password using already encrypted password:
echo 'username:encrypted_password' | chpasswd -e
Changing/setting the password for list of users:passowrds
chpasswd < users:passwords_list_file
(one line per user:password in the file)

02 Dec 16 Discover live hosts on a network under Linux

There are lost of tools available to scan a network and list the IPs of the hosts that are live.
Here is one that I find quite cool using nmap with the following command(for example for the LAN network 192.168.100.0/24):
Reference: http://security.stackexchange.com/questions/36198/how-to-find-live-hosts-on-my-network
nmap 192.168.100.0/24 -n -sP | grep report | awk '{print $5}'
the result could be for example:
192.168.1.1
192.168.1.11
192.168.1.12
192.168.1.13
192.168.1.14
192.168.1.15
192.168.1.118
192.168.1.122
192.168.1.123
192.168.1.126
192.168.1.129
192.168.1.133
192.168.1.134
192.168.1.156
192.168.1.159
192.168.1.168
192.168.1.170

22 Nov 16 Forcing pam users to use only FTPS and block SFTP/SSH

Introduction:
I needed to force certain PAM users(configured in /etc/passwd) to use FTPS and block them from using SSH or SFTP.
Here is a solution I found in:
http://askubuntu.com/questions/93411/simple-easy-way-to-jail-users

Solution:
Add to /etc/shells a new shell:
vim /etc/shells
Add one line:
/bin/false
Save. For each user you want to deny ssh/sftp, change the user’s shell:
usermod -s /bin/false userx
Now userx cannot log in via ssh/sftp.
Install vsftpd:
apt-get install vsftpd
Edit the config file:
vim /etc/vsftpd.conf
And some changes….
anonymous_enable=NO
local_enable=YES
chroot_local_user=YES

Save. Restart vsftpd:
/etc/init.d/vsftpd restart

30 Oct 16 Resolving Mysql error: Too many open files

Introduction:
As I upgraded from Mysql 5.5 to 5.6 suddenly some sites were showing the following error:
...... Too many open files
The issue has to do with the present limitations given to the system and PAM system to open max 1024 files. After doing some research I found this site below here which is in German in which the following is explained:
https://www.filewalker.de/ulimit-mysql-open_files_limit/

STEPS:
Check the files-open limits or running mysql server:
mysql -p -u root
mysql> SHOW VARIABLES LIKE 'open%';

The very possible output:
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| open_files_limit | 1024 |
+------------------+-------+
1 row in set (0.00 sec)

That means that Mysql server gets to open maximum 1024 which seems too little for Mysql 5.6.

Raising this limit
Edit the file /etc/security/limits.conf and add the following lines:
mysql hard nofile 65535
mysql soft nofile 65535

This will raise the limit of open files to 65535 for the user mysql only.
If you want to rise this limit for all users then replace the word mysql for *
eg.
* hard nofile 65535
* soft nofile 65535

And according to this site edit the file /etc/pam.d/common-session and add this line at the end:
session required pam_limits.so
Note: I’m not sure this step is really needed though. Some people did try without it and it also worked. For me, in Debian Wheezy, I had to do this otherwise I was still getting the error.

For systems that run systemd instead of InitV do the following:
Edit file /usr/lib/systemd/system/mysqld.service
Add these 2 lines at the end:
LimitNOFILE=65535
LimitNPROC=65535

Restart Mysql server and test it again
service mysql restart
mysql -p -u root
mysql>> SHOW VARIABLES LIKE 'open%';

The hopeful output:
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| open_files_limit | 65535 |
+------------------+-------+
1 row in set (0.00 sec)

This error should no more appear.

26 Sep 16 Blocking all traffic from individual countries using IPSet and IPTables

Introduction:
As I looked at the syslog I found too often that SSH login attacks are coming either from China or from Russia. Having enough of that, and anyway not expecting any traffic from any of these countries, although I use fail2ban still I decided to block any traffic coming from these 2 countries. Fail2ban is a great tool for blocking unsuccessful attempts to login. BUT it seems that many attemps(thousands) per day are still going through. I can only assume that the attacker is using parallel sending of attempts and till Fail2ban(based on auth logs) reacts many have gone through.
To do a full blocking of IPs with preloaded lists of IP ranges, I started by using iptables with one rule per IP range, BUT the loading of the rules was taking too long and more importantly, loading all IP ranges, as pure iptables rules, made my server unstable, meaning … it crashed!!! It is said that more than max. 25,000 rules in the iptables, especially larger than 27,000, rules may put the kernel in an unstable state.
To remedy to that I use ipset with iptables. ipset is especially conceived to deal with large IP Range lists(fast access hash tables) which can contain up to 65536 entries.

NOTE: The script below is only valid for Debian based Linux distributions. For other distributions you will need to adapt the script accordingly.

Principle of this Countries Blocking protection:
The IP ranges in CIDR format are picked up from the web site http://www.ipdeny.com/ipblocks/data/countries/ and entered in the IPSet’s individual lists which are named by country codes and then referenced by iptables to define the TARGET (what to do with the IPs that match:DROP)
NOTE: In this example the script sets iptables rules target to DROP instead of REJECT to avoid high traffic of TCP/IP stack rejection responses. DROP doesn’t respond anything.

IMPORTANT NOTE: This script below should be run AFTER you loaded your regular firewall rules. It INSERTS the new iptables rules in such a way that any incoming packets from those defined countries will be blocked BEFORE any further processing in your firewall.

Steps:
#!/bin/bash
# Description: Uses IPSET and IPTABLES to block full countries from accessing the server for all ports and protocols
# Syntax: countries_firewall.sh countrycode [countrycode] ......
# Use the standard locale country codes to get the proper IP list. eg.
# countries_firewall.sh cn ru ro
# Will create tables that block all requests from China, Russia and Romania
# Changes: 13.11.2016 Initial creation of script
# Note: To get a sorted list of the inserted IPSet IPs for example China list(cn) run the command:
# ipset list cn | sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4
# #############################################################################
# Defining some defaults
iptables="/sbin/iptables"
tempdir="/tmp"
sourceURL="http://www.ipdeny.com/ipblocks/data/countries/"
#
# Verifying that the program 'ipset' is installed
if ! (dpkg -l | grep '^ii ipset' &>/dev/null) ; then
echo "ERROR: 'ipset' package is not installed and required."
echo "Please install it with the command 'apt-get install ipset' and start this script again"
exit 1
fi
[ -e /sbin/ipset ] && ipset="/sbin/ipset" || ipset="/usr/sbin/ipset"
#
# Verifying the number of arguments
if [ $# -lt 1 ]; then
echo "ERROR: wrong number of arguments. Must be at least one."
echo "countries_firewall.sh countrycode [countrycode] ......"
echo "Use the standard locale country codes to get the proper IP list. eg."
echo "countries_firewall.sh cn ru ro"
exit 2
fi
#
# Now load the rules for blocking each given countries and insert them into IPSet tables
for country ; do
# Read each line of the list and create the IPSet rules
# Making sure only the valid country codes and lists are loaded
if wget -q -P $tempdir ${sourceURL}${country}.zone ; then
# Destroy the IPSet list if it exists
$ipset flush $country &>/dev/null
# Create the IPSet list name
echo "Creating and filling the IPSet country list: $country"
$ipset create $country hash:net &>/dev/null
(for IP in $(cat $tempdir/${country}.zone) ; do
# Create the IPSet rule from each IP in the list
echo -n "$ipset add $country $IP --exist - "
$ipset add $country $IP -exist && echo "OK" || echo "FAILED"
done) > $tempdir/IPSet-rules.${country}.txt
# Destroy the already existing rule if it exists and insert the new one
$iptables -D INPUT -p tcp -m set --match-set $country src -j DROP &>/dev/null
$iptables -I INPUT -p tcp -m set --match-set $country src -j DROP
# Delete the temporary downloaded counties IP lists
rm $tempdir/${country}.zone
else
echo "Argument $country is invalid or not available as country IP list. Skipping"
fi
done
# Display the result of the iptables rules in INPUT chain
echo "======================================"
echo "IPSet lists registered in iptables:"
$iptables -L INPUT -n -v | grep 'match-set'
# Dispaly the number of IP ranges entered in the IPset lists
echo "--------------------------------------"
for country ; do
echo "Number of ip ranges entered in IPset list '$country' : $($ipset list $country | wc -l)"
done
echo "======================================"
#
#eof

Loggin of the script operation:

As you can see in the script, the adding of IP ranges in the IPSet tables is logged in: $tempdir/IPSet-rules.${country}.txt which is overwritten every time the script is run for the same country.

Starting the script

In order to make sure this firewall add-on starts properly on each boot, but after the user defined firewall, I start it via cron @reboot job after a delay of about 40 sec.(which can be adjusted to you needs) to let other services start, including the firewall service. I’m aware that this method of starting the script is not very elegant but it fits pretty much all variations of Linux distributions whether Sysinit-V or Systemd based. Example of root cron job:
@reboot /bin/sleep 40 ; /bin/bash -c ". /root/.bashrc ; /root/bin/countries_firewall.sh cn ru"

Sending traffic reports per email

In order to send traffic reports per email every day I collect every day the traffic data from iptables, format it and send it by email using the following bash script. This script will then be run every day by cron (put in /etc/cron.daily/) and the traffic counter will be reset.
#!/bin/bash
# Purpose: Sends the blocked traffic report per email and resets the counter
# Syntax: iptables_report
# Dependencies: Systems tools: iptables, awk, column, whois, sendmail
# Changes: 13.11.2016 First implementation of script
#----------------------------------------------------------
HOST=$(cat /etc/hostname | tr 'a-z' 'A-Z')
email="me@myserver.com"
reportsender="cron@$HOST"
subject="BLOCKED Packets report on $(hostname | tr 'a-z' 'A-Z')"
tempdir="/tmp"
file1="iptables_report1.txt"
file2="iptables_report2.txt"
#
#------------ Build the header of the mail to send ------------
echo "From: $reportsender" > $tempdir/$file1
echo "To: $email" >> $tempdir/$file1
echo "Subject: $subject" >> $tempdir/$file1
echo "MIME-Version: 1.0" >> $tempdir/$file1
echo 'Content-Type: text/html; charset="ISO-8859-15"' >> $tempdir/$file1
echo "" >> $tempdir/$file1
echo "<br />" >> $tempdir/$file1
echo -e "<font size=3 FACE='Courier'><pre>" >> $tempdir/$file1
# Formatted message starts here
# Add the country at the end of each line
# Load the header and data to the temporary file 2
echo -e "Packets Bytes Source \n======= ========= ======" >$tempdir/$file2
/sbin/iptables -L -n -v | /bin/grep -v '^ 0' | /bin/grep 'match-set' | /usr/bin/awk '{print $1" "$2" "$11}' >> $tempdir/$file2
#
# Format temp file2 into temp file1
cat $tempdir/$file2 | column -t >> $tempdir/$file1
#
#
# Add the last HTML preformatting End
echo -e "</pre>" >> $tempdir/$file1
echo "" >> $tempdir/$file1
#
#----------------- Send the prepared email ---------------------------
# now format the report and send it by email
cat $tempdir/$file1 | /usr/sbin/sendmail -t
rm $tempdir/$file1 $tempdir/$file2
#
# Reset the iptables counters
/sbin/iptables -Z
#
# eof

Creating the cron job for regular daily reports
Save that file in eg. /etc/cron.daily/iptables_report
Make it runable:
chmod 755 /etc/cron.daily/iptables_report
Example of report email:
Packets Bytes Source
======= ========= ======
188 7852 ru
19295 1150K cn

Manual status:
To get manual status of the iptables rules for the INPUT chain run the command:
iptables -L INPUT -v -n
To get a sorted listing of an IPSet IP list run the command(eg. for Russia):
ipset list ru | sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4