Maxmind licenses should be properly considered in commercial and non-free use cases / environments.
❗ 📝 This project uses Legacy Maxmind GeoIP .db databases that are now considered deprecated and no longer supported by Maxmind who only release v2 .mmdb files. 📝 ❗ |
---|
👏 ⭐ Thanks to @terrablue for helping me port this code that had been broken for 3 years since node changes then - his a 👑 javascript legend 👏 ⭐ |
💘 👍 ✌️ 💾 DB files are provided curtesy of mailfud.org - MAXIMUM ONE DOWNLOAD AN IP PER HOUR. 💾 ✌️ 👍 💘 |
🚧 if the linked mailfud.org mirror is down you can create your own DB using the script: GeoLite2xtables and the source CSV files from your account in Maxmind dashboard. Anther source is: miyuru.lk/geoiplegacy. 🚧 |
✔️ Versions tested: Node.js v16.16.0 & NPM 8.11.0 (August 2022) on 🐧 Linux 🍎 macOS & 🔰 Windows ✔️ |
vipi
is a Node.js
utility using legacy Maxmind
GeoIP DB as well legacy (v0.6.0) npm maxmind
to provide known info of each IP
:
- Location (Country, City, etc)
- Time Zone
- ASN
vipi
is a standalone command-line-interface (CLI) utility and it may also act as a HTTP server / web daemon.
The intent with this utility is to provide dual log stores that are in Comman-Log-Format (CLF) and JSON contextual to application and user requirements. Session specific information can be stored and read to an automatically named file and or any other specified file.
Available functionality and features - by way of CLI arguments / parameters or query-strings (get-parameters) in daemon mode are documented herein.
Using as a npm
an OS
with Node.js
already installed.
npm install -g vipi # global install or with `sudo` for CLI use.
npm install vipi # for use in project or locally
Once installed vipi
can be used as a standalone command or further extended as module in your Node.js
script / project.
Once installed you may run in shell
vipi # // brief help & options
man vipi # // for manual if install globally
man vipi.1.gz # // manual file in repository / package root.
Example lookup uses:
vipi 5.5.5.5 | jq '.' # single IP lookup & `jq` pretty JSON response.
[
{
"ip": "5.5.5.5",
"date": "2022-08-04T18:01:19.593Z",
"location": {
"countryCode": "DE",
"countryName": "Germany",
"region": "00",
"city": null,
"postalCode": null,
"latitude": 51.29929999999999,
"longitude": 9.49090000000001,
"dmaCode": 0,
"areaCode": 0,
"metroCode": 0,
"continentCode": "EU",
"regionName": null
},
"asn": "AS6805TelefonicaGermany",
"timeZone": "Europe/Berlin"
}
]
vipi 208.67.222.222 208.67.220.220 # multi IP lookups
vipi 8.8.8.8 8.8.4.4 -cd # include distance between pairs
Custom & automatic saving of JSON Object & String CLF key(s) for queried IP:
vipi 208.67.222.222 -sa -skc='200 "GET / HTTP/1.1"'
# Key string to save for IP entry in Auto-Save CLF logs
vipi 208.67.222.222 -sa -sko='{"x":9}'
# Key JSON Object string for IP entry in Auto-Save OBJ logs
vipi 208.67.222.222 -sf=S3141_user -skc='200 "GET / HTTP/1.1" -sko='{"x":9}'
# log OBJ & CLF to specified file 'S3141_user' session file(s)
Logs are saved to the specified absolute or relative path from where execution occurred (pwd
/ cwd
).
To execute vipi
in web / daemon either -d
, --daemon
or -dp
, --dipport
options are required such as:
vipi -d # // default mode
vipi -dp=127.0.0.1:65534 # // custom IP:PORT binding
Default daemon options allow for read, write and return to be freely available; post launch - visiting the address of the instance in a browser without any option ( or with !_help
||
!_h
parameter) should yield a brief of usage and available parameters. Eg:
curl 127.0.0.1:59999 # will output:
|\-------------------------/|
| ==== Visitor IP Info ==== |
|/_________________________\|
vipi - v0.0.4
Usage (?!_=...):
http://127.0.0.1:59999/?!_=ua # use the inquiring address instead of ip.
http://127.0.0.1:59999/?!_=208.67.222.222 # query & get results in text/plain
(&) Query String / Get-Parameters:
!_as, !_asnumber Includes ASN number of IP queried.
!_cd, !_cdistance Calculate & Include approximate distances in Kilometres between IPs pairs.
!_df=, !_deletefile= Delete obj & clf named file(s).
!_da, !_deleteall Deletes all clf & obj file(s) resetting to new.
!_h, !_help Shows this help page.
!_js, !_json Return content-type: 'application/json' instead of 'text/plain'.
!_ls, !_listsaves Lists all available user obj json files.
!_nu, !_noua Include requesting users agent in save.
!_nr, !_noreturn No output or return.
!_nc, !_noclf Include requesting users agent in save.
!_ra, !_readauto Return content-type: 'application/json'
!_rf=, !_readfile= Contents of log file to read & return.
!_sua, !_saveua Include requesting users agent in save.
!_tp, !_textplain Return content-type: 'text/plain'.
!_sa, !_saveauto Save to file named using date: 'IP [DATE] KEY' (KEY optional) in .clf & .json file.
!_sf=, !_savefile= Save like -sa: using specified file prefix name for .clf & .json saves.
!_skc=, !_skclf= Save KEY clf string URL-Encoded string eg: '200 "GET / HTTP/1.1"' to save.
!_sko=, !_skobj= Save KEY object json string URL-Encoded eg '{"eg":1}' to save.
!_tz, !_timezone Includes time-zone of IP location queried.
!_xi, !_xinfo Show OS / Node.js / Maxmind DB related info & exit.
Requests made to the server are by way of Query-String(s) / Get-Parameter(s) which are prefixed with !_
. When in default non-referral mode - the !_=
parameter is used to pass the IP
being queried.
curl '127.0.0.1:59999/?!_=208.67.222.222' # will output:
[{"ip":"208.67.222.222","date":"2016-02-04T11:40:01.984Z","location":{"countryCode":"US","countryName":"United States","region":"CA","city":"San Francisco","postalCode":"94107","latitude":37.7697,"longitude":-122.39330000000001,"dmaCode":807,"areaCode":415,"metroCode":807,"continentCode":"NA","regionName":"California"},"ua":"curl/7.38.0","timeZone":"America/Los_Angeles","asn":"AS36692 OpenDNS, LLC"}]
Multiple IP
's may also be passed in sequence using multiple !_=
values or using a single comma (,
) separated value such as:
curl '127.0.0.1:59999/?!_=208.67.222.222,8.8.8.8' # two (2x) IPs comma separated
curl '127.0.0.1:59999/?!_=208.67.222.222&!_=8.8.8.8' # serialised.
In daemon mode GeoIP DB files are written at the path of execution in the directory: vipi_dbs
.
A JSON Object key and CLF string key can be as passed as Percent-Encoded (URL-Encoded) strings which can be saved with each lookup ip
where save features have been enabled. For example doing:
curl '127.0.0.1:59999/?!_=208.67.222.222&!_skc=200%20%22GET%20%2F%20HTTP%2F1.1%22'
# OBJ Key = '{"x":9}' - Object saved for this entry in JSON logs
curl '127.0.0.1:59999/?!_=208.67.222.222&!_sko=%7B%22x%22%3A9%7D'
# CLF Key = '200 "GET / HTTP/1.1"' - String saved for this entry in CLF logs
curl '127.0.0.1:59999/?!_=208.67.222.222&!_sko=%7B%22x%22%3A9%7D&!_skc=200%20%22GET%20%2F%20HTTP%2F1.1%22'
# Save both CLF & OBJ keys.
Semi or fully silent daemon mode(s) are possible with the -dn...
& -dx...
set of parameters where they be act as collectors; a use case may be:.
vipi -d -dno -dnr -dnw -dur -dxa -dsa # // only collects auto saving & ignoring all !_ parameters.
Using vipi
as an npm
module is also possible though the original npm maxmind
is recommended instead.
This module ships with the following available methods / functions:
function | parameters & description |
---|---|
.lookup(IPs, true, false) |
(1st) String or Array of IP , (2nd) distance calculation of pairs, (3rd) benchmark mode. |
.enableupdates(Hours) |
Enables automatic update checks every 24 Hours where no value is passed |
Simple example:
var mVIPI = require("vipi");
var aReturn = mVIPI.lookup(["208.67.222.222","208.67.220.220"]);
mVIPI.enableupdates();
console.log("IP Details:\n", aReturn);
Any error(s) incurred in the lookup process result in a String
return containing ERROR:
in CLI / Daemon modes or an array containing the same value when used as an array.
Other queried requests which do not result in an error are not returned; this should NOT prevent or stop the logging of successful IP
's in damon modes.
A performance of ~
100,000
to 300,000
lookups per second can be expected in non-daemon / http modes with most modern (2015) X86 / AMD64
computers subject to available resources including the node.js
version, hardware specification such as DDR
as well as other architectural consideration.
Daemon / http mode - are limited by the asynchronous and single process nature of Node.js
; thus any concurrency beyond 100,000
is unlikely and not recommended; for greater concurrent volumes of lookups consider load-balancing / running multiple version of the service.
The author of GoAccess
(@allinurl) - had appropriately asked whether the acclaimed numbers herein have been tested; an example benchmark case has subsequently been included in vipi_benchmark.js
.
The included benchmark performs a linear ordered lookup of over 100,000
IP which goes to demonstrate the expected number of looks that may be expected from the host computer on which vipi
is executed.
Two example AMD64 architectures which were over a decade apart in age (2015 & older) are shown below:
cat /proc/cpuinfo && sudo dmidecode --type 17 # or 'hwinfo'
# CPU - Model: Intel(R) Xeon(TM) CPU 3.60GHz
# Clock: 3591 MHz
# L1 Cache: 16 kb
# L2 Cache: 1024 kb
# MEMORY - Type: DDR2 - ECC RAM - Speed: 400 MHz
# -------
vipi_benchmark ;
# Doing lookups of: 100000 IPs ...
# Completed approximatly: 300000 operations (location, timezone & asn lookups)
# IP READ Time in Seconds: 0.16299986839294434
# LOOKUP Time in Seconds: 6.851000070571899
# TOTAL execution Time: 7.014999866485596
# EXPECTED lookups a sec: 14596.40913295923
cat /proc/cpuinfo && sudo dmidecode --type 17 ; # or 'hwinfo'
# CPU - Model: Intel(R) Core(TM) i7-5820K CPU @ 3.30GHz
# Clock: 2400 MHz
# L1 Cache: 64 kb
# L2 Cache: 256 kb
# L3 Cache: 2560 kb
# MEMORY - Type: DDR4 - NON-ECC RAM - Speed: 2400 MHz
# -------
vipi_benchmark ;
# Doing lookups of: 100000 IPs ...
# Completed approximately: 300000 operations (location, timezone & asn lookups)
# IP READ Time in Seconds: 0.06599998474121094
# LOOKUP Time in Seconds: 1.502000093460083
# TOTAL execution Time: 1.569000005722046
# EXPECTED lookups a sec: 66577.89199575545
cat /proc/cpuinfo && sudo dmidecode --type 17 ; # or 'hwinfo'
# CPU - Model: 700 MHz single-core ARM1176JZF-S
# Clock: 600 MHz
# L1 Cache: 16 kb
# L2 Cache: 128 kb
# MEMORY - Type: SDRAM - Speed: 400 MHz
# -------
vipi_benchmark ;
# Doing lookups of: 100000 IPs ...
# Completed approximately: 300000 operations (location, timezone & asn lookups)
# IP READ Time in Seconds: 3.819999933242798
# LOOKUP Time in Seconds: 510.35199999809265
# TOTAL execution Time: 514.1749999523163
# EXPECTED lookups a sec: 195.94319215046426
The daemon / http mode can be tested using ab
tool. For example to perform 10,000
concurrent requests:
ulimit -a ; # check user limits
ulimit -n 1000000 ; # set as high
ab -n 10000 -c 10000 'http://127.0.0.1:59999/?!_=208.67.222.222&!_nr' ;
# ...
# Concurrency Level: 10000
# Time taken for tests: 2.651 seconds
# Complete requests: 10000
# Failed requests: 0
# Total transferred: 1590000 bytes
# HTML transferred: 50000 bytes
# Requests per second: 3772.14 [#/sec] (mean)
# Time per request: 2651.013 [ms] (mean)
# Time per request: 0.265 [ms] (mean, across all concurrent requests)
# Transfer rate: 585.71 [Kbytes/sec] received
# Connection Times (ms)
# min mean[+/-sd] median max
# Connect: 0 277 400.0 87 1004
# Processing: 13 243 269.8 128 1617
# Waiting: 13 243 269.8 128 1617
# Total: 15 521 430.2 505 2617
# ...
This type of testing is limited by the servomechanism of loopback
(127.0.0.1
); use of (non-loopback) adaptors may yield greater performances.
This product includes GeoLite2 data created by MaxMind, available from Maxmind
.
0.0.4
GPLv3