limit outgoing

----------

Limit 100 e-mails per hour postfix

edit main.cf and set some sender limits:

anvil_rate_time_unit = 3600s

anvil_status_update_time = 600s

smtpd_recipient_limit = 100

smtpd_recipient_overshoot_limit = 101

smtpd_client_connection_rate_limit = 100

smtpd_client_message_rate_limit = 100

smtpd_client_recipient_rate_limit = 100

local_destination_concurrency_limit = 2

default_destination_concurrency_limit = 20

this will limit 100 mails per user per hour. A sender will have to wait for an hour before they can send out any more mails, if they reach limit of 100 e-mail.

Postfix - Rate limit for all domains

smtp_destination_rate_delay = 60s

default_destination_recipient_limit = 2

default_destination_concurrency_limit = 1

smtp_destination_concurrency_limit = 1

smtp_destination_recipient_limit = 2

smtp_initial_destination_concurrency = 1

Postfix: limit outgoing mail throttling

 /etc/postfix/main.cf

smtp_destination_concurrency_limit = 2 smtp_destination_rate_delay = 1s smtp_extra_recipient_limit = 10

Then restart your Postfix.

2.1 Limit by domain

You can limit per domain if you want like this:

 /etc/postfix/main.cf

transport_maps = hash:/etc/postfix/transport   # Throttle limit policy mail (global) smtp_destination_concurrency_limit = 4 smtp_extra_recipient_limit = 2   # Polite policy polite_destination_concurrency_limit = 3 polite_destination_rate_delay = 0 polite_destination_recipient_limit = 5   # Turtle policy turtle_destination_concurrency_limit = 2 turtle_destination_rate_delay = 1s turtle_destination_recipient_limit = 2

Then add domains with the wished policy:

 /etc/postfix/transport

gmail.com polite: yahoo.com polite: hotmail.com turtle: live.fr turtle: orange.fr turtle:

Edit master configuration to inform postfix of those config. Add those lines:

 /etc/postfix/master.cf

polite unix - - n - - smtp turtle unix - - n - - smtp

Postmap and reload:

postmap /etc/postfix/transport service postfix reload

-------------

Ratelimit-policyd - MySQL

Installation

Recommended installation:

$ cd /opt/ $ git clone https://github.com/onlime/ratelimit-policyd.git ratelimit-policyd $ cd ratelimit-policyd $ chmod +x install.sh $ ./install.sh

Create the DB schema and user:

$ mysql -u root -p < mysql-schema.sql

GRANT USAGE ON *.* TO policyd@'localhost' IDENTIFIED BY '********'; GRANT SELECT, INSERT, UPDATE, DELETE ON policyd.* TO policyd@'localhost';

Adjust configuration options in daemon.pl:

### CONFIGURATION SECTIONmy @allowedhosts    = ('127.0.0.1', '10.0.0.1'); my $LOGFILE         = "/var/log/ratelimit-policyd.log"; my $PIDFILE         = "/var/run/ratelimit-policyd.pid"; my $SYSLOG_IDENT    = "ratelimit-policyd"; my $SYSLOG_LOGOPT   = "ndelay,pid"; my $SYSLOG_FACILITY = LOG_MAIL; chomp( my $vhost_dir = `pwd`); my $port            = 10032; my $listen_address  = '127.0.0.1'; # or '0.0.0.0'my $s_key_type      = 'email'; # domain or emailmy $dsn             = "DBI:mysql:policyd:127.0.0.1"; my $db_user         = 'policyd'; my $db_passwd       = '************'; my $db_table        = 'ratelimit'; my $db_quotacol     = 'quota'; my $db_tallycol     = 'used'; my $db_updatedcol   = 'updated'; my $db_expirycol    = 'expiry'; my $db_wherecol     = 'sender'; my $deltaconf       = 'daily'; # hourly|daily|weekly|monthlymy $defaultquota    = 1000; my $sql_getquota    = "SELECT $db_quotacol, $db_tallycol, $db_expirycol FROM $db_table WHERE $db_wherecol = ? AND $db_quotacol > 0"; my $sql_updatequota = "UPDATE $db_table SET $db_tallycol = $db_tallycol + ?, $db_updatedcol = NOW(), $db_expirycol = ? WHERE $db_wherecol = ?"; my $sql_updatereset = "UPDATE $db_table SET $db_tallycol = ?, $db_updatedcol = NOW(), $db_expirycol = ? WHERE $db_wherecol = ?"; my $sql_insertquota = "INSERT INTO $db_table ($db_wherecol, $db_quotacol, $db_tallycol, $db_expirycol) VALUES (?, ?, ?, ?)"; ### END OF CONFIGURATION SECTION

Take care of using a port higher than 1024 to run the script as non-root (our init script runs it as user "postfix").

In most cases, the default configuration should be fine. Just don't forget to paste your DB password in $db_password.

Now, start the daemon:

$ service ratelimit-policyd start

Testing

Check if the daemon is really running:

$ netstat -tl | grep 10032 tcp        0      0 localhost.localdo:10032 *:*                     LISTEN  $ cat /var/run/ratelimit-policyd.pid 30566  $ ps aux | grep daemon.pl postfix  30566  0.4  0.1 176264 19304 ?        Ssl  14:37   0:00 /opt/send_rate_policyd/daemon.pl  $ pstree -p | grep ratelimit init(1)-+-/opt/ratelimit-(11298)-+-{/opt/ratelimit-}(11300)         |                        |-{/opt/ratelimit-}(11301)         |                        |-{/opt/ratelimit-}(11302)         |                        |-{/opt/ratelimit-}(14834)         |                        |-{/opt/ratelimit-}(15001)         |                        |-{/opt/ratelimit-}(15027)         |                        |-{/opt/ratelimit-}(15058)         |                        `-{/opt/ratelimit-}(15065)

Print the cache content (in shared memory) with update statistics:

$ service ratelimit-policyd status Printing shm: Domain : Quota : Used : Expire Threads running: 6, Threads waiting: 2

Postfix Configuration

Modify the postfix data restriction class smtpd_data_restrictions like the following, /etc/postfix/main.cf:

smtpd_data_restrictions = check_policy_service inet:$IP:$PORT

sample configuration (using ratelimitpolicyd as alias as smtpd_data_restrictions does not allow any whitespace):

smtpd_restriction_classes = ratelimitpolicyd ratelimitpolicyd = check_policy_service inet:127.0.0.1:10032  smtpd_data_restrictions =         reject_unauth_pipelining,         ratelimitpolicyd,         permit

If you're sure that ratelimit-policyd is really running, restart Postfix:

$ service postfix restart

Logging

Detailed logging is written to ``/var/log/ratelimit-policyd.log```. In addition, the most important information including the counter status is written to syslog:

$ tail -f /var/log/ratelimit-policyd.log  Sat Jan 10 12:08:37 2015 Looking for demo@example.com Sat Jan 10 12:08:37 2015 07F452AC009F: client=4-3.2-1.cust.example.com[1.2.3.4], sasl_method=PLAIN, sasl_username=demo@example.com, recipient_count=1, curr_count=6/1000, status=UPDATE  $ grep ratelimit-policyd /var/log/syslog Jan 10 12:08:37 mx1 ratelimit-policyd[2552]: 07F452AC009F: client=4-3.2-1.cust.example.com[1.2.3.4], sasl_method=PLAIN, sasl_username=demo@example.com, recipient_count=1, curr_count=6/1000, status=UPDATE

Postfix send rate limit per user/domain

I needed to limit the number of emails sent by users through your Postfix server, and store message quota in RDMS systems (maybe you have multiple MX).

I tried policyd or other policy daemons for Postfix;  but they all miss support for SQL storage.

With this piece of code you can setup a send rate per users or sender domain on daily/weekly/monthly basis and store data in MySQL (PostgreSQL,…).

To work with mqdaemon you only need a mysql table described like this one:

CREATE TABLE  `emails` (`email` VARCHAR(65) NOT NULL,`messagequota` INT(10) UNSIGNED NOT NULL DEFAULT '0',`messagetally` INT(10) UNSIGNED NOT NULL DEFAULT '0',`timestamp` INT(10) UNSIGNED DEFAULT NULL,)

and setup configuration parameters (db_table, db_wherecol, db_messagequota, etc) inside the Perl script.

You must insert all rows for the emails you have to enforce! The script is configured to use a simple UPDATE.

Modify the postfix data restriction class “smtpd_data_restrictions” like the following:

To print the cache content with update statistics for username into log file just send a SIGHUP to the process PID using “kill -HUP $pid” or invoke the script with printshm paramenter (perl ./daemon.pl printshm).

To enforce per-domain quota set the search key ($s_key_type parameter) to “domain”.

Start the daemon with “# ./daemon.pl” and kill it with “# pkill daemon.pl”.

Take care of using a port higher than 1024 to run the script as non-root.

This daemon caches the quota in memory, so you don’t need to worry about I/O operations.

-----------------

smtpd_data_restrictions = check_policy_service inet:$IP:$PORT