-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathgeoip.js
More file actions
109 lines (87 loc) · 2.63 KB
/
Copy pathgeoip.js
File metadata and controls
109 lines (87 loc) · 2.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/**
* GeoIP lookup functionality using MaxMind GeoLite2 database
*/
const fs = require('fs');
const path = require('path');
const maxmind = require('maxmind');
const logger = require('./logger');
class GeoIPLookup {
constructor() {
this.reader = null;
this.dbPath = path.join(__dirname, 'data', 'GeoLite2-Country.mmdb');
this.isEnabled = false;
}
async initialize() {
try {
if (!fs.existsSync(this.dbPath)) {
logger.warn('GeoIP database not found. Country blocking disabled.');
logger.warn('Run "npm run setup-geoip" to download the database.');
this.isEnabled = false;
return false;
}
this.reader = await maxmind.open(this.dbPath);
this.isEnabled = true;
logger.info('GeoIP database loaded successfully');
return true;
} catch (err) {
logger.error('Failed to load GeoIP database:', err.message);
this.isEnabled = false;
return false;
}
}
lookup(ipAddress) {
if (!this.isEnabled || !this.reader) {
return null;
}
try {
// Clean IPv6-mapped IPv4 addresses (::ffff:192.168.1.1 -> 192.168.1.1)
const cleanIp = ipAddress.replace(/^::ffff:/i, '');
const result = this.reader.get(cleanIp);
if (result && result.country) {
return {
ip: ipAddress,
countryCode: result.country.iso_code || null,
countryName: result.country.names ? result.country.names.en : null,
};
}
return null;
} catch (err) {
logger.debug(`GeoIP lookup failed for ${ipAddress}: ${err.message}`);
return null;
}
}
isCountryBlocked(ipAddress, blockedCountries) {
if (!this.isEnabled || !blockedCountries || blockedCountries.length === 0) {
return false;
}
const geoInfo = this.lookup(ipAddress);
if (!geoInfo || !geoInfo.countryCode) {
// If we can't determine country, check if unknown IPs should be blocked
return false; // Default: allow if country unknown
}
const isBlocked = blockedCountries.includes(geoInfo.countryCode.toUpperCase());
if (isBlocked) {
logger.info(`Blocked connection from ${geoInfo.countryName} (${geoInfo.countryCode}): ${ipAddress}`);
}
return isBlocked;
}
getCountryInfo(ipAddress) {
return this.lookup(ipAddress);
}
}
// Singleton instance
let geoipInstance = null;
async function initializeGeoIP() {
if (!geoipInstance) {
geoipInstance = new GeoIPLookup();
await geoipInstance.initialize();
}
return geoipInstance;
}
function getGeoIP() {
return geoipInstance;
}
module.exports = {
initializeGeoIP,
getGeoIP,
};