Andrea Sodomaco - ICT scattered considerations

010101010111001101100101001000000111010001101000011001010010000001110011011011110111010101110010011000110110010100101100001000000100110001110101011010110110010100100001

Parliamo di Java, Linux e informatica

How to quickly block access to certain IPs on a Linux system using iptables and kernel network filtering, in an easy, secure and free way. Practical examples related to a web server.

Preamble

The topic has a wide range of solutions, both using OS functions and adopting countless software operating at various levels. It is not the purpose of this page to analyze the topic exhaustively or to provide a solution for the complete protection of a web server.

The purpose is to provide a quick, always available and effective solution that requires some theoretical knowledge and provides the possibility to be developed and customized.

If the practical applications of this solution are not particularly extensive, the theoretical value of the approach that can have an educational purpose is.

Objectives and possible scenarios

When managing a website, whether it is protected by other security mechanisms or not, there may be a need to quickly block some IPs that perform operations dangerous for the security or proper functioning of the site. Sometimes these are real hacker attacks, but sometimes they are just poorly calibrated bots or more malicious than dangerous activities.

There are various ways to do this, such as external firewalls or web server configurations. The tool I propose is the use of the network filtering system integrated into the Linux server. The advantage of this approach is to be always available and very efficient: not everyone has an external firewall, and IP filtering at the web server level could be ineffective in case of very intense DoS attacks, for example.

Advantages/disadvantages of the approach

Advantages:

  • Immediate: you can activate it while under attack without interrupting the service
  • Effective: it intervenes at the lowest level of the system and is therefore able to block any attack
  • Expandable and customizable: you can use the basic infrastructure, but you can also develop something more complex

Disadvantages:

  • Requires root access
  • Requires skills in networking, sysadmin, and bash (but this can be considered a good opportunity to learn)

Before we begin

The Linux network filtering can be used by other tools and software in use on your system (fairly common examples are firewalld and fail2ban). To verify this, run the following command and check the output

# iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

If the result is different from what is reported here, it is very likely that there are other tools that use the kernel's network filtering: do not proceed if you do not know what you are doing!

Let's start with a practical case

I refer to the case of a web server but the example can be easily applied to a mail server or a MySQL installation, or others.

Here is an example of an Nginx log that many webmasters may have seen

97.74.229.113 - - [01/Nov/2022:05:04:59 +0100] "GET /admin//config.php HTTP/1.1" 404 20 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
45.227.254.54 - - [01/Nov/2022:05:54:01 +0100] "\x03\x00\x00/*\xE0\x00\x00\x00\x00\x00Cookie: mstshash=Administr" 400 166 "-" "-"

Whether and to what extent this kind of accesses can be really worrying is beyond the scope of this discussion. Let's assume that we still want to block the IP.

For those who are completely ignorant of iptables, before starting, I recommend taking a look at this how-to

The Immediate Solution

Immediate and drastic solution to block the IP 45.227.254.54:

# iptables -I INPUT -s 45.227.254.54 -j DROP

The command must be executed as root or preceded by the sudo command.

This simple command blocks any access to the machine's networking from the specified address. If the activity of a certain IP is causing malfunctions to your web server, this is how you solve the problem at the root.

After executing the command, the situation will be as follows:

# iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
DROP       all  --  45.227.254.54        0.0.0.0/0           

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination   

To delete all the rules of the INPUT chain, execute the following command (always as root or preceded by sudo)

# iptables -F INPUT

This will restore the initial situation.

Some theory and explanation of the iptables command

The kernel's network filtering passes all incoming traffic through the so-called chains, which are lists of rules made up of two parts: selection criteria (match) and associated action (target).

In particular, there are 3 predefined chains: INPUT, FORWARD, OUTPUT. The part that interests us is that all incoming traffic passes through the INPUT chain, which is initially empty and the default policy is ACCEPT, so all traffic is accepted and passed to the kernel processing making it available to the machine's software.

The command

# iptables -I INPUT -s 45.227.254.54 -j DROP

inserts at the beginning (-I) of the INPUT chain the rule that identifies all traffic coming (-s stands for source) from the IP 45.227.254.54 and associates it with the DROP action (i.e. immediate deletion).

In the situation that is created after executing the command, all incoming traffic passing through the INPUT chain is compared with the inserted rule. If it matches, meaning that it originates from the specified IP address, the associated action (target) is applied. In this case, the traffic is dropped. Traffic that does not match the rule moves on to the next rule, if there is one. Since there are no other rules, the traffic is accepted.

More elaborate solution

Let's develop a better solution to make it more manageable and especially more robust in avoiding interference with other tools or services.

Let's start by observing that attacks usually only target a few services and therefore a few TCP ports. Even in the case of port scanning activity, this will only be annoying on active services and their exposed ports.

Let's take the practical example described above: the idea is to manage the traffic of this service in a separate chain. This solution at least avoids unwanted interactions with other services, especially with SSH.

Let's proceed with the following commands:

# iptables -N myhttp
# iptables -N myblocked
# iptables -I INPUT -p tcp --dport 80 -j myhttp
# iptables -I INPUT -p tcp --dport 443 -j myhttp
# iptables -I myblocked -j DROP
# iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
myhttp     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:443
myhttp     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain myblocked (0 references)
target     prot opt source               destination         
DROP       all  --  0.0.0.0/0            0.0.0.0/0           

Chain myhttp (2 references)
target     prot opt source               destination

In this way, we have created two chains. The myhttp chain is used to direct all http and https traffic (incoming on ports 80 and 443). Traffic that does not concern http or https does not match the rules inserted into the INPUT chain and will therefore still be accepted. The myhttp chain currently contains no rules and all http and https traffic, despite entering the chain, will pass freely. The other chain named "myblocked" blocks all traffic directed to it and is not currently in use.

To block http and https traffic from a specific IP, the following command is sufficient:

# iptables -I myhttp -s 45.227.254.54 -j myblocked

This command inserts a rule into the myhttp chain that forwards traffic coming from IP 45.227.254.54 to the myblocked chain, which in turn blocks it.

The advantage of this approach is that once the initial setup is done, we are sure not to interfere with other services (avoiding the risk of blocking, for example, ssh) since we will be modifying exclusively the myhttp chain. Furthermore, if we insert various IPs into myhttp that point to myblocked chain, we can uniformly manage the desired behavior. For examp

... -j DROP

with

.... -j REJECT --reject-with icmp-port-unreachable
# iptables -I myblocked -j LOG --log-prefix "MYBLOCKED:"
# iptables -n -L myblocked
Chain myblocked (1 references)
target     prot opt source               destination         
LOG        all  --  0.0.0.0/0            0.0.0.0/0            LOG flags 0 level 4 prefix "MYBLOCKED:"
REJECT     all  --  0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

With this solution, we achieve two results. The first is to obtain a log in syslog every time traffic is blocked. The second is to adopt a more correct way to block traffic.

Between "DROP" and "REJECT --reject-with icmp-port-unreachable," the substantial difference is that in the first case, the traffic is completely ignored, while in the second, there is a response from the server that communicates to the sender that the traffic is being refused (see ICMP protocol).

Iptables: DROP or REJECT with icmp-port-unreachable

With DROP, the effect is that the blocked sender perceives a situation identical to when the server is turned off or disconnected from the network. Moreover, with DROP, there is minimal effort for the kernel, which is not employed to give even a minimal response, making any DoS attacks even less effective. On the other hand, a client that is blocked by DROP will try to connect to the server multiple times as expected by the TCP/IP protocol, only giving up after a long enough timeout.

With REJECT with icmp-port-unreachable, on the other hand, the client will have immediate evidence of being blocked (obviously, it cannot know if the service is not active on the server or if only its IP has been blocked). For clients that still respect the protocols, this mode will be more efficient and correct. The downside to this solution is that it makes it evident to a potential hacker that the server exists and may have other vulnerabilities.

A specific case worth mentioning is when protecting an SMTP server (port 25) that sends external mail. In this case, REJECT with icmp-port-unreachable should be used because anti-spam filters could verify the existence of the server, a test that would fail when using DROP.

An alternative that could be considered is icmp-host-unreachable.

Further Insights

There are many topics to delve into and possible enhancements such as making changes persistent, efficiently managing a large number of IPs or ranges, and integrating automatically with your application.

I hope to be able to delve into some of these aspects in other articles based on the feedback I receive.

Screenshot of the IP check result on the website www.abuseipdb.com

Screenshot of the IP check result on the website abuseipdb.com

If suspicious activity from a specific IP is found in the logs, it is possible to check the IP's malicious activity on a specialized website before blocking it. I often use abuseipdb.com for this purpose.

These types of websites not only allow you to verify the danger of an IP, but they can also provide blacklists to use preventively.

Notes on Choosing iptables

iptables is not the only tool that allows manipulation of kernel net filtering. Valid alternatives could be ufw (considered more user-friendly) or nftables (the most modern version of iptables). I prefer iptables because they are often preinstalled, have a vast documentation available online, but I see no disadvantages in using alternatives.

One characteristic of iptables (unlike ufw, for example) is that, by manipulating the kernel's memory tables, the changes made are not permanent and disappear on reboot without explicit measures to save them. This is an extra burden for the development of applications based on the tool, but a huge advantage in case of testing on remote machines, as it will be possible to fix serious problems caused by inappropriate commands by simply rebooting the system.

 

Write to me at for questions, comments, suggestions...