koa-ip-geo
Version:
IP and GeoLocation filter middleware for koa, support allow lists and block lists.
385 lines (285 loc) • 12.9 kB
Markdown
# koa-ip-geo
IP and GeoLocation filter middleware for [koa][koa-url], support allow lists and block lists.
[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Git Issues][issues-img]][issues-url]
[![Closed Issues][closed-issues-img]][closed-issues-url]
[![deps status][daviddm-img]][daviddm-url]
[![Code Quality: Javascript][lgtm-badge]][lgtm-badge-url]
[![Total alerts][lgtm-alerts]][lgtm-alerts-url]
[![Caretaker][caretaker-image]][caretaker-url]
[![MIT license][license-img]][license-url]
## News and Changes
### Major (breaking) Changes - Version 2
- This new version 2.x.x is adapted for [Koa2][koajs-url]
- as it uses the **async/await** pattern this new version works only with [node.js][nodejs-url] **v7.6.0** and above.
## Quick Start
### Installation
```bash
$ npm install koa-ip-geo --save
```
You also need the **Maxmind GeoLite2 Free Database** (city or country). We recommend the 'country' version, because it is smaller. [Check their website to get the database][geodb-url].
Alternatively you can now also use **ip2location Databases** (city or country). We recommend the 'country' version, because it is smaller. [Check their website to get the database][ip2location-url].
### Basic Usage
This example has a allow for local IP addresses and a allow for Austrian IP addresses:
```js
const Koa = require('koa');
const ipGeo = require('koa-ip-geo');
const app = new Koa();
// if you are using maxminds geo ip database
app.use(ipGeo({
geoDB: 'path/to/geodb.mmdb',
getDBtype: 'maxmind',
allowIP: '192.168.0.*',
allowCountry: ['AT']
}));
app.use(...);
app.listen(3000);
```
If you waht to use the ip2location database instead, please change the config to:
```js
// using ip2location database
app.use(ipGeo({
geoDB: 'path/to/ip2location.bin',
getDBtype: 'ip2location',
allowIP: '192.168.0.*',
allowCountry: ['AT']
}));
app.use(...);
app.listen(3000);
```
### Advanced Options
##### Allow IP address
Very basic IP filtering:
```js
app.use(ipGeo('192.168.0.*'));
```
Filtering more than one IP address range:
```js
app.use(ipGeo('192.168.0.* 8.8.8.[0-3]'));
```
or
```js
app.use(ipGeo(['192.168.0.*', '8.8.8.[0-3]']));
```
>**Notes:**
> In the previous examples you saw just a single string or an array as a parameter passed to the middleware. For simplicity, in this case this will be interpreted as a 'allowIP'-parameter. Explicitly specifying a 'allowIP'-parameter would be the 'correct' and more readable way:
```js
app.use(ipGeo({
allowIP: ['192.168.0.*', '8.8.8.*']
}));
```
##### Block IP adresses example
```js
app.use(ipGeo({
blockIP: ['8.8.8.*', '1.80.*'],
}));
```
##### Allow countries
In order to determine country origin, we need also to specify the geoDB database:
```js
app.use(ipGeo({
geoDB: 'path/to/geodb.mmdb',
allowCountry: ['US', 'UK', 'DE', 'AT']
}));
```
>**Notes:**
> The geoDB database will only be loaded if necessary. So if you specify a database but do not filter by country or continent, the database will not be loaded.
##### Block countries
```js
app.use(ipGeo({
geoDB: 'path/to/geodb.mmdb',
blockCountry: ['CN', 'RU']
}));
```
##### Allow continents
```js
app.use(ipGeo({
geoDB: 'path/to/geodb.mmdb',
allowContinent: ['NA', 'EU']
}));
```
##### Block continents
```js
app.use(ipGeo({
geoDB: 'path/to/geodb.mmdb',
blockContinent: ['AS']
}));
```
##### Pass Geo-IP data into context ...
If you need Geo-IP data later in your koa context (ctx. ...), just set the 'context' option to true.
```js
app.use(ipGeo({
geoDB: 'path/to/geodb.mmdb',
allowCountry: ['US', 'UK', 'DE', 'AT'],
context: true
}));
// you can and then later access geo-ip data in the context of your request:
...
let city = ctx.geoCity; // city name
let country = ctx.geoCountry; // country name
let continent = ctx.geoContinent; // continent name
let countrycode = ctx.geoCountryCode // country code (ISO_3166-2)
let continentCode = ctx.geoContinentCode; // continent code
let latitude = ctx.geoLatitude; // latitude
let longitude = ctx.geoLongitude; // longitude
...
```
##### More complex example:
```js
app.use(ipGeo({
blockIP: ['8.8.8.*'],
geoDB: 'path/to/geodb.mmdb',
allowCountry: ['UK', 'US', 'FR', 'DE', 'AT'],
forbidden: '403 - Custom Forbidden Message',
development: (process.env.NODE_ENV === 'Development')
}));
```
##### Custom messages
Example with custom forbidden (= rejection) message (function):
```js
forbidden = async function (ctx, next) {
ctx.set('X-Seriously', 'yes');
return 'Seriously - No Access';
}
app.use(ipGeo({
allowIP: '192.168.0.*',
forbidden: forbidden
}))
```
### GeoLite2 Database
> This middleware works with **Maxmind GeoLite2 Free Database** (city or country). We recommend the 'country' version, because it is smaller. [Check their website to get the database][geodb-url].
> Alternatively you now can also use **ip2location Lite Databases** (city or country). We recommend the 'country' version, because it is smaller. [Check their website to get the database][ip2location-url].
>
> `koa-ip-geo` loads the entire database file into memory as a single node `Buffer`. It also uses an in-memory cache when reading complex data structures out of this buffer in the interests of performance. So very roughly speaking, you should assume this module will consume `size_of_mmdb_file * 1.25` of memory.
### Option Reference
| option | Description | Example |
| -------------- | --------------------- | ---------------------- |
| geoDB | path to maxmind or ip2location database | 'GeoLite2-City.mmdb' |
| geoDBtype | 'maxmind' or 'ip2location' - defaults to maxmind | 'maxmind' |
| allowIP | Array of IP addresses (or space separated string) | ['192.168.0.*', '8.8.8.[0-3]'] |
| blockIP | Array of IP addresses (or space separated string) | ['8.8.8.*', '1.80.*'] |
| allowCountry | Array of [ISO 3166-2 country code][iso3166-2-url] (or space separated string) | ['US', 'AT'] |
| blockCountry | Array of [ISO 3166-2 country code][iso3166-2-url] (or space separated string) | ['CN', 'RU'] |
| allowContinent | Array of continent code (or space separated string) | ['EU', 'NA'] |
| blockContinent | Array of continent code (or space separated string) | ['AS', 'OC', 'AF'] |
| forbidden | custom 'forbidden' message (string or function) | '403 - Forbidden' |
| context | set true, if you need geoIP information in the context | defaults to false |
| development | if true, no filztering is done | defaults to false |
### Formats
##### IP Addresses
Possible Formats:
- x.x.x.x for a specific IP address
- x.x.x.* for a IP range
- x.x.*.* for a IP range
- x.x.* for a IP range also works perfectly
- x.x.x.[0-127] this is also a range of IP addresses.
> **Notice:**
> CIDR notation (e.g. `x.x.x.x/18`) is not supported at the moment.
##### Country Codes
Please use the [ISO 3166-2 country code][iso3166-2-url] like 'US', 'UK', ....
##### Continent Codes
- AF - Africa
- AS - Asia
- EU - Europe
- NA - North America
- OC - Oceania
- SA - South America
## Version history
| Version | Date | Comment |
| -------------- | -------------- | -------- |
| 2.3.1 | 2020-10-04 | bugfix ip handling |
| 2.3.0 | 2020-10-04 | now also support for ip2location databases |
| 2.2.0 | 2020-06-17 | interface adaption allow/block (preserving backwards compatibility) |
| 2.1.2 | 2019-02-23 | typescript definitions adapted |
| 2.1.1 | 2019-02-22 | typescript definitions modification |
| 2.1.0 | 2019-02-22 | added typescript definitions |
| 2.0.4 | 2018-11-03 | improved code quality |
| 2.0.3 | 2018-11-03 | dependencies update, updated docs |
| 2.0.2 | 2017-12-23 | removed console.log |
| 2.0.1 | 2017-11-20 | fixed typos README.md |
| 2.0.0 | 2017-11-20 | made for Koa2, version bump, updated dependencies |
| 1.2.1 | 2015-09-25 | udated README, more examples, typos, ... |
| 1.2.0 | 2015-09-23 | now also space separated string possible |
| 1.1.2 | 2015-09-19 | updated DOCs - whiteListIP, examples, typos |
| 1.1.0 | 2015-09-19 | added geoIP data to koa context (as an option) |
| 1.0.0 | 2015-09-18 | initial release |
#### Changes Version 2.0.0
This new version is now for Koa2! So this means, this version is a breaking change! Be sure to also use [node.js][nodejs-url] v7.6.0 or above.
#### Changes Version 1.2.0
- you can now pass arrays as well as space separated strings to each allow/block:
```js
app.use(ipGeo({
blockIP: ['192.168.0.*', '8.8.8.*']
}));
```
is now the same as
```js
app.use(ipGeo({
blockIP: '192.168.0.* 8.8.8.*'
}));
```
- added synonym for `localhost` = IPv4 `127.0.0.1` = IPv6 `::1` - all three will be handled the same way, you only have to provide ONE of those addresses. E.g.:
```js
app.use(ipGeo({
allowIP: 'localhost'
}));
```
will allow `127.0.0.1` and `::1` and vice versa.
## Comments
If you have ideas or comments, please do not hesitate to contact me. Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue][issue-url].
Sincerely,
Sebastian Hildebrandt, [+innovations](http://www.plus-innovations.com)
## Credits
Written by Sebastian Hildebrandt [sebhildebrandt](https://github.com/sebhildebrandt)
This package is heavenly inspired by [koa-ip][koaip-url] and [koa-ip-filter][koaipfilter-url]. Check them out also.
## License [![MIT license][license-img]][license-url]
>The [`MIT`][license-url] License (MIT)
>
>Copyright © 2018-2020 Sebastian Hildebrandt, [+innovations](http://www.plus-innovations.com).
>
>Permission is hereby granted, free of charge, to any person obtaining a copy
>of this software and associated documentation files (the "Software"), to deal
>in the Software without restriction, including without limitation the rights
>to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
>copies of the Software, and to permit persons to whom the Software is
>furnished to do so, subject to the following conditions:
>
>The above copyright notice and this permission notice shall be included in
>all copies or substantial portions of the Software.
>
>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
>AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
>THE SOFTWARE.
[npm-image]: https://img.shields.io/npm/v/koa-ip-geo.svg?style=flat-square
[npm-url]: https://npmjs.org/package/koa-ip-geo
[downloads-image]: https://img.shields.io/npm/dm/koa-ip-geo.svg?style=flat-square
[downloads-url]: https://npmjs.org/package/koa-ip-geo
[license-url]: https://github.com/sebhildebrandt/koa-ip-geo/blob/master/LICENSE
[license-img]: https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square
[npmjs-license]: https://img.shields.io/npm/l/koa-ip-geo.svg?style=flat-square
[issue-url]: https://github.com/sebhildebrandt/koa-ip-geo/issues/new
[koa-url]: https://github.com/koajs/koa
[iso3166-2-url]: https://en.wikipedia.org/wiki/ISO_3166-2
[geodb-url]: https://dev.maxmind.com/geoip/geoip2/geolite2/
[ip2location-url]: https://lite.ip2location.com/database/ip-country/
[koaip-url]: https://github.com/MangroveTech/koa-ip
[koaipfilter-url]: https://github.com/tunnckoCore/koa-ip-filter
[daviddm-url]: https://david-dm.org/sebhildebrandt/koa-ip-geo
[daviddm-img]: https://img.shields.io/david/sebhildebrandt/koa-ip-geo.svg?style=flat-square
[issues-img]: https://img.shields.io/github/issues/sebhildebrandt/koa-ip-geo.svg?style=flat-square
[issues-url]: https://github.com/sebhildebrandt/koa-ip-geo/issues
[closed-issues-img]: https://img.shields.io/github/issues-closed-raw/sebhildebrandt/koa-ip-geo.svg?style=flat-square
[closed-issues-url]: https://github.com/sebhildebrandt/koa-ip-geo/issues?q=is%3Aissue+is%3Aclosed
[nodejs-url]: https://nodejs.org/en/
[koajs-url]: http://koajs.com/
[lgtm-badge]: https://img.shields.io/lgtm/grade/javascript/g/sebhildebrandt/koa-ip-geo.svg?style=flat-square
[lgtm-badge-url]: https://lgtm.com/projects/g/sebhildebrandt/koa-ip-geo/context:javascript
[lgtm-alerts]: https://img.shields.io/lgtm/alerts/g/sebhildebrandt/koa-ip-geo.svg?style=flat-square
[lgtm-alerts-url]: https://lgtm.com/projects/g/sebhildebrandt/koa-ip-geo/alerts
[caretaker-url]: https://github.com/sebhildebrandt
[caretaker-image]: https://img.shields.io/badge/caretaker-sebhildebrandt-blue.svg?style=flat-square