Geo blocking & tracking comes in two flavours.

  • Dynloader 'geo'
  • Module 'GeoTrack'

Dynloader 'geo' ...

As usual a dynloader (dynamic loader) picks up data from external resources and transforms the information into a loadable file to be loaded into an ipset. The creation of the 'match-set' in 'iptables' and the creation of the corresponding 'ipset' is 'on-the-fly' for all dynloaders.

Like all other dynloaders the dynloader 'geo' is located in $MASTER_PATH/dynload/geo with the excutable by the same name below this path; i.e. $MASTER_PATH/dynload/geo/geo

The 'geo' dynloader picks up the excellent data provided by '' updated once every 24 hours (at about 12:30 [PM]).

The update is managed by a crontab entry (as usual for dynloaders) shortly after the update time:

( ... crontab excerpt of user 'root'...)

#============ Watcher =========================================

* * * * *    /usr/local/sbin/MyRouter >/dev/null 2>&1
*/5 * * * *  /usr/local/sbin/Freeme >/dev/null 2>&1

#--- DynLoader : Once per day
00 13 * * * $MASTER_PATH/dynload/geo/Load


'geo' then downloads the configured *.zone' files and transforms these into loadable files for 'ipset' according to the 'geo.conf' file in its working directory.

# - geo.conf -
# Configuration file for dynloader 'geo'
ZONES='cn ru kp by er'

WGET='wget -q --no-check-certificate'


As a result loadfiles for 'ipset' get created and are flushed into the corresponding ipset.

root@vmd28527 Watcher]# ipset -t list | grep -E "geo-"
Name: geo-cn
Name: geo-ru
Name: geo-kp
Name: geo-by
Name: geo-er


With the 'Watcher-Report' tool the filling state can be easily viewed:

[root@vmd28527 Watcher]# Watcher-Report
Watcher-Report ======[ 2023-04-05 20:18:13 ]======

Geo blockings ... (ZONES='cn ru kp by er')
DROPs contributed by ipdeny, geo-cn : 5459
DROPs contributed by ipdeny, geo-ru : 8855
DROPs contributed by ipdeny, geo-by : 94
DROPs contributed by ipdeny, geo-kp : 1
DROPs contributed by ipdeny, geo-er : 1
               Total geo blockings: » 14410


Notice in particular, that the shown  counters are NOT just single IP addresses.
These are CIDRs and thus complete subnets, that get blocked if the '*' files are downloaded.
This will result in millions of blocked IP addresses for a given country.


Module 'GeoTrack' ...

Watcher GeoTrack Struktur

The GeoTrack module is actually a pseudo-module as it does not serve a particular service (login, mail, web,...)

Like all other modules it has its own database and reads its own exclusive FiFo ('named pipe'). But the pipe is fed by other modules from the  'initial' section in the 'inject' routine; i.e. if an attacker is initially recorded to the module's database the attacker's IP address is also passed to the pipe of GeoTrack for further determination and processing.

The reason for this is, that for geolocation determination a very time consuming request to 'whois' databases on the InterNet must be conducted. Doing these 'whois' requests inside the scanner loops of the regular modules would tremendously slow-down the working speed of the regular modules. Instead the IP address and the module name of the origin is simply passed to the GeoTrack (pseudo-)module for processing.

(excerpt from the WatchLG module)


ACTION="Initial $affairs/$MAX_AFFAIRS"

if [ ! -z "$GEOTRACK" ]
then do_geotrack


With the 'GEOTRACK' configuration variable in the modules' configuration file geotracking can be turned 'on' or 'off' in general for a regular module. To turn it 'off' just set GEOTRACK to an empty string in the regular module; i.e. 'GEOTRACK='

In addition a function in the common.bashlib checks, that the GeoTrack pseudo-module was started and thus has established its listening pipe as '$FIFO_BASE/GeoTrack'.

do_geotrack() {
     if [ -p $FIFO_BASE/GeoTrack ]
     then echo $BANDIT $ME >> $FIFO_BASE/GeoTrack


GeoTrack always determines a CIDR from the information on whois-servers and stores this in the ipset 'custody'. If a prefix bitmask could not determined a fake-CIDR will be recorded in the GeoTrack database (geotrack.db) as '<IP_ADDR>/32' which will at least result in a 'point-to-point' blocking between the server and the attacking IP address.

The geotrack database only holds little information.

[root@vmd28527 GeoTrack]# sqlite --table geotrack.db
SQLite version 3.36.0 2021-06-18 18:36:39
Enter ".help" for usage hints.
sqlite> select * from geotrack ;
| route            | ip              | country | origin  | regdate             | provider |
| | | RU      | WatchWB | 2023-04-21 16:29:12 | RIPE     |
|    |   | CN      | WatchMX | 2023-04-22 08:55:06 | APNIC    |
|    |   | CN      | WatchMX | 2023-04-22 09:40:54 | APNIC    |

Note: 'route' is a CIDR (complete sub-net) and the primary key in the table and thus the entry in the table is unique, 'ip' is just the IP address that has triggered the entry in the database.

So a mask length of '/14' (in the example above) will block 2^(32-14) = 2^18 = 262144 IP addresses below the network's base address '' ... not just the one, that has triggered the entry.


How GeoTrack differs from regular modules ...

The pseudo-module GeoTrack works without 'rules'. It just uses the 'ZONES=...' configured in the GeoTrack.conf configuration file; e.g.: ZONES='cn ru'

GeoTrack has an 'ENABLED=...' configuration variable, that must be set to a non-empty value to enable the (pseudo-)module GeoTrack. If GeoTrack is not enabled its listening pipe $FIFO_BASE/GeoTrack won't be established and thus the regular modules won't write to the GeoTrack listening pipe. (see 'do_geotrack' function above)

# - GeoTrack.conf -
# Individual settings for the module
#-------------- Custom section ------------------------

# Set to a non-empty string to enable the GeoTrack (pseudo-)module
# to disable set 'ENABLED='

# The list of zones to be blocked
ZONES="cn ru by kp er"



Scenarios ...

The dynloader 'geo' and/or the (pseudo-)module 'GeoTrack' can be used 'standalone' or in combination (recommened).

If only using the 'geo' dynloader the information can be incomplete as there can be quite a couple of changes in the registration of IP address ranges for a particular country within the 24-hour update cycle. These are then not covered by the *.zone files, that provides. As a result attackers can slip thru the door by frequently changing the IP address (ranges) they are using.

As typical for modules -and thus for the (pseudo-)module 'GeoTrack'- only IP addresses that are really attacking are detected by complains from their corresponding log-information of the service, that the module covers. So GeoTrack has to 'learn' all these IP addresses for the countries to be blocked at first. Without the information from the dynloader 'geo' the GeoTrack database can grow to several thousands of entries in its database.

The best scenario is using both:

  • the dynloader 'geo'
  • the module 'Geotrack'

in combination.

The registration changes, that the 'geo' dynloader does not cover with a 24-hour update cycle can so be catched by the GeoTrack module. The EXPIRATION value for the GeoTrack database can then be set to '1' (for one day), that the database gets cleared from entries, that are older than 24 hours.

Alternatively one may call the 'Expire' routine of GeoTrack as 'Expire 1' from the crontab entry just a minute after the 'geo' dynloader has picked up fresh information from the InterNet.

 (excerpt of the crontab for 'root')

#============ Watcher =========================================

############# Housekeeping ###########################
#------------ Dynloaders------------------------------------------
#--- DynLoader : Once per day
00 13 * * * $MASTER_PATH/dynload/geo/Load
01 13 * * * $MASTER_PATH/modules/GeoTrack/Expire 1 >/dev/null 2>&1



Measuring and statistics ...

Just collecting data makes no sense, it the data isn't used to measure the success from the endeavours.

GeoTrack has a small companion named GeoCount that is implemented as a BASH coprocess and is fired-up by GeoTrack, when the process starts.

GeoCount gets all detected country codes passed from GeoTrack and counts (asyncronously) in the background all accesses from all regular Watcher modules in its own table in the database.

(code snippet from the 'GeoCount' code)




$SQL "update $TABLE
      set count    = count+1,
          lasttime = datetime(current_timestamp,'localtime')
where country='$COUNTRY'


As simple as this is, nice statistics can be drawn and infact this is provided by the Stat component, that all regular modules have - so GeoTrack has a Stat component as well.

[root@vmd28527 GeoTrack]# pwd
[root@vmd28527 GeoTrack]# ls -l Stat*
lrwxrwxrwx 1 root root    7 Apr 30 16:12 Stat -> StatGeo
-rwxr-xr-x 1 root root 1137 Apr 30 11:06 StatGeo
-rw-r--r-- 1 root root  194 Apr 30 11:07 Statistics-Geo_top10.csv
[root@vmd28527 GeoTrack]# 


Calling Stat will generate a CSV file (or a bunch of CSV files) and then sends it/these to the configured $REPORT_MAIL address as an email message with the CSV file(s) in the attachment. From the CSV data  very nice statistics can be created with your favourite Spreadsheet software (EXCEL, LibreOffice CALC, ...) to be shown in meetings or to report the situation to your boss ... for instance.

Sample Stat Geo 

(For more such sample statistics views see the 'Statistics' section in the Watcher 1.3 documentation available  in the Download area under 'Support » Downloads' in the menu)


Conclusion ...

The regular Watcher modules (Watch{LG|MX/MB|WB]) with support from the dynloaders will cut-down the 'attack rate' from milliseconds to several minutes. In some cases I have seen time lags of over an hour between attacks ...

From the experience during testing 'geo blocking' of just the two most aggressive countries (Russia & China) has cut down about 60% of all the remaining attacks, that were not already detected by the regular modules.

The overall amount of attacks dropped by 95% compared to a situation when Watcher is not running.

Dieses System verwendet Cookies, weil das für den Betrieb eines Online-Shops unverzichtbar ist. Ich verstehe, dass Cookies auf meinem Computer Notizen über den Kontakt mit der besuchten WEB-Seite(n) hinterlegen und akzeptiere dies.