change Blacklist/Whitelist tables to not use ip.toLong to avoid weird results on IPv6
This commit is contained in:
parent
62337771a2
commit
759bffbf1f
5
package-lock.json
generated
5
package-lock.json
generated
|
@ -6718,11 +6718,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
|
||||||
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
|
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
|
||||||
},
|
},
|
||||||
"ip": {
|
|
||||||
"version": "1.1.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
|
|
||||||
"integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo="
|
|
||||||
},
|
|
||||||
"ip-address": {
|
"ip-address": {
|
||||||
"version": "6.2.0",
|
"version": "6.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-6.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-6.2.0.tgz",
|
||||||
|
|
|
@ -41,7 +41,6 @@
|
||||||
"global": "^4.3.2",
|
"global": "^4.3.2",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
"http-proxy-agent": "^3.0.0",
|
"http-proxy-agent": "^3.0.0",
|
||||||
"ip": "^1.1.5",
|
|
||||||
"ip-address": "^6.2.0",
|
"ip-address": "^6.2.0",
|
||||||
"isomorphic-fetch": "^2.2.1",
|
"isomorphic-fetch": "^2.2.1",
|
||||||
"keycode": "^2.1.9",
|
"keycode": "^2.1.9",
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
* @flow
|
* @flow
|
||||||
* */
|
* */
|
||||||
|
|
||||||
import IP from 'ip';
|
import fetch from '../utils/proxiedFetch';
|
||||||
import fetch from '../utils/proxiedFetch.js';
|
|
||||||
|
|
||||||
import redis from '../data/redis';
|
import redis from '../data/redis';
|
||||||
|
import { getIPv6Subnet } from '../utils/ip';
|
||||||
import { Blacklist, Whitelist } from '../data/models';
|
import { Blacklist, Whitelist } from '../data/models';
|
||||||
import logger from './logger';
|
import logger from './logger';
|
||||||
|
|
||||||
|
@ -108,11 +108,10 @@ async function getCombined(ip: string): Promise<boolean> {
|
||||||
* @return true if blacklisted
|
* @return true if blacklisted
|
||||||
*/
|
*/
|
||||||
async function isBlacklisted(ip: string): Promise<boolean> {
|
async function isBlacklisted(ip: string): Promise<boolean> {
|
||||||
const numIp = IP.toLong(ip);
|
|
||||||
const count = await Blacklist
|
const count = await Blacklist
|
||||||
.count({
|
.count({
|
||||||
where: {
|
where: {
|
||||||
numIp,
|
ip,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return count !== 0;
|
return count !== 0;
|
||||||
|
@ -124,11 +123,10 @@ async function isBlacklisted(ip: string): Promise<boolean> {
|
||||||
* @return true if whitelisted
|
* @return true if whitelisted
|
||||||
*/
|
*/
|
||||||
async function isWhitelisted(ip: string): Promise<boolean> {
|
async function isWhitelisted(ip: string): Promise<boolean> {
|
||||||
const numIp = IP.toLong(ip);
|
|
||||||
const count = await Whitelist
|
const count = await Whitelist
|
||||||
.count({
|
.count({
|
||||||
where: {
|
where: {
|
||||||
numIp,
|
ip,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return count !== 0;
|
return count !== 0;
|
||||||
|
@ -137,7 +135,7 @@ async function isWhitelisted(ip: string): Promise<boolean> {
|
||||||
/*
|
/*
|
||||||
* 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(ip: string): Promise<boolean> {
|
async function dummy(): Promise<boolean> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +147,8 @@ async function dummy(ip: string): Promise<boolean> {
|
||||||
*/
|
*/
|
||||||
async function withoutCache(f, ip) {
|
async function withoutCache(f, ip) {
|
||||||
if (!ip) return true;
|
if (!ip) return true;
|
||||||
return !(await isWhitelisted(ip)) && (await isBlacklisted(ip) || await f(ip));
|
const ipKey = getIPv6Subnet(ip);
|
||||||
|
return !(await isWhitelisted(ipKey)) && (await isBlacklisted(ipKey) || await f(ip));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -160,11 +159,12 @@ async function withoutCache(f, ip) {
|
||||||
* @return true if proxy or blacklisted, false if not or whitelisted
|
* @return true if proxy or blacklisted, false if not or whitelisted
|
||||||
*/
|
*/
|
||||||
let lock = 4;
|
let lock = 4;
|
||||||
const checking = new Array();
|
const checking = [];
|
||||||
async function withCache(f, ip) {
|
async function withCache(f, ip) {
|
||||||
if (!ip) return true;
|
if (!ip) return true;
|
||||||
// get from cache, if there
|
// get from cache, if there
|
||||||
const key = `isprox:${ip}`;
|
const ipKey = getIPv6Subnet(ip);
|
||||||
|
const key = `isprox:${ipKey}`;
|
||||||
const cache = await redis.getAsync(key);
|
const cache = await redis.getAsync(key);
|
||||||
if (cache) {
|
if (cache) {
|
||||||
const str = cache.toString('utf8');
|
const str = cache.toString('utf8');
|
||||||
|
@ -176,20 +176,20 @@ async function withCache(f, ip) {
|
||||||
// else make asynchronous ipcheck and assume no proxy in the meantime
|
// else make asynchronous ipcheck and assume no proxy in the meantime
|
||||||
// use lock to just check three at a time
|
// use lock to just check three at a time
|
||||||
// do not check ip that currently gets checked
|
// do not check ip that currently gets checked
|
||||||
if (checking.indexOf(ip) == -1 && lock > 0) {
|
if (checking.indexOf(ipKey) == -1 && lock > 0) {
|
||||||
lock -= 1;
|
lock -= 1;
|
||||||
checking.push(ip);
|
checking.push(ipKey);
|
||||||
withoutCache(f, ip)
|
withoutCache(f, ip)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
const value = result ? 'y' : 'n';
|
const value = result ? 'y' : 'n';
|
||||||
redis.setAsync(key, value, 'EX', 3 * 24 * 3600); // cache for three days
|
redis.setAsync(key, value, 'EX', 3 * 24 * 3600); // cache for three days
|
||||||
const pos = checking.indexOf(ip);
|
const pos = checking.indexOf(ipKey);
|
||||||
if (~pos) checking.splice(pos, 1);
|
if (~pos) checking.splice(pos, 1);
|
||||||
lock += 1;
|
lock += 1;
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
logger.error('PROXYCHECK withCache %s', error.message || error);
|
logger.error('PROXYCHECK withCache %s', error.message || error);
|
||||||
const pos = checking.indexOf(ip);
|
const pos = checking.indexOf(ipKey);
|
||||||
if (~pos) checking.splice(pos, 1);
|
if (~pos) checking.splice(pos, 1);
|
||||||
lock += 1;
|
lock += 1;
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,33 +6,17 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import DataType from 'sequelize';
|
import DataType from 'sequelize';
|
||||||
import nodeIp from 'ip';
|
|
||||||
|
|
||||||
import Model from '../sequelize';
|
import Model from '../sequelize';
|
||||||
|
|
||||||
|
|
||||||
const Blacklist = Model.define('Blacklist', {
|
const Blacklist = Model.define('Blacklist', {
|
||||||
|
|
||||||
numIp: {
|
ip: {
|
||||||
type: DataType.INTEGER.UNSIGNED,
|
type: DataType.CHAR(39),
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
primaryKey: true,
|
primaryKey: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
}, {
|
|
||||||
|
|
||||||
getterMethods: {
|
|
||||||
ip(): string {
|
|
||||||
return nodeIp.fromLong(this.numIp);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
setterMethods: {
|
|
||||||
ip(value: string): number {
|
|
||||||
this.setDataValue('numIp', nodeIp.toLong(value));
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default Blacklist;
|
export default Blacklist;
|
||||||
|
|
|
@ -7,33 +7,17 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import DataType from 'sequelize';
|
import DataType from 'sequelize';
|
||||||
import nodeIp from 'ip';
|
|
||||||
|
|
||||||
import Model from '../sequelize';
|
import Model from '../sequelize';
|
||||||
|
|
||||||
|
|
||||||
const Whitelist = Model.define('Whitelist', {
|
const Whitelist = Model.define('Whitelist', {
|
||||||
|
|
||||||
numIp: {
|
ip: {
|
||||||
type: DataType.INTEGER.UNSIGNED,
|
type: DataType.CHAR(39),
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
primaryKey: true,
|
primaryKey: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
}, {
|
|
||||||
|
|
||||||
getterMethods: {
|
|
||||||
ip(): string {
|
|
||||||
return nodeIp.fromLong(this.numIp);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
setterMethods: {
|
|
||||||
ip(value: string): number {
|
|
||||||
this.setDataValue('numIp', nodeIp.toLong(value));
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default Whitelist;
|
export default Whitelist;
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import nodeIp from 'ip';
|
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import expressLimiter from 'express-limiter';
|
import expressLimiter from 'express-limiter';
|
||||||
import type { Request, Response } from 'express';
|
import type { Request, Response } from 'express';
|
||||||
|
@ -12,7 +11,7 @@ import bodyParser from 'body-parser';
|
||||||
import sharp from 'sharp';
|
import sharp from 'sharp';
|
||||||
import multer from 'multer';
|
import multer from 'multer';
|
||||||
|
|
||||||
import { getIPFromRequest } from '../utils/ip';
|
import { getIPFromRequest, getIPv6Subnet } from '../utils/ip';
|
||||||
import { getIdFromObject } from '../core/utils';
|
import { getIdFromObject } from '../core/utils';
|
||||||
import redis from '../data/redis';
|
import redis from '../data/redis';
|
||||||
import session from '../core/session';
|
import session from '../core/session';
|
||||||
|
@ -64,17 +63,20 @@ router.use(passport.session());
|
||||||
router.use(async (req, res, next) => {
|
router.use(async (req, res, next) => {
|
||||||
const ip = await getIPFromRequest(req);
|
const ip = await getIPFromRequest(req);
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
logger.info(`${ip} tried to access admintools without login`);
|
logger.info(`ADMINTOOLS: ${ip} tried to access admintools without login`);
|
||||||
res.status(403).send('You are not logged in');
|
res.status(403).send('You are not logged in');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!req.user.isAdmin()) {
|
if (!req.user.isAdmin()) {
|
||||||
logger.info(
|
logger.info(
|
||||||
`${ip} / ${req.user.id} tried to access admintools but isn't Admin`,
|
`ADMINTOOLS: ${ip}/${req.user.id} wrongfully tried to access admintools`,
|
||||||
);
|
);
|
||||||
res.status(403).send('You are not allowed to access this page');
|
res.status(403).send('You are not allowed to access this page');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
logger.info(
|
||||||
|
`ADMINTOOLS: ${req.user.id} / ${req.user.regUser.name} is using admintools`,
|
||||||
|
);
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -86,31 +88,32 @@ router.use(async (req, res, next) => {
|
||||||
* @return true if successful
|
* @return true if successful
|
||||||
*/
|
*/
|
||||||
async function executeAction(action: string, ip: string): boolean {
|
async function executeAction(action: string, ip: string): boolean {
|
||||||
const numIp = nodeIp.toLong(ip);
|
const ipKey = getIPv6Subnet(ip);
|
||||||
const key = `isprox:${ip}`;
|
const key = `isprox:${ipKey}`;
|
||||||
|
|
||||||
|
logger.info(`ADMINTOOLS: ${action} ${ip}`);
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'ban':
|
case 'ban':
|
||||||
await Blacklist.findOrCreate({
|
await Blacklist.findOrCreate({
|
||||||
where: { numIp },
|
where: { ip: ipKey },
|
||||||
});
|
});
|
||||||
await redis.setAsync(key, 'y', 'EX', 24 * 3600);
|
await redis.setAsync(key, 'y', 'EX', 24 * 3600);
|
||||||
break;
|
break;
|
||||||
case 'unban':
|
case 'unban':
|
||||||
await Blacklist.destroy({
|
await Blacklist.destroy({
|
||||||
where: { numIp },
|
where: { ip: ipKey },
|
||||||
});
|
});
|
||||||
await redis.del(key);
|
await redis.del(key);
|
||||||
break;
|
break;
|
||||||
case 'whitelist':
|
case 'whitelist':
|
||||||
await Whitelist.findOrCreate({
|
await Whitelist.findOrCreate({
|
||||||
where: { numIp },
|
where: { ip: ipKey },
|
||||||
});
|
});
|
||||||
await redis.setAsync(key, 'n', 'EX', 24 * 3600);
|
await redis.setAsync(key, 'n', 'EX', 24 * 3600);
|
||||||
break;
|
break;
|
||||||
case 'unwhitelist':
|
case 'unwhitelist':
|
||||||
await Whitelist.destroy({
|
await Whitelist.destroy({
|
||||||
where: { numIp },
|
where: { ip: ipKey },
|
||||||
});
|
});
|
||||||
await redis.del(key);
|
await redis.del(key);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Request, Response } from 'express';
|
import type { Request, Response } from 'express';
|
||||||
import nodeIp from 'ip';
|
|
||||||
|
|
||||||
import draw from '../../core/draw';
|
import draw from '../../core/draw';
|
||||||
import { blacklistDetector, cheapDetector, strongDetector } from '../../core/isProxy';
|
import { blacklistDetector, cheapDetector, strongDetector } from '../../core/isProxy';
|
||||||
|
@ -83,9 +82,8 @@ async function checkHuman(req: Request, res: Response, next) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { token } = req.body;
|
const { token } = req.body;
|
||||||
const numIp = nodeIp.toLong(ip);
|
|
||||||
|
|
||||||
const key = `human:${ip}:${ip}`;
|
const key = `human:${ip}`;
|
||||||
|
|
||||||
const ttl: number = await redis.ttlAsync(key);
|
const ttl: number = await redis.ttlAsync(key);
|
||||||
if (ttl > 0) {
|
if (ttl > 0) {
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import nodeIp from 'ip';
|
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import expressLimiter from 'express-limiter';
|
import expressLimiter from 'express-limiter';
|
||||||
import bodyParser from 'body-parser';
|
import bodyParser from 'body-parser';
|
||||||
|
|
|
@ -17,7 +17,7 @@ function randomProxyURL() {
|
||||||
return rand;
|
return rand;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetch(url, options = {}) {
|
function fetch(url, options = {}) {
|
||||||
if (proxylist.length === 0) {
|
if (proxylist.length === 0) {
|
||||||
return isoFetch(url, options);
|
return isoFetch(url, options);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user