mirror of https://gitgud.io/fatchan/jschan.git
***DO NOT USE*** This still has some issues and needs testing. - needs updated nginx configs added, expects "TOR" in the x-country-code header under a separate vhost - need to make sure bans work properly still - need to implement system to prevent captcha ddos, since i cant just to IP ratelimit now - im 99% sure post history of tor users is broken if viewed by non-global staff - manual input ban form will also be broken for non-global staff - could still use some improvement on the middleware having a little more complicated flor for tor users But for the most part it works. Basically it will use the bypass id of a tor user as their "ip".merge-requests/208/head
parent
ad2c1e030e
commit
b0797f0418
20 changed files with 266 additions and 869 deletions
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 102 KiB |
@ -0,0 +1,82 @@ |
||||
'use strict'; |
||||
|
||||
const { Bypass, Captchas } = require(__dirname+'/../../db/') |
||||
, { ObjectId } = require(__dirname+'/../../db/db.js') |
||||
, { secureCookies, blockBypass } = require(__dirname+'/../../configs/main.js') |
||||
, remove = require('fs-extra').remove |
||||
, uploadDirectory = require(__dirname+'/../files/uploadDirectory.js') |
||||
, dynamicResponse = require(__dirname+'/../dynamic.js') |
||||
, production = process.env.NODE_ENV === 'production'; |
||||
|
||||
module.exports = async (req, res, next) => { |
||||
|
||||
console.log('TOR PRE BYPASS') |
||||
//early byapss is only needed for tor users
|
||||
if (!res.locals.tor) { |
||||
return next(); |
||||
} |
||||
|
||||
//for captcha in existing form (NOTE: wont work for multipart forms yet)
|
||||
const input = req.body.captcha; |
||||
if (input && input.length !== 6) { |
||||
return dynamicResponse(req, res, 403, 'message', { |
||||
'title': 'Forbidden', |
||||
'message': 'Incorrect captcha answer', |
||||
'redirect': req.headers.referer, |
||||
}); |
||||
} |
||||
const captchaId = req.cookies.captchaid; |
||||
if (input) { |
||||
// try to get the captcha from the DB
|
||||
let captcha; |
||||
try { |
||||
const captchaMongoId = ObjectId(captchaId); |
||||
captcha = await Captchas.findOneAndDelete(captchaMongoId, input); |
||||
} catch (err) { |
||||
return next(err); |
||||
} |
||||
if (captcha && captcha.value && captcha.value.text === input) { |
||||
res.locals.solvedCaptcha = true; |
||||
res.clearCookie('captchaid'); |
||||
remove(`${uploadDirectory}/captcha/${captchaId}.jpg`).catch(e => { console.error(e) }); |
||||
} else { |
||||
return dynamicResponse(req, res, 403, 'message', { |
||||
'title': 'Forbidden', |
||||
'message': 'Incorrect captcha answer', |
||||
'redirect': req.headers.referer, |
||||
}); |
||||
} |
||||
} |
||||
|
||||
if (res.locals.solvedCaptcha) { |
||||
//they dont have a valid bypass, but just solved a captcha, so give them a new one
|
||||
const newBypass = await Bypass.getBypass(); |
||||
const newBypassId = newBypass.insertedId; |
||||
res.locals.blockBypass = newBypass.ops[0]; |
||||
res.cookie('bypassid', newBypassId.toString(), { |
||||
'maxAge': blockBypass.expireAfterTime, |
||||
'secure': production && secureCookies, |
||||
'sameSite': 'strict', |
||||
'signed': true |
||||
}); |
||||
return next(); |
||||
} |
||||
|
||||
//check if blockbypass exists and right length
|
||||
const bypassId = req.signedCookies.bypassid; |
||||
if (!bypassId || bypassId.length !== 24) { |
||||
return dynamicResponse(req, res, 403, 'message', { |
||||
'title': 'Forbidden', |
||||
'message': 'Please complete a block bypass to continue', |
||||
'frame': '/bypass_minimal.html', |
||||
'link': { |
||||
'href': '/bypass.html', |
||||
'text': 'Get block bypass', |
||||
}, |
||||
}); |
||||
} |
||||
|
||||
console.log('in tor pre bypass', bypassId) |
||||
return next(); |
||||
|
||||
} |
@ -0,0 +1,65 @@ |
||||
'use strict'; |
||||
|
||||
const { globalLimits, debugLogs, filterFileNames, spaceFileNameReplacement } = require(__dirname+'/../configs/main.js') |
||||
, dynamicResponse = require(__dirname+'/dynamic.js') |
||||
, uploadLimitFunction = (req, res, next) => { |
||||
return dynamicResponse(req, res, 413, 'message', { |
||||
'title': 'Payload Too Large', |
||||
'message': 'Your upload was too large', |
||||
'redirect': req.headers.referer |
||||
}); |
||||
} |
||||
, upload = require('express-fileupload') |
||||
, postFiles = upload({ |
||||
debug: debugLogs, |
||||
createParentPath: true, |
||||
safeFileNames: filterFileNames, |
||||
spaceFileNameReplacement, |
||||
preserveExtension: 4, |
||||
limits: { |
||||
totalSize: globalLimits.postFilesSize.max, |
||||
fileSize: globalLimits.postFilesSize.max, |
||||
//files: globalLimits.postFiles.max
|
||||
}, |
||||
limitHandler: uploadLimitFunction, |
||||
useTempFiles: true, |
||||
tempFileDir: __dirname+'/../tmp/' |
||||
}); |
||||
|
||||
|
||||
module.exports = { |
||||
|
||||
handleBannerFiles: upload({ |
||||
debug: debugLogs, |
||||
createParentPath: true, |
||||
safeFileNames: filterFileNames, |
||||
spaceFileNameReplacement, |
||||
preserveExtension: 4, |
||||
limits: { |
||||
totalSize: globalLimits.bannerFilesSize.max, |
||||
fileSize: globalLimits.bannerFilesSize.max, |
||||
files: globalLimits.bannerFiles.max |
||||
}, |
||||
limitHandler: uploadLimitFunction, |
||||
useTempFiles: true, |
||||
tempFileDir: __dirname+'/../tmp/' |
||||
}), |
||||
|
||||
handlePostFilesEarlyTor: (req, res, next) => { |
||||
console.log('handlePostFilesEarlyTor') |
||||
console.log(res.locals.tor, postFiles) |
||||
if (res.locals.tor) { |
||||
return postFiles(req, res, next); |
||||
} |
||||
return next(); |
||||
}, |
||||
|
||||
handlePostFiles: (req, res, next) => { |
||||
console.log('handlePostFiles') |
||||
if (res.locals.tor) { |
||||
return next(); |
||||
} |
||||
return postFiles(req, res, next); |
||||
}, |
||||
|
||||
} |
@ -0,0 +1,14 @@ |
||||
'use strict' |
||||
|
||||
const { countryNamesMap } = require(__dirname+'/countries.js') |
||||
, { countryCodeHeader } = require(__dirname+'/../configs/main.js'); |
||||
|
||||
module.exports = (req, res, next) => { |
||||
const code = req.headers[countryCodeHeader] || 'XX'; |
||||
res.locals.tor = code === 'TOR'; |
||||
res.locals.country = { |
||||
code, |
||||
name: countryNamesMap[code], |
||||
} |
||||
return next(); |
||||
} |
Loading…
Reference in new issue