Continuing my previous post, about ASN Enrichment (https://threathuntingtails.com/zeek-asn-enrichment/), today I will talk about Geolocation Enrichment or how to insert Geolocation Data in your Zeek logs. This feature will provide you a better understanding of where the monitoring network talks with.

First, we must install the geolocation databases in which Zeek will look up the IPs and bind them with the coordinates.

To do that we will install the MaxMind DBs (the free version, GeoLite2).

dnf install maxminddb

Disclaimer: Zeek must be compiled with GeoIP support (e.g. ./configure --with-geoip=<path>). More detailed instructions can be found in Zeek’s Documentation (https://docs.zeek.org/en/master/frameworks/geoip.html?highlight=geoip#geolocation).

After that for our ease, we will install the geoipupdate tool to update the databases frequently.

wget https://github.com/maxmind/geoipupdate/releases/download/v4.11.1/geoipupdate_4.11.1_linux_amd64.rpm

rpm -i geoipupdate_4_11.1_linux_amd64.rpm

We edit the /etc/GeoIP.conf and we add the AccountID and LicenseKey (we have to signup to Maxmind to use this tool), and we add to “EditionID” the “GeoLite2-ASN” to have ASN look up. Finally, we downloaded the GeoLite2 Databases.

geoipupdate -v

We can create a cron job on the days that MaxMind updates its databases (https://support.maxmind.com/hc/en-us/articles/4408216129947-Download-and-Update-Databases), so we can keep them up to date continuously.

Now we are ready to mess up with Zeek and add the geolocation capability to your logs. We add to our scripts the following file and we load it to our local.zeek configuration.

@load base/utils/site


module Conn;

export {
     # Add GeoData to our organization's private ips
     option org_geolocation_show = F;
     option org_country_code = "GR";
     option org_region = "E";
     option org_city = "Athens";
     option org_latitude = 37.97215199576059;
     option org_longitude = 23.725653947921796;


     #Append new fields to our Conn Record
     redef record Conn::Info += {

         orig_geo: geo_location &log &optional;
         resp_geo: geo_location &log &optional;
         orig_asn: geo_autonomous_system &log &optional;
         resp_asn: geo_autonomous_system &log &optional;

     };

}


event connection_state_remove(c: connection) &priority=0
{

      local orig: addr = c$conn$id$orig_h;
      #if ip is not private
      if ( !Site::is_private_addr(orig)){

            c$conn$orig_geo = lookup_location(orig);
            c$conn$orig_asn = lookup_autonomous_system(orig);
      }
      else {
           if ( org_geolocation_show ){
            c$conn$orig_geo = [$country_code=org_country_code,$region=org_region,$city=org_city,$latitude=org_latitude,$longitude=org_longitude];
		}

      }
      local resp: addr = c$conn$id$resp_h;
      if ( !Site::is_private_addr(resp)){

            c$conn$resp_geo = lookup_location(resp);
            c$conn$resp_asn = lookup_autonomous_system(resp);
      }
      else {
           if ( org_geolocation_show ){
            c$conn$resp_geo = [$country_code= org_country_code ,$region= org_region ,$city= org_city,$latitude= org_latitude ,$longitude= org_longitude ];
	  }

      }

}

As you can see I also added another feature which adds GeoData to our organization’s private IPs to present the on a map. These are the default ones (in the sake of example) but you can change them by redef them inside the local.zeek. Another thing is that by default this feature (enriching the organization’s private ips) is disabled so you have to redef also the “org_geolocation_show” to “T”.

     option org_geolocation_show = F;
     option org_country_code = "GR";
     option org_region = "E";
     option org_city = "Athens";
     option org_latitude = 37.97215199576059;
     option org_longitude = 23.725653947921796;

Now if we look at our conn.log we can see that Geolocation data have been added.