Protection against DoS / DDoS attacks by filtering by Autonomous System Number (ASN)
Introduction
In the light of the New Year holidays, with their inherent attribute - increased activity of DoS / DDoS attacks, I would like to raise one rather rarely used (but at the same time quite effective) way to repel attacks - blocking based on the IP address blocks belonging to a specific provider / Data Center.

On the Internet and on Habré there were a lot of publications on the subject of protection, but basically they come down to the following approaches based on the IP grouping according to various criteria:
- Blocking individual IP attack bots
- Blocking entire subnets to which bots belong
- Blocking entire countries / cities to which attacking bots belong
- Blocking all IP addresses except explicitly allowed
- Blocking IP addresses based on a specific algorithm (including the use of specialized hardware)
But at the same time, one more method of grouping (and, consequently, blocking) IP addresses is completely undeservedly missed - their belonging to autonomous systems (ASN). What is ASN? This is a group of IP addresses that are served by a single provider or Data Center. Conventionally, this is a higher level of hierarchy, immediately following the concept of network / subnet, but having an organizational origin. Let's take Yandex as an example, their autonomous system number is 13238 and it owns the following blocks of IP addresses: bgp.he.net/AS13238#_prefixes as you can see, there is no pattern other than belonging to one ASN for these addresses. It is also worth noting that ASNs come in two types - 16 bit (up to 65635) and 32 bit (up to 2 ^ 32-1).
But how does this technical excursion help protect against intruders? The fact is that there is a fairly wide list of providers (both ISP and Data Centers) who, to put it mildly, do not take the best care of the security of their networks (do not block outgoing DDoS attacks, do not respond to complaints, etc.) and, as a result are quite often the sources of DDoS attacks. Blocking such autonomous systems (temporary, of course) can greatly help in protecting against attacks. Detailed statistics on autonomous systems, which are most often sources of attacks, can be found on the website: stopddos.ru/current (almost real-time statistics)

Determining the autonomous system number to which the IP address belongs
How to determine the autonomous system to which the IP address / network belongs? It is pretty simple. If the IP address is in Europe (and therefore in the jurisdiction of RIPE), then you can use the command: whois ip_address / network. Let's try on Yandex:
whois 93.158.146.0
We draw attention to the ORIGIN field, it just indicates the number of the autonomous system.

If the IP addresses belong to another RIR (AFRINIC, LACNIC, etc.), then for them there is no concept of a route object and here the most universal advice that I can give is to use a special service that allows you to convert the IP address to ASN: www. team-cymru.org/Services/ip-to-asn.html
What is more remarkable about the service from CymRu is the ability to automate and call this operation from the console, which will be very appropriate if used (when protecting against real attacks without it not enough) automated traffic analyzers, log files for searching patterns tey and anomalies in the context of certain ASN.
Well, let's say, at this stage, we found an ASN (usually, of course, from a few to a few dozen), from which the attack comes, the next step is to check who it belongs to and for what purpose, so as not to accidentally cut off your own customers, this can be done through a service from Hurricane Electric, bgp.he.net/ASXXXX , where instead of XXXX you need to put the detected autonomous system number.
Blocking traffic from / to a specific ASN
But how do we block traffic that comes to us from a specific ASN? Any backbone provider has this function, a data center or a telecom operator (and it is implemented using the BGP protocol), but it is almost impossible to get this function for the end user. Therefore, we will use Debian Wheezy and the iptables packet filter to cut off traffic from spurious ASNs.

Of course, a standard solution that will allow you to do something in style:
iptables -I INPUT -p tcp --dport 80 -m asn --asn-number 11222 -j DROP
It does not exist yet, so we have to improvise!
Two different approaches immediately come to mind - ipset and geoip (yes, you will have a question - what does it have to do with the question, but more on that later). ipset allows you to block traffic belonging to a set of IP addresses or a set of IP networks, which in principle suits us. But this is not particularly flexible and I'm not sure that the Linux kernel will be enough if we create, say, 120 hashes for the autonomous systems we need and managing such a set of hashes will be very, very problematic.
Quite by chance, in the process of studying the xtables GeoIP module, it occurred to me that it uses about the same algorithm for determining whether a network belongs to a certain country, which we need to determine whether it belongs to a specific autonomous system. In addition, there are a number of good comments from the author of xtables GeoIP, judging by which the approach used by him is more optimal: xtables-addons.sourceforge.net/geoip.php
So, let's first assemble and install the xtables geoip module and after that we will unify it for solving the initial problem - blocking by ASN.
Install xtables GeoIP
There were a lot of such instructions, they are quite brief, so I will allow myself to give a complete instruction here.
Install the required packages:
apt-get install xtables-addons-common xtables-addons-source
A lot of work has been done in Debian Wheezy with Xtables and now there is no need to perform any additional gestures to get working modules from the Xtables package. Also, due to the use of the DKMS framework, there is no need to manually rebuild the modules when updating / replacing the kernel - the system will solve all this automatically.
Now a few words about how GeoIP works. It uses a rather clever (in my opinion) approach, when lists of IP networks belonging to a certain country are given in binary format, stored in the server’s file system, and when the iptables command invokes this country, they are loaded into memory. This allows you to ensure high speed and save memory, since the full set of IP addresses of all networks in the world takes almost 500 megabytes in uncompressed form.
For xtables GeoIP, the network-country mapping databases taken from the MaxMind website are used, but geoip is required to manually download and convert to the format that the xtables kernel module will accept.
Go:
cd /tmp
/usr/lib/xtables-addons/xt_geoip_dl
After this operation, in the current folder, two files with the CSV extension will be found, which respectively contain lists of IP networks for the IPv6 and IPv4 protocols, indicating which countries they belong to.
Now we need to convert these files to binary format:
mkdir -p /usr/share/xt_geoip
/usr/lib/xtables-addons/xt_geoip_build -D /usr/share/xt_geoip *.csv
During the conversion process, we will see many interesting information messages, for example, the number of IP v4 / v6 ranges for each country:
759 IPv6 ranges for RU Russian Federation
5401 IPv4 ranges for RU Russian Federation
Everything, we are ready to work, we will try to cut off traffic that comes, for example, from Zimbabwe:
iptables -I INPUT -p tcp --dport 80 -m geoip --src-cc ZW -j DROPThe moment we give this command, the file /usr/share/xt_geoip/LE/ZW.iv4, which contains a list of IP countries, will be taken from the file system and loaded into the kernel.
Pay attention friends! In no case do not use similar in production NEVER-YES. This is the best practice, as you can not do on the Internet. This can only be done temporarily, for example, in the case of active opposition to DDoS / DoS attacks or just to calculate how much traffic goes from each country. Always keep in mind that the relevance of GeoIP databases leaves much to be desired and your key clients from New York (which, of course, are denied access to your resource) may be banned by you Zimbabwe.
Creating a database on networks owned by ASN in MaxMind format.
To simplify our life as much as possible, let's try to create a network-ASN mapping base in the same format that MaxMind stores network-country mapping data. With this approach, we can use the xt_geoip_build script without any changes.
How to create a similar base? Firstly, we will need the current fingerprint of the Internet routing table, since information about the affiliation of networks of a particular ASN changes every minute and therefore it is not possible to always have an up-to-date database. Where to get this print? It is always up-to-date in the MRT TABLE DUMP V2 format at Routevievs.org: archive.routeviews.org/bgpdata .
But there is a small problem with this format - it is very difficult to analyze and therefore we need a converter that is developed by RIPE and is called BgpDump: bitbucket.org/ripencc/bgpdump/wiki/Home
Unfortunately, there is no such converter in the Debian repository and we will have to collect it from the source code, this is pretty trivial, I give the instruction below:
apt-get install -y libbz2-dev
cd /usr/src
wget http://www.ris.ripe.net/source/bgpdump/libbgpdump-1.4.99.13.tgz
tar -xf libbgpdump-1.4.99.13.tgz
cd libbgpdump-1.4.99.13
./configure --prefix=/opt/libbgpdump
mkdir /opt/libbgpdump
make
mv bgpdump /opt/libbgpdump
But the data format that BgpDump generates does not match the MaxMind format, and we need one more converter (fortunately, a lot simpler) that we implemented on Perl, you can get it at: raw.github.com/FastVPSEestiOu/xt_asn/ master / bgp_table_to_text.pl , then put it at /opt/bgp_table_to_text.pl and set the exec flag (chmod + x).
Now we have a complete set of software for generating the ASN network base in MaxMind format. To implement the entire task, a number of bash commands are required:
rm -f /opt/bgp/asn.csv
mkdir /opt/bgp
# http://phpsuxx.blogspot.com/2011/12/full-bgp.html
yesterday_date=$(date --date='1 days ago' '+%Y.%m')
yesterday_date_with_day=$(date --date='1 days ago' '+%Y%m%d')
# get routing data for yesterday at 5 o'clock
wget http://archive.routeviews.org/bgpdata/${yesterday_date}/RIBS/rib.${yesterday_date_with_day}.0600.bz2 -O /opt/bgp/rib.bz2
# Обращаю внимание, что следующие команды выполняются мягко говоря "долго" (25 минут на i7 2600)
/opt/libbgpdump/bgpdump /opt/bgp/rib.bz2 | /opt/bgp_table_to_text.pl > /opt/bgp/asn.csv
After that, we convert according to the same scheme as the Max Mind GeoIP data:
/usr/lib/xtables-addons/xt_geoip_build -D /usr/share/xt_geoip /opt/bgp/asn.csv
As a result of the work of the command, almost 100 thousand files (2 for each ASN) will be created in the / usr / share / xt_geoip / LE / folder and they will be used to load into the kernel filtering module.
Modifying xtables geoip to use it to determine if an IP belongs to a specific ASN
If we try to replace the name of the ZW country in the iptables command with the ASN number, for example, 11222, then we get the error:
geoip: invalid country code '11222'
What to do? Look inside xt_geoip. Here are a few words about how GeoIP works - it consists of a plugin for iptables (userspace), which loads the rules into the kernel and the kernel module (kernel space, respectively). After a quick search by code, we find that the Country Code in the ISO3166 format is stored in the unsigned 16-bit number format, which can store numbers up to 65535.
As we mentioned earlier, the ASN format is currently adopted as 32-bit, so filtering traffic from / to 32-bit ASN (for example, 190111) will require a little improvisation - you will need to find a free ASN in the first 65 thousand (for example, it’s currently free ASN 170) and transfer the list of networks in binary format to it (mv /usr/share/xt_geoip/LE/190111.iv4 /usr/share/xt_geoip/LE/170.iv4), but without forgetting that the ASN number is used "replaced".
Such a hack will work perfectly even if you need to operate with all ASNs of the world! Their total number today is ~ 46000 and can easily interfere with permutations of 16-bit unsigned numbers. If, at the time of reading the article, ASN becomes more than 65 thousand, then you will have to patch the core of the GeoIP module, but it will be quite simple - you will need to replace short int with a full int or even long (what if 64 bit ASNs appear?).

To make it possible to use ASNs instead of two-letter country codes, we will patch the code a bit. Namely, we comment out the block in which the check is made, so that the specified iptables argument “country” is exactly the two-letter ISO country code:
//if (strlen(cc) != 2) /* Country must be 2 chars long according
// to the ISO3166 standard */
// xtables_error(PARAMETER_PROBLEM,
// "geoip: invalid country code '%s'", cc);
// Verification will fail if chars aren't uppercased.
// Make sure they are..
//for (i = 0; i < 2; i++)
// if (isalnum(cc[i]) != 0)
// cc[i] = toupper(cc[i]);
// else
// xtables_error(PARAMETER_PROBLEM,
// "geoip: invalid country code '%s'", cc);
And after that, we replace the packing code of two 8-bit characters into a 16-bit number with a code that simply reads the 16-bit number from the string and saves it:
//cc_int16 = (cc[0] << 8) | cc[1];
// Convert 16 bit unsinged integer (up to 65535)
sscanf(cc, "%d", &cc_int16);
You will also need to change the code that displays the country code using the internal numeric representation of the country (16 bit number), now we just display the number without conversion:
-printf("%s%c%c", i ? "," : "", COUNTRY(info->cc[i]));
+printf("%sxas%d", i ? "," : "", info->cc[i]);
In this case, I allowed myself to replace asn with xas, since in some cases (32 bit ASN) this is not a real ASN number (but a wildcard) and I wanted to emphasize this.
The final patch file can be found here in our repository on GitHub: raw.github.com/FastVPSEestiOu/xt_asn/3e3eebe8b2136d148fe71adc1218a656c363ada2/libxt_geoip_patched.c
Now we have to put it in a small package, we need to compile it for compilation extension module for iptables working in user space) by applying this patch to it:
cd /usr/src
apt-get install -y dpkg-dev devscripts build-essential fakeroot
apt-get source xtables-addons-common
apt-get build-dep -y xtables-addons-common
cd xtables-addons-1.42
# заменяем на патченную версию
wget https://raw.github.com/FastVPSEestiOu/xt_asn/3e3eebe8b2136d148fe71adc1218a656c363ada2/libxt_geoip_patched.c -Oextensions/libxt_geoip.c
dpkg-source --commit
Вводим "Patch for xtables geoip - ASN resolver"
debuild -us -uc
Now install the patched package:
dpkg -i /usr/src/xtables-addons-common_1.42-2_amd64.deb
And after that, you can use 16 bit ASN numbers in ipables rules:
iptables -I INPUT -p tcp --dport 80 -m geoip --dst-cc 11222 -j DROP
Now you are ready to repel another type of attack! In addition, similar methods can be used to analyze legitimate traffic that goes to your server :)
Friends! Good luck to you next year and fewer DDoS attacks, your FastVPS!
