No geoip points in kibana map

Hello everyone and welcome to another rooky question :smiley:

In a very simple logstash pipeline, I want to enter via stdin an ipv4 address and ship it to elasticsearch...than get the geoip location drawn on a map.

However...I get no results (and no error).
Yes I read a lot..but I had no luck to solve it on my own.

What I did:
In Elasticsearch, I created an index:

PUT testme
{
    "mappings": {
      "properties": {
        "@timestamp": {
          "type": "date"
        },
        "source": {
          "type": "ip"
        },
        "geoip": {
          "properties": {
            "location": {
              "type": "geo_point"
            }
          }
        }
      }
    }
  }
}  

Once created, I also checked the mapping:

{
  "testme": {
    "mappings": {
      "properties": {
        "@timestamp": {
          "type": "date"
        },
        "@version": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "client": {
          "properties": {
            "geo": {
              "properties": {
                "city_name": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "continent_code": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "country_iso_code": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "country_name": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "location": {
                  "properties": {
                    "lat": {
                      "type": "float"
                    },
                    "lon": {
                      "type": "float"
                    }
                  }
                },
                "postal_code": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "region_iso_code": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "region_name": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                },
                "timezone": {
                  "type": "text",
                  "fields": {
                    "keyword": {
                      "type": "keyword",
                      "ignore_above": 256
                    }
                  }
                }
              }
            },
            "ip": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "mmdb": {
              "properties": {
                "dma_code": {
                  "type": "long"
                }
              }
            }
          }
        },
        "event": {
          "properties": {
            "original": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            }
          }
        },
        "geoip": {
          "properties": {
            "location": {
              "type": "geo_point"
            }
          }
        },
        "host": {
          "properties": {
            "hostname": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            }
          }
        },
        "message": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "source": {
          "type": "ip"
        }
      }
    }
  }
}

I also created a data-view in kibana.

Here is my logstash config:

input {
    stdin { }
}

filter {

    grok {
        match => { "message" => "%{IP:source}" }
    }

    geoip {
        source => "source"
        target => "client"
    }

}

output {
        elasticsearch {
            hosts => "localhost:9200"
            manage_template => false
            index => "testme"
        }

        stdout {
            codec => rubydebug { }
        }
}

Starting logstash and entering an IP gives me this:

11.11.11.11
{
        "client" => {
          "ip" => "11.11.11.11",
         "geo" => {
                   "city_name" => "Bullard",
                "country_name" => "United States",
            "country_iso_code" => "US",
                 "postal_code" => "75757",
                    "location" => {
                "lon" => -95.3381,
                "lat" => 32.1118
            },
             "region_iso_code" => "US-TX",
              "continent_code" => "NA",
                 "region_name" => "Texas",
                    "timezone" => "America/Chicago"
        },
        "mmdb" => {
            "dma_code" => 709
        }
    },
    "@timestamp" => 2022-09-11T16:23:49.714266Z,
      "@version" => "1",
          "host" => {
        "hostname" => "rocky-8-1"
    },
        "source" => "11.11.11.11",
       "message" => "11.11.11.11",
         "event" => {
        "original" => "11.11.11.11"
    }
}

Looks good to me....
Elasticsearch shows this content:

{
  "took": 0,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 3,
      "relation": "eq"
    },
    "max_score": 1,
    "hits": [
      {
        "_index": "testme",
        "_id": "oNNdLYMBPd5sI551QSM_",
        "_score": 1,
        "_source": {
          "client": {
            "ip": "11.11.11.11",
            "geo": {
              "city_name": "Bullard",
              "country_name": "United States",
              "country_iso_code": "US",
              "postal_code": "75757",
              "location": {
                "lon": -95.3381,
                "lat": 32.1118
              },
              "region_iso_code": "US-TX",
              "continent_code": "NA",
              "region_name": "Texas",
              "timezone": "America/Chicago"
            },
            "mmdb": {
              "dma_code": 709
            }
          },
          "@timestamp": "2022-09-11T16:23:49.714266Z",
          "@version": "1",
          "host": {
            "hostname": "rocky-8-1"
          },
          "source": "11.11.11.11",
          "message": "11.11.11.11",
          "event": {
            "original": "11.11.11.11"
          }
        }
      },
      {
        "_index": "testme",
        "_id": "ntNaLYMBPd5sI551KiPj",
        "_score": 1,
        "_source": {
          "client": {
            "geo": {
              "timezone": "Europe/Berlin",
              "location": {
                "lon": 9.491,
                "lat": 51.2993
              },
              "continent_code": "EU",
              "country_name": "Germany",
              "country_iso_code": "DE"
            },
            "ip": "5.4.3.2"
          },
          "@timestamp": "2022-09-11T16:20:27.205240Z",
          "@version": "1",
          "host": {
            "hostname": "rocky-8-1"
          },
          "source": "5.4.3.2",
          "message": "5.4.3.2",
          "event": {
            "original": "5.4.3.2"
          }
        }
      },
      {
        "_index": "testme",
        "_id": "n9NaLYMBPd5sI551ayN8",
        "_score": 1,
        "_source": {
          "client": {
            "geo": {
              "timezone": "America/Chicago",
              "location": {
                "lon": -97.822,
                "lat": 37.751
              },
              "continent_code": "NA",
              "country_name": "United States",
              "country_iso_code": "US"
            },
            "ip": "4.3.2.1"
          },
          "@timestamp": "2022-09-11T16:20:43.906904Z",
          "@version": "1",
          "host": {
            "hostname": "rocky-8-1"
          },
          "source": "4.3.2.1",
          "message": "4.3.2.1",
          "event": {
            "original": "4.3.2.1"
          }
        }
      }
    ]
  }
}

In Kibana, I see the geo.location field...MAPS shows me the countries based on the 2 field code if I want...but only the geo.location delivers nothing ...(time range is set correctly).

So after 1.5 days of testing and reading...I need help. 1000x Kudos to the chosen one who helps me out.

Hi @SirStephanikus As Usual You are close .... but just a bit off look carefully at the data and mappings

You mapping and data do not align...

In your data... the actual location field is

client.geo.location

       "_source": {
          "client": {
            "geo": {
              "timezone": "America/Chicago",
              "location": {
                "lon": -97.822,
                "lat": 37.751
              },

and your mapping shows this which is NOT a geo_point And the mapping shows that is...

                "location": {
                  "properties": {
                    "lat": {
                      "type": "float"
                    },
                    "lon": {
                      "type": "float"
                    }
                  }
                },

That needs to be

The mapping you have at the very top... does not match to any actually data fields because it is not under client.geo

            "location": {
              "type": "geo_point"
            }
          }

so it needs to be something like this.... you need to define this ahead of time...
Plus you should get rid of the keyword / text multifield and just use keyword for most those fields..
Note I did not do this in an editor so tte {s may not match up... but it shows the correct idea

...
        "client": {
          "properties": {
            "geo": {
              "properties": {
                "city_name": {
                  "type": "keyword"
                  }
                },
                "continent_code": {
                  "type": "keyword"
                  }
                },
                "country_iso_code": {
                  "type": "keyword"
                  }
                },
                "country_name": {
                  "type": "keyword"
                  }
                },
                "location": {
                    "type": "geo_point"
                  }
                },
....
2 Likes

:bulb: :bulb: :bulb:
I haven't seen the wood because of all the trees (in german, it sound waaayy better).

Oh my god...so simple, just a wrong indexing/mapping of geo...reminds me of a messed up C exam at college.

:partying_face: I feel like a teen right now (I'm old !), thank you so much Stephen...you took your time to explain something to a stranger on a sunday. I really really appreciate that.

2 Likes

You are doing just fine!

Did you get the points on the map?

The next things people trip over with the geoip Is they send internal IP addresses which will not turn into a geo and wonder why they don't show up?.

I totally get it...

Yep...everything and my Fail2Ban filebeat -> Logstash -> EL <- Kibana config works too (GROK and custom pattern were easy to me). I labbed this yesterday and the geoip location gave me headache.

FYI:
Tomorrow I will have a call with one of the ELK people...I'm highly interested in the private training opportunity. Live courses are unfortunately sold out.

The next things people trip over with the geoip Is they send internal IP addresses which will not turn into a geo and wonder why they don't show up?.

Well...how should you translate PRIVATE addresses ? I mean...there is a reason why it is called PRIVATE. Perhaps one can translate the global outside ip of the edge devices IP...which than is an alias everything behind it. I.E.
internal datacenter VMs are depicted on a map by their external gateway...but never by their internal private address like 172.16.x.x that is just not possible.

What I did for a customer (another monitoring system) was to get the GPS data of all their branches (5k+), displayed it on open-street-map and on this map they got their branch devices linked...but this particular task is not related to ELK, and was more a workaround mapping trick.

1 Like

You can have an index with the private addresses geolocated and use the enrich processor to transfer those locations to your ingested events. This is described in this blog post

1 Like

@jsanz Yes thanks I did not realize we had a blog... I wish enrich worked on IP ranges :slight_smile: not only exact matches... I will bring that up again!

1 Like

Since you are using Logstash, this is pretty easy to do with the translate filter.

I had a similar use case in the past where I needed to enrich the information from something around 1800 network devices distributed around the country and used a couple of dictionary files and the translate filter.

For example, I had a dictionary file with the name of the devices and the geolocation, something like this:

"device-0001": [ lon, lat]
"device-0002": [ lon, lat]
"device-0003": [ lon, lat]
"device-NNNN": [ lon, lat]

Then a translate filter

translate {
	source => "deviceName"
	target => "[geo][location]"
	dictionary_path => "/path/to/file/locations.yml"
	refresh_interval => 300
}

You could use a similar approach to enrich the data of your private addresses, it just depends on how you can filter for each location.

1 Like

So the exact way as described in my post and successfully performed for more than 5k+ branches.

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.