1

Using Linux Debian Bookworm.

Problem

I want to block all incoming connections to my server coming from specific countries.

Edit

As someone pointed out in the comments, I really shouldn't be doing this with iptables since this will grind my server to a halt once the list of IP addresses it blocks grows to an unmanageable size (like thousands of IP addresses). Instead, I should use ipset (to block entire ranges). Problem with that is that it's depending on lists I need to download on a regular base. I want something I set once (preferably).

So how can I stop connections from specific countries? Traffic (and sometimes brute force attacks) originating from China and Russia is getting out of hand. They bring my server to its knees regularly. They don't adhere to the robots.txt file and they crawl the site very aggressively (with hundreds, sometimes thousands of connections simultaneously). I really need to stop that. My guesstimate is that well over 90% of all traffic my server handles is malicious/malformed.

Edit 2

I found some online tutorials (like this one) how to do this, but it seems these tutorials are pretty old. Also, it requires downloading and compiling/installing some modules. I'm worried this might break in the future (when updating/upgrading other packages or even the distribution) or might become a security risk in the future. I keep my server up to date and current (by running apt-get update / apt-get upgrade / apt-get dist-upgrade regularly).

Original Message

I found a script online that (in a nutshell) gets a list of ip addresses of established connections every second, then uses geoiplookup to get the IP address' country. If country is from the list of countries you would like to block, it adds the ip address to your firewall filter using iptables. I made a few slight changes to the script (making it more readable and because I wasn't interested in this script sending me an email every time it blocked an ip address). This script is then run every minute through crontab:

#!/bin/bash
# Script found on lautenbacher.io"

end=$((SECONDS+55))

while [ $SECONDS -lt $end ]; do
  echo $SECONDS
  netstat -ant | egrep ':.*ESTABLISHED' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c > testcc.txt
  sed 's/^[ t]*//' -i testcc.txt
  sed '/^$/d' -i testcc.txt

  while read c d; do

    if [[ $c > "0" ]]; then
      bGF1dGVuYmFjaGVyLmlv=$(geoiplookup $d | awk -v ip="$d" '{FS=" "} {if($4 == "RU," || $4 == "CN," || $4 == "BLR,") {print 1}}')

      if [[ $bGF1dGVuYmFjaGVyLmlv = "1" ]]; then
        echo "running geolookup"
        echo checking ip $d
        geoiplookup $d

        isCloudflare=0
        # The original script made an exception for CLOUDFLARE. I don't want that exception
        # bGF1dGVuYmFjaGVyLmlX=$(whois $d)
        # if [[ "$bGF1dGVuYmFjaGVyLmlX" == *"CLOUDFLARE "* ]]; then
        #  isCloudflare=1
        #  echo Cloudflare detected
        # fi

        if [[ "$isCloudflare" != 1 ]]; then
          echo try to add ip $d to blocklist
          sudo iptables -I INPUT -s $d -j DROP
          ### I would like to sever the connection here ###
        fi

      fi

    fi
  done < testcc.txt

  sleep 1
    :
done

BTW, I have no idea why the script's author uses such weird variable names ("bGF1dGVuYmFjaGVyLmlv").

Anyways, the problem is whenever it finds a connection with an IP address from a banned country, it runs

sudo iptables -I INPUT -s $d -j DROP

on the ip address. This is all fine, but most of these connections are somewhat persistent, meaning a second later the same ip address is found and is again added using iptables. I'm not sure what happens (does it create duplicate rules?), but I would like to immediately drop the connection after the ipaddress was added with iptables.

So in short: How can I kill a(ll) connection(s) with an IP address?

5
  • 1
    'bGF1dGVuYmFjaGVyLmlX' == base64('lautenbacher.iW') Sep 20 at 12:29
  • Hahaha I figured it was something like that!
    – Zippy1970
    Sep 20 at 12:54
  • Please don't do this. Your machine will grind to a halt when you get to a few thousand iptables rules (should be using ipset) and there are plenty of examples of how to apply geofencing for web traffic in realtime on the internet.
    – symcbean
    Sep 20 at 14:41
  • Thanks for the tip. I will search for such examples. But it's not only web traffic that I want to block. Just yesterday I was unable to login to my server using SSHD because of a brute force attack on sshd. Fail2Ban takes care of such attacks from a single IP address, but this attack came from thousands of IP addresses (all from China).
    – Zippy1970
    Sep 20 at 15:05
  • There's the xtables-addons-dkms iptables match extension geoip. As it also requires to download the list, the script provided for this could be used as a base also for ipset if you don't want to have to get the extension compiled. see manpages.debian.org/bookworm/xtables-addons-common/… (note the path is wrong, dpkg -L would find it)
    – A.B
    Sep 21 at 8:11

1 Answer 1

1

Since several years, the Linux kernel has been having an API to forcibly kill existing IP sockets whatever their state. It can be done with the ss command and its filter syntax:

-K, --kill

Attempts to forcibly close sockets. This option displays sockets that are successfully closed and silently skips sockets that the kernel does not support closing. It supports IPv4 and IPv6 sockets only.

You can replace:

### I would like to sever the connection here ###

with:

ss --kill -n dst = "$d"

The filter (dst = ...) is needed, because the command will kill whatever socket would be displayed. Without filter that would be more than asked. The local process might get an otherwise rare error on its socket such as ECONNABORTED. The remote node will probably be notified with a TCP RST unless an OUTPUT rule is also (temporarily) added to prevent it.

See also this Q/A (where I made an answer): Drop ALL the TCP connections (ESTABLISHED,RELATED) in Ubuntu, where OP attempts to protect from attacks with an ipset (and also has problems with stale connections and stateful firewalling).

3
  • Note: your question appears to include multiple questions in one. I answered what's in the title and in the last sentence. It's not clear if you expected also something else.
    – A.B
    Sep 21 at 9:16
  • Yes, I am going to accept your answer because it answers my original question (and in fact helps me to go forward). I am looking for an alternative solution however, due to the concerns raised in the "Edit" and "Edit 2" paragraphs in my question.
    – Zippy1970
    Sep 21 at 12:39
  • See my first comment and the linked Q/A: geoip or ipset ...
    – A.B
    Sep 21 at 12:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .