xtables-addons: filter packets by country



The task of blocking traffic from certain countries seems simple, but the first impression is deceiving. Today we will tell you how this can be implemented.



Background



Google search results on this topic are upsetting: most of the solutions have long been "rotten" and sometimes it seems that this topic has been shelved and forgotten about it forever. We have gone through a lot of old records and are ready to share the modern version of the instructions.

We recommend that you read the entire article before executing these commands.

Preparing the operating system



The filtering will be configured using the iptables utility , which requires an extension to work with GeoIP data. Such an extension can be found in xtables-addons . xtables-addons installs iptables extensions as standalone kernel modules, so there is no need to recompile the OS kernel.



At the time of this writing, the current version of xtables-addons is 3.9. However, only 3.8 can be found in the standard Ubuntu 20.04 LTS repositories, and 3.0 in the Ubuntu 18.04 repositories. You can install the extension from the package manager with the following command:



apt install xtables-addons-common libtext-csv-xs-perl


Note that there are small but important differences between version 3.9 and the current state of the project, which we will discuss later. To build from source codes, install all the necessary packages:



apt install git build-essential autoconf make libtool iptables-dev libxtables-dev pkg-config libnet-cidr-lite-perl libtext-csv-xs-perl


Clone the repository:



git clone https://git.code.sf.net/p/xtables-addons/xtables-addons xtables-addons-xtables-addons


cd xtables-addons-xtables-addons


xtables-addons contains many extensions, but we are only interested in xt_geoip . If you don't want to drag unnecessary extensions into the system, you can exclude them from the assembly. To do this, you need to edit the mconfig file . Set y for all desired modules , and n for all unnecessary ones . We collect:



./autogen.sh


./configure


make


And install with superuser rights:



make install


During the installation of kernel modules, an error may appear with the following content:



INSTALL /root/xtables-addons-xtables-addons/extensions/xt_geoip.ko
At main.c:160:
- SSL error:02001002:system library:fopen:No such file or directory: ../crypto/bio/bss_file.c:72
- SSL error:2006D080:BIO routines:BIO_new_file:no such file: ../crypto/bio/bss_file.c:79
sign-file: certs/signing_key.pem: No such file or directory


This situation occurs due to the inability to sign kernel modules, since nothing to sign. You can solve this problem with a couple of commands:



cd /lib/modules/(uname -r)/build/certs


cat <<EOF > x509.genkey


[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
prompt = no
string_mask = utf8only
x509_extensions = myexts

[ req_distinguished_name ]
CN = Modules

[ myexts ]
basicConstraints=critical,CA:FALSE
keyUsage=digitalSignature
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid
EOF


openssl req -new -nodes -utf8 -sha512 -days 36500 -batch -x509 -config x509.genkey -outform DER -out signing_key.x509 -keyout signing_key.pem


The compiled kernel module is installed, but the system does not detect it. Let's ask the system to create a dependency map based on the new module, and then load it:



depmod -a


modprobe xt_geoip


Make sure xt_geoip is loaded into the system:



# lsmod | grep xt_geoip
xt_geoip               16384  0
x_tables               40960  2 xt_geoip,ip_tables


Additionally, make sure that the extension is loaded into iptables:



# cat /proc/net/ip_tables_matches 
geoip
icmp


Everything suits us and all that remains is to add the name of the module to / etc / modules so that the module will work after rebooting the OS. At this point, iptables understands geoip commands, but lacks the data to work with. Let's start loading the geoip database.



Get GeoIP Database



Create a directory that will store information for the iptables extension:



mkdir /usr/share/xt_geoip


At the beginning of this article, we mentioned that there are differences between the source version and the package manager version. The most noticeable difference is the change of the database provider and the xt_geoip_dl script , which downloads the actual data.



Version from the package manager



The script lies along the path / usr / lib / xtables-addons, but when you try to start, you may see a not very informative error:



# ./xt_geoip_dl 
unzip:  cannot find or open GeoLite2-Country-CSV.zip, GeoLite2-Country-CSV.zip.zip or GeoLite2-Country-CSV.zip.ZIP.


Previously, the database used the GeoLite product, now known as GeoLite Legacy, distributed under the Creative Commons ASA 4.0 license by MaxMind . With this product, two events happened at once, which "broke" the compatibility with the extension for iptables.



First, in January 2018, they announced the end of support for the product, and on January 2, 2019, all links to download the old version of the database were removed from the official website. New users are advised to use GeoLite2 product or its paid version GeoIP2.



Secondly, since December 2019, MaxMind announcedabout a significant change in access to their databases. To comply with California consumer protection law, MaxMind has decided to β€œcover up” distribution of GeoLite2 by registration.



Since we want to use their product, we will register on this page.





After that, a message will come to the mail with a request to set a password. Now that we have created an account, we need to create a license key. In your personal account, find the item My License Keys , and then click on the Generate new License Key button .



When creating a key, we will be asked only one question: will we use this key in the GeoIP Update program? We answer in the negative and click on the Confirm button . The key will be displayed in the pop-up window. Save this key in a safe place, as after closing the pop-up window, you will no longer be able to see the full key.





We have the ability to download GeoLite2 databases manually, but their format is not compatible with the format expected by the xt_geoip_build script. This is where GeoLite2xtables scripts come in. For scripts to work, install the NetAddr :: IP perl module:



wget https://cpan.metacpan.org/authors/id/M/MI/MIKER/NetAddr-IP-4.079.tar.gz


tar xvf NetAddr-IP-4.079.tar.gz


cd NetAddr-IP-4.079


perl Makefile.PL


make


make install


Next, we clone the repository with scripts and write the previously obtained license key to the file:



git clone https://github.com/mschmitt/GeoLite2xtables.git


cd GeoLite2xtables


echo YOUR_LICENSE_KEY=\’123ertyui123\' > geolite2.license


We launch the scripts:



#   GeoLite2
./00_download_geolite2
#     (  )
./10_download_countryinfo
#  GeoLite2    GeoLite Legacy 
cat /tmp/GeoLite2-Country-Blocks-IPv{4,6}.csv |
./20_convert_geolite2 /tmp/CountryInfo.txt > /usr/share/xt_geoip/dbip-country-lite.csv
MaxMind imposes a limit of 2000 downloads per day and, with a large number of servers, offers to cache the update on a proxy server.
Note that the output file must be named dbip-country-lite.csv . Unfortunately, 20_convert_geolite2 does not produce a perfect file. The xt_geoip_build script expects three columns:



  • the beginning of the address range;
  • end of address range;
  • country code in iso-3166-alpha2.


And the output file contains six columns:



  • start of address range (string representation);
  • end of address range (string representation);
  • start of address range (numeric);
  • end of address range (numeric);
  • code of the country;
  • the name of the country.


This discrepancy is critical and can be corrected in one of two ways:



  1. edit 20_convert_geolite2 ;
  2. edit xt_geoip_build .


In the first case, we abbreviate printf to the required format, and in the second, we change the assignment of the $ cc variable to $ row -> [4] . After that, you can build:



/usr/lib/xtables-addons/xt_geoip_build -S /usr/share/xt_geoip/ -D /usr/share/xt_geoip


. . .
 2239 IPv4 ranges for ZA
  348 IPv6 ranges for ZA
   56 IPv4 ranges for ZM
   12 IPv6 ranges for ZM
   56 IPv4 ranges for ZW
   15 IPv6 ranges for ZW


Note that the author of GeoLite2xtables does not consider his scripts to be ready for production and suggests following the development of the original xt_geoip_ * scripts. Therefore, let's move on to building from source, in which these scripts have already been updated.



Source version



When installing from source, the xt_geoip_ * scripts are located in the / usr / local / libexec / xtables-addons directory . This version of the script uses the IP to Country Lite database . License - Creative Commons Attribution License, and from the available data those are the most necessary three columns. Download and collect the database:



cd /usr/share/xt_geoip/


/usr/local/libexec/xtables-addons/xt_geoip_dl


/usr/local/libexec/xtables-addons/xt_geoip_build


After these steps, iptables is ready to go.



Using geoip in iptables



The xt_geoip module adds only two keys:



geoip match options:
[!] --src-cc, --source-country country[,country...]
	Match packet coming from (one of) the specified country(ies)
[!] --dst-cc, --destination-country country[,country...]
	Match packet going to (one of) the specified country(ies)

NOTE: The country is inputed by its ISO3166 code.


The way iptables rules are formed generally remain unchanged. To use switches from additional modules, you must explicitly specify the module name with the -m switch. For example, a rule to block incoming TCP connections on port 443 from non-US on all interfaces:



iptables -I INPUT ! -i lo -p tcp --dport 443 -m geoip ! --src-cc US -j DROP


The files generated by xt_geoip_build are used only when creating rules, but are not considered for filtering. Thus, to update the geoip database correctly, you must first update the iv * files, and then recreate all the rules that use geoip in iptables.

Conclusion



Filtering packets by country is a somewhat forgotten strategy. Despite this, software tools for such filtering are developing and, perhaps, soon a new version of xt_geoip with a new geoip data provider will appear in package managers, which will greatly simplify the life of system administrators.






All Articles