On Mon, Sep 21, 2015 at 07:25:53AM +0100, Kianoosh Kashefi wrote:
> I use Postfix with Postfwd as policy service. and I want to limit all 
> outgoing messages with exceptions for several SASL users with HOLD verdict. 
> I'm new to postfwd so I need configuration example for rate-limiting with 
> HOLD verdict (for instance limit all users outgoing messages to 10 messages 
> per minute and HOLD messages exceeding that limit) also I need the same 
> configuration to apply only to certain SASL users again with HOLD verdict 
> (for example limit a certain user's outgoing messages to 100 message per 
> minute and HOLD messages exceeding that limit). I appreciate if you reply 
> with full configuration examples for these two cases. 

It can be done with the Accounting/Quota support of mtpolicyd:

https://www.mtpolicyd.org/getting-started.html#Mail::MtPolicyd::Cookbook::HowtoAccountingQuota

First you'll have to setup an SQL database and configure it in mtpolicyd:

  db_dsn="dbi:mysql:mail"
  db_user=mtpolicyd
  db_password=secret

Then configure the a VirtualHost with the accounting plugin to record mails 
sent based on
sasl_username:

<VirtualHost 12345>
  name="rate-limit"
  <Plugin AcctUser>
    module = "Accounting"
    fields = "sasl_username"
    time_pattern = "%Y-%m-%d %H:%M"
  </Plugin>
  # more plugins come here later...
</VirtualHost>

Then add a query to this policyd vhost in your postfix configuration:

  smtpd_end_of_data_restrictions = check_policy_service inet:127.0.0.1:12345

At this point mtpolicyd will create a table acct_sasl_username with the
first recieved mail and record accounting data in it.

To limit the rate add the following Quota plugin configuration:

  <Plugin QuotaIP>
    module = "Quota"
    field = "sasl_username"
    metric = "count"
    threshold = 10
    action = "hold"
    time_pattern = "%Y-%m-%d %H:%M"
  </Plugin>

This should limit the message count per sasl_username.

To add different limits per user you can use the per user configuration
features of mtpolicyd.

Create a database schema for it:

  CREATE TABLE `user_policy` (
    `id` int(11) NOT NULL auto_increment,
    `desc` VARCHAR(64) NOT NULL,
    `config` TEXT NOT NULL,
    PRIMARY KEY  (`id`)
  ) ENGINE=InnoDB;

  // configuration is expected as JSON format hash
  INSERT INTO user_policy VALUES(1, 'privileged user', '{"rate-limit":"100"}');

  CREATE TABLE `users` (
    `id` int(11) NOT NULL auto_increment,
    `sasl_username` VARCHAR(64) NOT NULL,
    `user_policy` int(11) NOT NULL,
    PRIMARY KEY  (`id`),
    KEY `user_policy` (`user_policy`),
    CONSTRAINT `users_ibfk_1` FOREIGN KEY (`user_policy`) REFERENCES 
`user_policy` (`id`)
  ) ENGINE=InnoDB;

  INSERT INTO users VALUES(NULL, 'kianoosh@saslauth', 1);

Add a query to retrieve the user configuration _before_ the Quota plugin:

  <Plugin UserConfiguration>
    module = "SqlUserConfig"
    sql_query = "SELECT p.config FROM user_policy p JOIN users u ON 
(u.relay_policy = p.id) WHERE u.sasl_username=?"
    field = "sasl_username"
  </Plugin>

That will retrieve the user configuration by the sasl_username.

Then edit the Quota plugin and add uc_threshold parameter:

  uc_threshold="rate-limit"

This will overwrite the threshold option if there is a value for
"rate-limit" defined in the current session.


In my option the time slice is a little bit small with 1 minute.
I would use a per hour or per day limit.

 Markus

-- 
Markus Benning, https://markusbenning.de/

Reply via email to