add ipInfo table

This commit is contained in:
HF 2022-08-01 19:49:13 +02:00
parent d4ef69c2ac
commit e795874893
7 changed files with 134 additions and 30 deletions

View File

@ -11,7 +11,7 @@ import {
import { findIdByNameOrId } from '../data/sql/RegUser'; import { findIdByNameOrId } from '../data/sql/RegUser';
import ChatMessageBuffer from './ChatMessageBuffer'; import ChatMessageBuffer from './ChatMessageBuffer';
import socketEvents from '../socket/SocketEvents'; import socketEvents from '../socket/SocketEvents';
import { cheapDetector } from './isProxy'; import cheapDetector from './isProxy';
import { DailyCron } from '../utils/cron'; import { DailyCron } from '../utils/cron';
import { escapeMd } from './utils'; import { escapeMd } from './utils';
import ttags from './ttag'; import ttags from './ttag';

View File

@ -2,7 +2,8 @@ import fetch from '../utils/proxiedFetch';
import redis from '../data/redis/client'; import redis from '../data/redis/client';
import { getIPv6Subnet } from '../utils/ip'; import { getIPv6Subnet } from '../utils/ip';
import { Blacklist, Whitelist } from '../data/sql'; import whois from '../utils/whois';
import { Blacklist, Whitelist, IPInfo } from '../data/sql';
import { proxyLogger as logger } from './logger'; import { proxyLogger as logger } from './logger';
import { USE_PROXYCHECK } from './config'; import { USE_PROXYCHECK } from './config';
@ -37,14 +38,17 @@ async function getIPIntel(ip) {
logger.info('PROXYCHECK fetch getipintel is proxy? %s : %s', ip, body); logger.info('PROXYCHECK fetch getipintel is proxy? %s : %s', ip, body);
// returns tru iff we found 1 in the response and was ok (http code = 200) // returns tru iff we found 1 in the response and was ok (http code = 200)
const value = parseFloat(body); const value = parseFloat(body);
return value > 0.995; return [
value > 0.995,
`score:${value}`,
];
} }
/* /*
* check proxycheck.io if IP is proxy * check proxycheck.io if IP is proxy
* Use proxiedFetch with random proxies * Use proxiedFetch with random proxies
* @param ip IP to check * @param ip IP to check
* @return true if proxy, false if not * @return [ isProxy, info] true if proxy and extra info
*/ */
async function getProxyCheck(ip) { async function getProxyCheck(ip) {
const url = `http://proxycheck.io/v2/${ip}?risk=1&vpn=1&asn=1`; const url = `http://proxycheck.io/v2/${ip}?risk=1&vpn=1&asn=1`;
@ -61,7 +65,17 @@ async function getProxyCheck(ip) {
} }
const data = await response.json(); const data = await response.json();
logger.info('PROXYCHECK proxycheck is proxy?', data); logger.info('PROXYCHECK proxycheck is proxy?', data);
return data.status === 'ok' && data[ip].proxy === 'yes'; if (!data.status) {
return [
false,
'status not ok',
];
}
const ipData = data[ip];
return [
ipData.proxy === 'yes',
`${ipData.type},${ipData.city}`,
];
} }
/* /*
@ -98,7 +112,16 @@ async function isWhitelisted(ip) {
* dummy function to include if you don't want any proxycheck * dummy function to include if you don't want any proxycheck
*/ */
async function dummy() { async function dummy() {
return false; return [false, 'dummy'];
}
async function saveIPInfo(ip, isProxy, info) {
const whoisData = await whois(ip);
IPInfo.upsert({
...whoisData,
isProxy,
pcheck: info,
});
} }
/* /*
@ -116,7 +139,8 @@ async function withoutCache(f, ip) {
if (await isBlacklisted(ipKey)) { if (await isBlacklisted(ipKey)) {
return true; return true;
} }
const result = f(ip); const [result, info] = await f(ip);
saveIPInfo(ip, result, info);
return result; return result;
} }
@ -145,33 +169,30 @@ async function withCache(f, ip) {
if (checking.indexOf(ipKey) === -1 && lock > 0) { if (checking.indexOf(ipKey) === -1 && lock > 0) {
lock -= 1; lock -= 1;
checking.push(ipKey); checking.push(ipKey);
withoutCache(f, ip) try {
.then((result) => { const result = await withoutCache(f, ip);
const value = result ? 'y' : 'n'; const value = result ? 'y' : 'n';
redis.set(key, value, { redis.set(key, value, {
EX: 3 * 24 * 3600, EX: 3 * 24 * 3600,
}); // cache for three days }); // cache for three days
const pos = checking.indexOf(ipKey); const pos = checking.indexOf(ipKey);
if (~pos) checking.splice(pos, 1); if (~pos) checking.splice(pos, 1);
lock += 1; } catch (error) {
}) logger.error('PROXYCHECK withCache %s', error.message || error);
.catch((error) => { const pos = checking.indexOf(ipKey);
logger.error('PROXYCHECK withCache %s', error.message || error); if (~pos) checking.splice(pos, 1);
const pos = checking.indexOf(ipKey); } finally {
if (~pos) checking.splice(pos, 1); lock += 1;
lock += 1; }
});
} }
return false; return false;
} }
export function cheapDetector(ip) { function cheapDetector(ip) {
if (USE_PROXYCHECK) { if (USE_PROXYCHECK) {
return withCache(getProxyCheck, ip); return withCache(getProxyCheck, ip);
} }
return withCache(dummy, ip); return withCache(dummy, ip);
} }
export function blacklistDetector(ip) { export default cheapDetector;
return withCache(dummy, ip);
}

81
src/data/sql/IPInfo.js Normal file
View File

@ -0,0 +1,81 @@
import { DataTypes } from 'sequelize';
import sequelize from './sequelize';
const IPInfo = sequelize.define('IPInfo', {
ip: {
type: DataTypes.CHAR(39),
allowNull: false,
primaryKey: true,
},
uuid: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
allowNull: false,
},
country: {
type: DataTypes.CHAR(2),
defaultValue: 'xx',
allowNull: false,
},
cidr: {
type: DataTypes.CHAR(43),
allowNull: false,
},
org: {
type: DataTypes.CHAR(60),
},
descr: {
type: DataTypes.CHAR(60),
},
asn: {
type: DataTypes.CHAR(12),
allowNull: false,
},
proxy: {
type: DataTypes.TINYINT,
defaultValue: 0,
},
/*
* extra information from
* proxycheck
*/
pcheck: {
type: DataTypes.CHAR(60),
},
}, {
getterMethods: {
isProxy() {
return !!this.proxy;
},
},
setterMethods: {
isProxy(proxy) {
const num = (proxy) ? 1 : 0;
this.setDataValue('proxy', num);
},
org(value) {
this.setDataValue('org', value.slice(0, 60));
},
descr(value) {
this.setDataValue('descr', value.slice(0, 60));
},
pcheck(value) {
this.setDataValue('pcheck', value.slice(0, 60));
},
},
});
export default IPInfo;

View File

@ -5,6 +5,7 @@ import Channel from './Channel';
import UserChannel from './UserChannel'; import UserChannel from './UserChannel';
import Message from './Message'; import Message from './Message';
import UserBlock from './UserBlock'; import UserBlock from './UserBlock';
import IPInfo from './IPInfo';
/* /*
* User Channel access * User Channel access
@ -43,4 +44,5 @@ export {
UserChannel, UserChannel,
Message, Message,
UserBlock, UserBlock,
IPInfo,
}; };

View File

@ -7,7 +7,7 @@ import getMe from '../../core/me';
import { import {
USE_PROXYCHECK, USE_PROXYCHECK,
} from '../../core/config'; } from '../../core/config';
import { cheapDetector } from '../../core/isProxy'; import cheapDetector from '../../core/isProxy';
export default async (req, res, next) => { export default async (req, res, next) => {

View File

@ -25,7 +25,7 @@ import chatProvider, { ChatProvider } from '../core/ChatProvider';
import authenticateClient from './authenticateClient'; import authenticateClient from './authenticateClient';
import { drawByOffsets } from '../core/draw'; import { drawByOffsets } from '../core/draw';
import { needCaptcha } from '../data/redis/captcha'; import { needCaptcha } from '../data/redis/captcha';
import { cheapDetector } from '../core/isProxy'; import cheapDetector from '../core/isProxy';
const ipCounter = new Counter(); const ipCounter = new Counter();

View File

@ -42,7 +42,7 @@ function orgFromWhois(whoisData) {
function parseWhois(ip, whoisData) { function parseWhois(ip, whoisData) {
return { return {
ip, ip,
country: whoisData.country || 'N/A', country: whoisData.country || 'xx',
cidr: cIDRofWhois(ip, whoisData), cidr: cIDRofWhois(ip, whoisData),
org: orgFromWhois(whoisData), org: orgFromWhois(whoisData),
descr: whoisData.descr || 'N/A', descr: whoisData.descr || 'N/A',