api: use req.ip instead of cloudflare headers, ratelimit ipv6 by prefix

allows for more versatile configurations that do not necessarily have to use cloudflare

also ratelimits IPv6 addresses by prefix instead of individual addresses
currently set at /56, which should not be too strict
(yet allows a /48 holder to make 256 as many requests instead of 2^80 as many requests), change if needed
This commit is contained in:
dumbmoron 2023-07-25 19:46:25 +00:00 committed by dumbmoron
parent b4f11b047e
commit a375000ae9
No known key found for this signature in database
GPG key ID: C59997C76C6A8E5F
3 changed files with 16 additions and 3 deletions

View file

@ -34,6 +34,7 @@
"express-rate-limit": "^6.3.0",
"ffmpeg-static": "^5.1.0",
"hls-parser": "^0.10.7",
"ipaddr.js": "2.1.0",
"nanoid": "^4.0.2",
"node-cache": "^5.1.2",
"psl": "1.9.0",

View file

@ -24,7 +24,7 @@ export function runAPI(express, app, gitCommit, gitBranch, __dirname) {
max: 20,
standardHeaders: true,
legacyHeaders: false,
keyGenerator: (req, res) => sha256(getIP(req), ipSalt),
keyGenerator: req => sha256(getIP(req), ipSalt),
handler: (req, res, next, opt) => {
return res.status(429).json({
"status": "rate-limit",
@ -37,7 +37,7 @@ export function runAPI(express, app, gitCommit, gitBranch, __dirname) {
max: 25,
standardHeaders: true,
legacyHeaders: false,
keyGenerator: (req, res) => sha256(getIP(req), ipSalt),
keyGenerator: req => sha256(getIP(req), ipSalt),
handler: (req, res, next, opt) => {
return res.status(429).json({
"status": "rate-limit",
@ -49,6 +49,8 @@ export function runAPI(express, app, gitCommit, gitBranch, __dirname) {
const startTime = new Date();
const startTimestamp = Math.floor(startTime.getTime());
app.set('trust proxy', ['loopback', 'uniquelocal']);
app.use('/api/:type', cors(corsConfig));
app.use('/api/json', apiLimiter);
app.use('/api/stream', apiLimiterStream);

View file

@ -1,5 +1,6 @@
import { normalizeURL } from "../processing/url.js";
import { createStream } from "../stream/manage.js";
import ipaddr from "ipaddr.js";
const apiVar = {
allowed: {
@ -111,7 +112,16 @@ export function checkJSONPost(obj) {
}
}
export function getIP(req) {
return req.header('cf-connecting-ip') ? req.header('cf-connecting-ip') : req.ip;
const strippedIP = req.ip.replace(/^::ffff:/, '');
const ip = ipaddr.parse(strippedIP);
if (ip.kind() === 'ipv4')
return strippedIP;
const PREFIX = 56;
const v6Bytes = ip.toByteArray();
v6Bytes.fill(0, PREFIX / 8);
return ipaddr.fromByteArray(v6Bytes).toString();
}
export function cleanHTML(html) {
let clean = html.replace(/ {4}/g, '');