0.5.3 • Published 5 years ago
express-attack v0.5.3
express-attack
Express middleware for blocking and throttling inspired by rack-attack and Node Redis GCRA Library
Installation
$ yarn install express-attackUsage
const express = require('express')
const expressAttack = require('express-attack')
const requestIp = require('request-ip')
const app = express()
function localReq(req) {
const clientIp = requestIp.getClientIp(req)
return clientIp === '127.0.0.1' || clientIp === '::1'
}
const BAD_BOTS = ['bad-bot', 'evil-bot']
function badBot(req) {
const userAgent = req.headers['user-agent'] || 'unknown'
const found = BAD_BOTS.find(function(badBot) {
return userAgent.indexOf(badBot) >= 0
})
return !!found
}
app.use(
expressAttack({
safelist: [localReq],
blocklist: [badBot]
})
)
app.get('/foo', function(req, res, next) {
res.json({ msg: 'bar' })
})
app.listen(3000, function() {
console.log('The server is running at http://localhost:3000')
})Throttling
GCRA is used for throttling. Default store is memoryStore, you can create your own store.
// If I want to allow 2 request per second and at most 6 requests simultaneously, then:
// emissionInterval = period / rate => 1000 milliseconds / 2 reqs => 500
// burst => 6
function throttleByIp(req) {
const clientIp = requestIp.getClientIp(req)
return {
key: clientIp
burst 6,
emissionInterval: 500
}
}
app.use(
expressAttack({
throttles: [throttleByIp]
})
)Create your store
Create an object with below methods:
get(key): retrun value according to key, if key doesn't exsits return undefined.
set(key, timestamp, period): assign timestamp to key, and expire the key after period milliseconds.
function dummyStore() {
const store = {}
const get = async function(key) {
return store[key]
}
const set = async function(key, timestamp, period) {
store[key] = timestamp
}
return {
get,
set
}
}
app.use(
expressAttack({
throttles: [throttleByIp],
store: dummyStore()
})
)Customizing responses
// do what ever you want with response.
const blocklistedResponse = (req, res) => {
return res.status(503).send('Service Unavailable')
}
const throttledResponse = (req, res) => {
return res.status(503).send('Service Unavailable')
}
app.use(
expressAttack({
blocklistedResponse
throttledResponse
})
)Options
safelist: array of safe request functions, if one of the fucntion returntrue, ths request is allowed to go.blocklist: array of block request functions, if one of the function reutrntrue, the request is blocked.throttles: array of throttle functions, check Throttling for detail.safelistedResponse(req, res, next): custom your response when request is mark assafelisted.blocklistedResponse(req, res): custom your response when request is mark asblocklisted.throttledResponse(req, res): custom your response when request is mark asthrottled.normalResponse(req, res, next): custom your response when request not in above situation.errorResponse(req, res, next, error): custom your response when exception raise during check request phase.store: check Custom your store for detail.
License
MIT