Skip to content

Commit

Permalink
imported limit plugin from Haraka
Browse files Browse the repository at this point in the history
  • Loading branch information
msimerson committed Jan 26, 2017
1 parent afa76b6 commit adbcdc4
Show file tree
Hide file tree
Showing 8 changed files with 653 additions and 2 deletions.
27 changes: 27 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"env": {
"node": true,
"mocha": true,
"es6": true
},
"extends": "eslint:recommended",
"installedESLint": true,
"root": true,
"rules": {
"comma-dangle": [2, "only-multiline"],
"dot-notation": 2,
"indent": [2, 4, {"SwitchCase": 1}],
"one-var": [2, "never"],
"no-trailing-spaces": [2, { "skipBlankLines": false }],
"keyword-spacing": [2, {
"before": true,
"after": true
}],
"no-delete-var": 2,
"no-empty": ["error", { "allowEmptyCatch": true }],
"no-label-var": 2,
"no-shadow": 2,
"no-unused-vars": [ 1, { "args": "none" }],
"no-console": 0
}
}
20 changes: 20 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
language: node_js
node_js:
- "4"
- "6"

services:
- redis-server

before_script:

script:
- npm run lint
- npm test

after_success:
- npm install istanbul codecov
- npm run cover
- ./node_modules/.bin/codecov

sudo: false
80 changes: 78 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,78 @@
# haraka-plugin-limit
Enforce many types of limits on a Haraka mail server.
# limit

Apply several types of limits to SMTP connections.

Each limit type has a max value that can be defined in limit.ini. The default is empty / disabled until a value has been set.

## See Also

To set rate limits on connections and recipients, see the `rate_limit` plugin.

## concurrency

When `[concurrency]max` is defined, it limits the maximum number of simultaneous connections per IP address. Connection attempts in excess of the limit are delayed for `disconnect_delay` seconds (default: 3) before being disconnected.

This works best in conjunction with a history / reputation database, so that
one can assign very low concurrency (1) to bad or unknown senders and higher
limits for reputable mail servers.

### History

History: when enabled, the `history` setting is the name of a plugin that stores IP history / reputation results. The result store must have a positive value for good connections and negative integers for poor / undesirable connections. Karma is one such plugin.


## recipients

When `[recipients]max` is defined, each connection is limited to that number of recipients. The limit is imposed against **all** recipient attempts. Attempts in excess of the limit are issued a temporary failure.


## unrecognized_commands

When `[unrecognized_commands]max` is set, a connection that exceeeds the limit is disconnected.

Unrecognized commands are normally SMTP verbs invalidly issued by the client.
Examples:

* issuing AUTH when we didn't advertise AUTH extension
* issuing STARTTLS when we didn't advertise STARTTLS
* invalid SMTP verbs


### Limitations

The unrecognized_command hook is used by the `tls` and `auth` plugins, so
running this plugin before those would result in valid operations getting
counted against that connections limits. The solution is simple: list
`limit` in config/plugins after those.


## errors

When `[errors]max` is set, a connection that exceeeds the limit is disconnected. Errors that count against this limit include:

* issuing commands out of turn (MAIL before EHLO, RCPT before MAIL, etc)
* attempting MAIL on port 465/587 without AUTH
* MAIL or RCPT addresses that fail to parse

# Error Handling

## Too high counters

If the NoSQL store is Redis and Haraka is restarted or crashes while active
connections are open, the concurrency counters might be inflated. This is
handled by the [concurrency]reset setting (default: 10m), which:

* ssc: sets collection expiration time
* redis: empties the concurrency hash
* RAM: empties the in-memory hash of all keys

## Too low counters

Because the redis and RAM objects are emptied periodically, connections that
are open while the collections are emptied will be too low. When
that happens, log messages like these might be emitted:

resetting 0 to 1
resetting -1 to 1

This is a harmless error condition that is repaired automatically.
46 changes: 46 additions & 0 deletions config/limit.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
; limits imposed on connection(s)
; see also: rate_limit

[redis]
; host=127.0.0.1
; port=6387
db=4
;
; expire: minutes concurrency information is cached in RAM, default: 10
; expire=10

; there are no defaults unless shown. Limits are disabled until a max value is set.
; help: haraka -h limits

[concurrency]
; max=3
; disconnect_delay=5
; reset=10 // default: minutes

; History: when enabled, the value must be a plugin which stores IP history
; results. The result store must have a positive value for good connections
; and negative integers for poor / undesirable connections. At present,
; karma is the only such plugin.
; history=karma
; history_bad=1
; history_none=3
; history_good=10


[recipients]
; max= 20
; max_relaying= 100

; The same history notes for [concurrency] apply here.
; history=karma
; history_bad=5
; history_none=15
; history_good=50


[unrecognized_commands]
; max= 10


[errors]
; max= 10

0 comments on commit adbcdc4

Please sign in to comment.