api: proper rate limiting (including limiting ipv6 by prefix)

merge pull request #163 from dumbmoron/xff
This commit is contained in:
wukko 2024-01-31 16:48:13 +06:00 committed by GitHub
commit bb04749fc1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 17 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,17 @@ 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, '');