Skip to content

Commit

Permalink
Implemented improvements for rate limiting
Browse files Browse the repository at this point in the history
  • Loading branch information
SGrondin committed Dec 21, 2014
1 parent 16fa10e commit 5e985d6
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 9 deletions.
21 changes: 21 additions & 0 deletions src/lib/config.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,27 @@ module.exports = (dnschain) ->
# Example: "mywebsite.com" : 9000 # This tells the server to send traffic meant to "mywebsite.com" to port 9000. It'll still be encrypted when it reaches port 9000
}

# WARNING: Do not change these settings unless you know exactly what you're doing.
# Read the source code, read the Bottleneck docs,
# make sure you understand how it might make your server complicit in DNS Amplification Attacks and your server might be taken down as a result.
rateLimiting:
dns:
maxConcurrent: 1
minTime: 200
highWater: 2
strategy: Bottleneck.strategy.BLOCK
penalty: 7000
http:
maxConcurrent: 2
minTime: 150
highWater: 10
strategy: Bottleneck.strategy.OVERFLOW
https:
maxConcurrent: 2
minTime: 150
highWater: 10
strategy: Bottleneck.strategy.OVERFLOW


nmcDefs =
rpcport: 8336
Expand Down
5 changes: 3 additions & 2 deletions src/lib/dns.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ module.exports = (dnschain) ->
@log = gNewLogger 'DNS'
@log.debug "Loading DNSServer..."
@method = gConf.get 'dns:oldDNSMethod'
@rateLimiting = gConf.get 'rateLimiting:dns'

# this is just for development testing of NODE_DNS method
# dns.setServers ['8.8.8.8']
Expand All @@ -55,8 +56,8 @@ module.exports = (dnschain) ->
@server.on 'sockegError', (err) -> gErr err
@server.on 'request', (req, res) =>
key = "dns-#{req.address.address}-#{req.question[0]?.name}"
limiter = gThrottle key, -> new Bottleneck 1, 200, 2, Bottleneck.strategy.BLOCK
limiter.changePenalty(7000).submit (@callback.bind @), req, res, null
limiter = gThrottle key, => new Bottleneck @rateLimiting.maxConcurrent, @rateLimiting.minTime, @rateLimiting.highWater, @rateLimiting.strategy
limiter.changePenalty(@rateLimiting.penalty).submit (@callback.bind @), req, res, null
@server.serve gConf.get('dns:port'), gConf.get('dns:host')

@log.info 'started DNS', gConf.get 'dns'
Expand Down
6 changes: 1 addition & 5 deletions src/lib/globals.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,7 @@ module.exports = (dnschain) ->
gLogger.error e.stack
throw e

gThrottle: (key, makeLimiter) ->
if limiters[key]?
limiters[key]
else
limiters[key] = makeLimiter()
gThrottle: (key, makeLimiter) -> limiters[key] ? (limiters[key] = makeLimiter())

# TODO: this function should take one parameter: an IP string
# and return either 'A' or 'AAAA'
Expand Down
3 changes: 2 additions & 1 deletion src/lib/http.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ module.exports = (dnschain) ->
# @log = @dnschain.log.child server: "HTTP"
@log = gNewLogger 'HTTP'
@log.debug "Loading HTTPServer..."
@rateLimiting = gConf.get 'rateLimiting:http'

@server = http.createServer((req, res) =>
key = "http-#{req.connection?.remoteAddress}"
limiter = gThrottle key, -> new Bottleneck 2, 150, 10, Bottleneck.strategy.OVERFLOW
limiter = gThrottle key, => new Bottleneck @rateLimiting.maxConcurrent, @rateLimiting.minTime, @rateLimiting.highWater, @rateLimiting.strategy
limiter.submit (@callback.bind @), req, res, null
) or gErr "http create"
@server.on 'error', (err) -> gErr err
Expand Down
3 changes: 2 additions & 1 deletion src/lib/https.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,11 @@ module.exports = (dnschain) ->
constructor: (@dnschain) ->
@log = gNewLogger "HTTPS"
@log.debug gLineInfo "Loading HTTPS..."
@rateLimiting = gConf.get 'rateLimiting:https'

@server = net.createServer (c) =>
key = "https-#{c.remoteAddress}"
limiter = gThrottle key, -> new Bottleneck 2, 150, 10, Bottleneck.strategy.OVERFLOW
limiter = gThrottle key, => new Bottleneck @rateLimiting.maxConcurrent, @rateLimiting.minTime, @rateLimiting.highWater, @rateLimiting.strategy
limiter.submit (@callback.bind @), c, null
@server.on "error", (err) -> gErr err
@server.on "close", -> gErr "HTTPS server was closed unexpectedly."
Expand Down

1 comment on commit 5e985d6

@taoeffect
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Great job.

Please sign in to comment.