Prevent tokens from being sent to the OVH servers. Instead, add them directly to the Redis DB. Ref #3393
58 lines
1.6 KiB
JavaScript
58 lines
1.6 KiB
JavaScript
'use strict'
|
|
|
|
const RateLimit = require('./rate-limit')
|
|
|
|
function setRoutes({ rateLimit }, { server, metricInstance }) {
|
|
const ipRateLimit = new RateLimit({
|
|
// Exclude IPs for GitHub Camo, determined experimentally by running e.g.
|
|
// `curl --insecure -u ":shields-secret" https://s0.shields-server.com/sys/rate-limit`
|
|
safelist: /^(?:192\.30\.252\.\d+)|(?:140\.82\.115\.\d+)$/,
|
|
})
|
|
const badgeTypeRateLimit = new RateLimit({ maxHitsPerPeriod: 3000 })
|
|
const refererRateLimit = new RateLimit({
|
|
maxHitsPerPeriod: 300,
|
|
safelist: /^https?:\/\/shields\.io\/$/,
|
|
})
|
|
|
|
server.handle((req, res, next) => {
|
|
if (rateLimit) {
|
|
const ip =
|
|
(req.headers['x-forwarded-for'] || '').split(', ')[0] ||
|
|
req.socket.remoteAddress
|
|
const badgeType = req.url.split(/[/-]/).slice(0, 3).join('')
|
|
const referer = req.headers.referer
|
|
|
|
if (ipRateLimit.isBanned(ip, req, res)) {
|
|
metricInstance.noteRateLimitExceeded('ip')
|
|
return
|
|
}
|
|
if (badgeTypeRateLimit.isBanned(badgeType, req, res)) {
|
|
metricInstance.noteRateLimitExceeded('badge_type')
|
|
return
|
|
}
|
|
if (refererRateLimit.isBanned(referer, req, res)) {
|
|
metricInstance.noteRateLimitExceeded('referrer')
|
|
return
|
|
}
|
|
}
|
|
|
|
next()
|
|
})
|
|
|
|
server.get('/sys/rate-limit', (req, res) => {
|
|
res.json({
|
|
ip: ipRateLimit.toJSON(),
|
|
badgeType: badgeTypeRateLimit.toJSON(),
|
|
referer: refererRateLimit.toJSON(),
|
|
})
|
|
})
|
|
|
|
return function () {
|
|
ipRateLimit.stop()
|
|
badgeTypeRateLimit.stop()
|
|
refererRateLimit.stop()
|
|
}
|
|
}
|
|
|
|
module.exports = { setRoutes }
|