-
-
Save bmatthewshea/a214d710382b36612f6a06ee8ab5d3bf to your computer and use it in GitHub Desktop.
#!/bin/bash | |
# | |
# By: Brady Shea - 10FEB2020 - Last update 04DEC2023 | |
# | |
# Usage (ip4 only): | |
# geoip2lookup IP_ADDRESS | |
# | |
# ** Install GeoIP Tool and Updater ** | |
# | |
# sudo add-apt-repository ppa:maxmind/ppa | |
# sudo apt install libmaxminddb0 libmaxminddb-dev mmdb-bin geoipupdate | |
# | |
# * Review: https://dev.maxmind.com/geoip/geoip2/geolite2/ and | |
# sign up for a free license. | |
# * Edit your "/etc/GeoIP.conf": | |
# * Make sure you have the proper downloads location set: | |
# "EditionIDs GeoLite2-Country GeoLite2-City GeoLite2-ASN" | |
# * Make sure you have added the 'AccountID' and 'LicenseKey' | |
# | |
# Then finally execute: | |
# | |
# sudo geoipupdate | |
# | |
# Make sure you see new files in "/usr/share/GeoIP" or "/var/lib/GeoIP". | |
# If not, check the 'DatabaseDirectory' directive in your config/.conf above. | |
# A cron job will also be created to periodocally run the updater. | |
# | |
# Notes: | |
# * The valid_ip() function is taken from: | |
# https://www.linuxjournal.com/content/validating-ip-address-bash-script | |
# * Updated Legacy files can be found here: https://www.miyuru.lk/geoiplegacy | |
# - this script uses mmdb (only), though. | |
# * The country file is not currently used in this script. It can be removed | |
# from your downloads in the .conf file above if needed. | |
# | |
# Defaults | |
geo_file_prefix="/usr/share/GeoIP" | |
test_file1="GeoLite2-City.mmdb" | |
test_file2="GeoLite2-ASN.mmdb" | |
##################################################################### | |
# Functions | |
##################################################################### | |
function process_quoted () { | |
# Process all given tokens with spaces as one func argument= $* | |
grab_quoted=`sed -E 's/.*"(.*)".*/\1/' <<< "$*"` | |
} | |
function process_unquoted () { | |
grab_first_word=${1% *} | |
} | |
function valid_ip() | |
{ | |
local ip=$1 | |
local stat=1 | |
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then | |
OIFS=$IFS | |
IFS='.' | |
ip=($ip) | |
IFS=$OIFS | |
[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]] | |
stat=$? | |
fi | |
return $stat | |
} | |
##################################################################### | |
# Validate | |
##################################################################### | |
# No argument given? | |
if [ -z "$1" ]; then | |
printf "\nUsage:\n\n geoip2lookup IP4_ADDRESS\n\n" | |
exit 1 | |
fi | |
# Check ip validity. | |
if ! valid_ip "$1"; then | |
printf "\nThis is not a valid IP address. Exiting.\n\n" | |
exit 1 | |
fi | |
# Check for GeoIP file location: | |
# Ubuntu 20 = /usr/share/ || Ubuntu 22 = /var/lib/ | |
if [[ -f "/var/lib/GeoIP/${test_file1}" ]]; then | |
geo_file_prefix="/var/lib/GeoIP" | |
fi | |
# Make sure both geoip files exist at given location: | |
if ! [[ -f "${geo_file_prefix}/${test_file1}" || -f "${geo_file_prefix}/${test_file2}" ]]; then | |
printf "\nOne or more GeoIP file(s) are missing. Looking in: \"${geo_file_prefix}/\". Exiting.\n" | |
exit 1 | |
fi | |
##################################################################### | |
# Execute | |
##################################################################### | |
printf "\nLooking up IP in the installed GeoIP database..\n" | |
#file_country="/usr/share/GeoIP/GeoLite2-Country.mmdb" | |
file_city="${geo_file_prefix}/${test_file1}" | |
file_asn="${geo_file_prefix}/${test_file2}" | |
city_string=`mmdblookup --file ${file_city} --ip "$1" city names en 2>/dev/null` | |
subdivision_string=`mmdblookup --file ${file_city} --ip "$1" subdivisions 0 names en 2>/dev/null` | |
country_string=`mmdblookup --file ${file_city} --ip "$1" country names en 2>/dev/null` | |
continent_string=`mmdblookup --file ${file_city} --ip "$1" continent names en 2>/dev/null` | |
location_lat_string=`mmdblookup --file ${file_city} --ip "$1" location latitude 2>/dev/null` | |
location_lon_string=`mmdblookup --file ${file_city} --ip "$1" location longitude 2>/dev/null` | |
location_metrocode_string=`mmdblookup --file ${file_city} --ip "$1" location metro_code 2>/dev/null` | |
location_timezone_string=`mmdblookup --file ${file_city} --ip "$1" location time_zone 2>/dev/null` | |
postal_string=`mmdblookup --file ${file_city} --ip "$1" postal code 2>/dev/null` | |
asn_number_string=`mmdblookup --file ${file_asn} --ip "$1" autonomous_system_number 2>/dev/null` | |
asn_name_string=`mmdblookup --file ${file_asn} --ip "$1" autonomous_system_organization 2>/dev/null` | |
process_quoted $city_string && city=${grab_quoted} | |
process_quoted $subdivision_string && subdivisions=${grab_quoted} | |
process_quoted $country_string && country=${grab_quoted} | |
process_quoted $continent_string && continent=${grab_quoted} | |
process_unquoted $location_lat_string && location_lat=${grab_first_word} | |
process_unquoted $location_lon_string && location_lon=${grab_first_word} | |
process_unquoted $location_metrocode_string && location_code=${grab_first_word} | |
process_quoted $location_timezone_string && location_tz=${grab_quoted} | |
process_quoted $postal_string && postal=${grab_quoted} | |
process_unquoted $asn_number_string && asn_number=${grab_first_word} | |
process_quoted $asn_name_string && asn_name=${grab_quoted} | |
printf " | |
City: ${city} | |
Territory: ${subdivisions} | |
Country: ${country} | |
Continent: ${continent} | |
Location (approx): ${location_lat},${location_lon} | |
Metro Code: ${location_code} | |
Timezone: ${location_tz} | |
Postal Code: ${postal} | |
ASN Number: ${asn_number} | |
ASN Organization: ${asn_name} | |
\n" |
#!/usr/bin/python3 | |
# mostly from https://github.com/maxmind/GeoIP2-python | |
import sys | |
import geoip2.database | |
# ^ (pip3 install geoip2) | |
ip = sys.argv[1] | |
print(ip + ":\n") | |
reader = geoip2.database.Reader('/usr/share/GeoIP/GeoLite2-City.mmdb') | |
response = reader.city(ip) | |
# Use these as needed | |
city = response.city.name | |
state = response.subdivisions.most_specific.name | |
country = response.country.name | |
postal = response.postal.code | |
llat = response.location.latitude | |
llon = response.location.longitude | |
netsize = response.traits.network | |
iso = response.country.iso_code | |
# example lookups created: | |
city_lookup = [city, state, country, postal] | |
location_lookup = [str(llat), str(llon)] | |
try: # "city_lookup" | |
print("\n".join(city_lookup)) | |
except TypeError: | |
print ("(no city info found)") | |
except: | |
print ("Unknown Error on city lookup.") | |
try: # "location_lookup" | |
print("Coordinate Location:", ",".join(location_lookup)) | |
except TypeError: | |
print ("No location data found.") | |
except: | |
print ("Unknown Error.") |
@vadirajks
Ahh yes & thanks. Yeah I see output is different. I just wasn't looking very closely. haha
The full thread below explained mmdblookup
was just a developmental tool and never intended to output parsable json. Dumb reason IMO.
And this specific comment also explains why they made mmdbinspect
(Also begs the question: Why not just re-write mmdblookup
a bit?? Couldn't they have simply given it a new flag/parameter to produce proper json output (--json perhaps? Guess not.)). :-(
Anyway see here-
maxmind/libmaxminddb#135 (comment)
updater puts database in /var/lib/GeoIP/ on 22.04 when not using ppa:maxmind/ppa
@kotenok2000
Thanks for the input. I have put a file check in BASH version and updated it here. I haven't had time to update python script, yet (or ever..lol).
If you are able to test bash version on a system that uses /var/lib/
, let me know if it works. Only re-tested on a 20 box. Still works there. And you should be using the maxmind ppa if you use this script as noted in script setup comments. If location changes when using ppa in future, let me know! It should run a check either way now, though, at least for /var/lib/GeoIP..
sorry, for reference https://github.com/maxmind/mmdbinspect and by using "mmdbinspect", it is easily to parse json without any problem(like jq command as mentioned in my link....etc) but that is not the case with mmdblookup(JSON-ish format).
yes, you are correct both provide same result.
/usr/bin/mmdblookup -f /usr/share/GeoIP/GeoLite2-City.mmdb -i 32.32.32.32 | jq . (don't work)
/usr/bin/mmdbinspect -f /usr/share/GeoIP/GeoLite2-City.mmdb -i 32.32.32.32| jq . (works)