policyd-client

DESCRIPTION

policyd-client is a rudimentary tool to query a policy server from the command line. It will generate the instance and request fields all other fields must be specified on stdin and the request is completed by a blank line.

USAGE

  policyd-client [-?hhksv] [long options...]
        -h -? --usage --help  Prints this usage information.
        -h --host            host:port of a policyd
        -s --socket_path     path to a socket of a policyd
        -k --keepalive       use connection keepalive?
        -v --verbose         be verbose, print input/output to STDERR

EXAMPLE

  $ policyd-client -v -h localhost:12347
  client_address=212.178.212.218

  >> request=smtpd_access_policy
  >> instance=0.133885340838791
  >> client_address=212.178.212.218
  >>
  << action=reject IP is blacklisted
  <<
  reject IP is blddacklisted

mtpolicyd

NAME

mtpolicyd - a modular policy daemon for postfix

DESCRIPTION

mtpolicyd is a policy daemon for postfix access delegation.

It can be configured to accept connections on several ports from a postfix mta. For each port a VirtualHost can be configured and for each VirtualHost several Plugins can be configured.

For more info, mailing list, see: https://www.mtpolicyd.org

EXAMPLE

In postfix main.cf:

  smtpd_recipient_restrictions = check_policy_service inet:127.0.0.1:12345

In mtpolicyd.conf:

  # listen on port 12345 (multiple ports can be separated by ',')
  port="127.0.0.1:12345"

  # defined host for this port
  <VirtualHost 12345>
    name=example_vhost
    <Plugin spamhaus_bl>
      module="RBL"
      domain="sbl.spamhaus.org"
      mode=reject
    </Plugin>
  </VirtualHost>

This check will execute a simple RBL lookup against dbl.spamhaus.org.

COMMANDLINE OPTIONS

  mtpolicyd
    [-h|--help]
    [-c|--config=<file>]
    [-f|--foreground]
    [-l|--loglevel=<level>]
    [-d|--dump_vhosts]
  • -h --help

    Show available command line options.

  • -c --config=<file> (default: /etc/mtpolicyd/mtpolicyd.conf)

    Specifiy the path to the configuration file.

  • -f --foreground

    Do not fork to background and log to stdout.

  • -l --loglevel=<level>

    Overwrite the log level specified in the configuration with the specified level.

  • -d --dump_vhosts

    Parse VirtualHosts configuration, print it to stdout and exit.

CONFIGURATION FILE

The configuration file is implementend with Config::General which allows apache style configuration files.

mtpolicyd accepts global configuration parameters in the style:

  key=value

Comments begin with '#'.

VirtualHosts must be configured with VirtualHost sections:

  <VirtualHost <portnumber>>
    name=<name of the vhost>
  </VirtualHost>

Each VirtualHost should contain at least on Plugin.

  <VirtualHost <portnumber>>
    name=<name of the vhost>
    <Plugin <name of check> >
      module = "<name of plugin>"
      # plugin options
      key=value
    </Plugin>
  </VirtualHost>

For individual plugin configuration options see the man page of the plugin:

  Mail::MtPolicyd::Plugin::<name of plugin>

GLOBAL CONFIGURATION OPTIONS

  • user

    user id to run as

  • group

    group id to run as

  • pid_file

    location of the pid file

  • log_level

    Verbosity of logging: 0=>'err', 1=>'warning', 2=>'notice', 3=>'info', 4=>'debug'

  • host

    ip address to bind to.

  • port

    comma separated list of ports to listen on.

  • min_servers (default: 4)

    The minimum number of client processes to start.

  • min_spare_servers (default: 4)

    The minimum number of client processes that should hanging around idle and wait for new connections.

    If the number of free processes is below this threshold mtpolicyd will start to create new child processes.

  • max_spare_servers (default: 12)

    The maximum number of idle processes.

    If the number of idle processes is over this threshold mtpolicyd will start to shutdown child processes.

  • max_servers (default: 25)

    The absolute maximum number of child processes to start.

  • max_requests (default: 1000)
  • max_keepalive (default: 0)

    Number of requests after that mtpolicyd closes the connection or no limit if set to zero.

    Should be the same value as smtpd_policy_service_reuse_count_limit (postfix >2.12) in postfix/smtpd configuration.

  • vhost_by_policy_context (default: 0)

    Select VirtualHost by 'policy_context' request field.

    The policy_context will be matched against the 'name' field of the VirtualHost.

    For example in postfix main.cf use advanced syntax:

      check_policy_service { inet:localhost:12345, policy_context=reputation }
      ...
      check_policy_service { inet:localhost:12345, policy_context=accounting }

    In mtpolicyd.conf:

      port="127.0.0.1:12345" # only 1 port
      vhost_by_policy_context=1
      <VirtualHost 12345>
        name=reputation
        ... plugins ...
      </VirtualHost>
    
      <VirtualHost 12345>
        name=accounting
        ... plugins ...
      </VirtualHost>

    The policy_context feature will be available in postfix 3.1 and later.

    If you just need small differentiations consider using the Mail::MtPolicyd::Plugin::Condition plugin to match against plugin_context field.

  • request_timeout

    Maximum total time for one request.

CONFIGURE CONNECTIONS

mtpolicyd has a global per process connection pool.

Connections could be registered within the connection pool using a <Connection> block within the configuration. You must at least specify the name of the connection and the module for the connection type.

  <Connection [name of connection]>
    module = "[connection type]"
    # ... addditional parameters
  </Connection>

Connection modules may require additional parameters.

Currently supported connection modules:

  • Sql

    Perl DBI based connections for SQL databases.

    Mail::MtPolicyd::Connection::Sql

  • Memcached

    Connection to a memcached server/cluster.

    Mail::MtPolicyd::Connection::Memcached

  • Ldap

    Connection to an LDAP directory server.

    Mail::MtPolicyd::Connection::Ldap

SESSION MANAGEMENT

mtpolicyd implements session managemend to cache data across different checks for requests with the same instance id.

mtpolicy is able to generate a session for each mail passed to it and store it within the session cache. The attached session information will be available to all following plugins across child processes, virtual hosts and ports.

Plugins will use this session information to cache lookup etc. across multiple requests for the same mail. Postfix will send a query for each recipient and for each configured check_policy_service call.

To enable the SessionCache specify a <SessionCache> block within your configuration:

  <SessionCache>
    module = "Memcached"
    expire = "300"
    lock_wait=50
    lock_max_retry=50
    lock_timeout=10
  </SessionCache>

The example requires that a connection of type "Memcached" and the name "memcached" is configured within the connection pool. For details read Mail::MtPolicyd::SessionCache::Memcached.

As of version 2.00 it is possible to implement different session caches.

Currently there are 2 session cache modules:

  • Mail::MtPolicyd::SessionCache::Memcached
  • Mail::MtPolicyd::SessionCache::Redis

PROCESSING OF REQUEST

The policy daemon will process all plugins in the order they appear in the configuration file. It will stop as soon as a plugin returns an action and will return this action to the MTA.

SCORING

Most plugins can be configured to not return an action if the performed check matched.

For example the RBL module could be set to passive mode and instead a score could be applied to the request:

  <Plugin spamhaus>
    module = "RBL"
    mode = "passive"
    domain="zen.spamhaus.org"
    score=5
  </Plugin>

Check the documentation of the plugin for certain score/mode parameters. Plugin may provide more than one mode/score parameters if the do several checks.

Now if you configure more than one RBL check the score will add up. Later an action can be taken based on the score. The ScoreAction plugin will return an action based on the score and the AddScoreHeader plugin will prepend the score as a header to the mail:

  <Plugin ScoreReject>
    module = "ScoreAction"
    threshold = 15
    action = "reject sender ip %IP% is blocked (score=%SCORE%%SCORE_DETAIL%)"
  </Plugin>
  <Plugin ScoreTag>
    module = "AddScoreHeader"
    spam_score=5
  </Plugin>

UPGRADING

FROM 1.x to 2.x

With mtpolicyd 2.x configuration of connections and session cache has been changed.

Database Connections

In mtpolicyd 2.00 the connections defined globaly in the configuration file have been replaced by a dynamic connection pool.

The global options db_* ldap_* and memcached_* have been removed.

Instead connections are registred within a connection pool.

You can define them using <Connection> blocks:

  <Connection myconn>
    module = "<adapter>"
    # parameter = "value"
    # ...
  </Connection>

In mtpolicyd 1.x:

  db_dsn=DBI:mysql:mtpolicyd
  db_user=mtpolicyd
  db_password=secret

In mtpolicyd 2.x:

  <Connection db>
     dsn = "DBI:mysql:mtpolicyd"
     user = "mtpolicyd"
     password = "secret"
  </Connection>

All SQL modules will by default use the connection registred as "db".

See modules in Mail::MtPolicyd::Connection::* for available connection adapters.

Session Cache

Starting with mtpolicyd 2.x it is possible to use other session caches then memcached.

The global session_* parameters have been removed.

Instead the session cache is defined by a <SessionCache> block:

  <SessionCache>
    module = "<module>"
    # parameter = "value"
    # ...
  </SessionCache>

A memcached session cache in mtpolicyd v1.x:

  memcached_servers="127.0.0.1:11211"

  session_lock_wait=50
  session_lock_max_retry=50
  session_lock_timeout=10

In mtpolicyd 2.x:

  <Connection memcached>
    servers = "127.0.0.1:11211"
  </Connection>

  <SessionCache>
    module = "Memcached"
    # defaults to connection "memcached"
    # memcached = "memcached"
    lock_wait = "50"
    lock_max_retry = "50"
    lock_timeout = "10"
  </SessionCache>

If no <SessionCache> is defined it will default to the dummy session cache module "None".

See modules in Mail::MtPolicyd::SessionCache::* for available session cache modules.

Plugin: SaAwlAction

DESCRIPTION

This plugin will execute an action or score based on a previous lookup done with SaAwlLookup plugin.

PARAMETERS

  • result_from (required)

    Take the AWL information from the result of this plugin.

    The plugin in must be executed before this plugin.

  • (uc_)enabled (default: on)

    Enable/disable this plugin.

  • (uc_)mode (default: reject)

    If set to 'passive' no action will be returned.

  • reject_message (default: 'sender address/ip has bad reputation')

    Could be used to specify an custom reject message.

  • score (default: empty)

    A score to apply to the message.

  • score_factor (default: empty)

    A factor to apply the SA score to the message.

    Do not configure a score if you want to use the factor.

  • min_count (default: 10)

    The minimum count of mails/scores spamassassin must have done on this sender/ip before the AWL entry is used.

    If the count in AWLs auto-whitelist table is below this count the test will be skipped.

  • threshold (default: 5)

    At this threshold the action or score will be applied.

  • match (default: gt)

    The default is to match values greater("gt") than the threshold.

    When configured with 'lt' AWL scores less than the threshold will be matched.

EXAMPLE

Check that AWL is active in your SA/amavis configuration:

  loadplugin Mail::SpamAssassin::Plugin::AWL
  use_auto_whitelist 1

Make sure that mtpolicyd has permissions to read the auto-whitelist db:

  $ usermod -G amavis mtpolicyd
  $ chmod g+rx /var/lib/amavis/.spamassassin
  $ chmod g+r /var/lib/amavis/.spamassassin/auto-whitelist

Make sure it stays like this when its recreated in your SA local.cf:

  auto_whitelist_file_mode 0770

Net::Server does not automatically set supplementary groups. You have to do that in mtpolicyd.conf:

  group="mtpolicyd amavis"

Permissions may be different on your system.

To check that mtpolicyd can access the file try:

  $ sudo -u mtpolicyd -- head -n0 /var/lib/amavis/.spamassassin/auto-whitelist

Now use it in mtpolicyd.conf:

  <Plugin amavis-reputation>
    module = "SaAwlLookup"
    db_file = "/var/lib/amavis/.spamassassin/auto-whitelist"
  </Plugin>

For whitelisting you may configure it like:

  <Plugin awl-whitelist>
    module = "SaAwlAction"
    result_from = "amavis-reputation"
    mode = "accept"
    match = "lt"
    threshold = "0"
  </Plugin>

Or apply a score based for bad AWL reputation (score > 5):

  <Plugin awl-score-bad>
    module = "SaAwlAction"
    result_from = "amavis-reputation"
    mode = "passive"
    match = "gt"
    threshold = 6
    score = 5
  </Plugin>

Or apply the score value from AWL with an factor:

  <Plugin awl-score-bad>
    module = "SaAwlAction"
    result_from = "amavis-reputation"
    mode = "passive"
    match = "gt"
    threshold = 5
    score_factor = 0.5
  </Plugin>

If the score in AWL is >5 it will apply the score with an factor of 0.5. When the score in AWL is 8 it will apply a score of 4.

Or just reject all mail with a bad reputation:

  <Plugin awl-reject>
    module = "SaAwlAction"
    result_from = "amavis-reputation"
    mode = "reject"
    match = "gt"
    threshold = 5
    reject_message = "bye bye..."
  </Plugin>

Troubleshooting

Check content of spamassassin AWL auto-whitelist

To check the content of the auto-whitelist database use the sa-awl command:

  $ sa-awl /var/lib/amavis/.spamassassin/auto-whitelist | grep <user>

SEE ALSO

Plugin: SaAwlLookup

DESCRIPTION

This plugin queries the auto_whitelist database used by spamassassins AWL plugin for the reputation of sender ip/address combination.

Based on the AWL score a score or action in mtpolicyd can be applied in combination with the SaAwlAction plugin.

PARAMETERS

  • db_file (default: /var/lib/amavis/.spamassassin/auto-whitelist)

    The path to the auto-whitelist database file.

EXAMPLE

To read reputation from amavis/spamassassin AWL use:

  <Plugin amavis-awl>
    module = "SaAwlLookup"
    db_file = "/var/lib/amamvis/.spamassassin/auto-whitelist"
  </Plugin>

The location of auto-whitelist may be different on your system. Make sure mtpolicyd is allowed to read the db_file.

Plugin: AddScoreHeader

DESCRIPTION

Adds an header with the current score and score details to the mail.

PARAMETERS

  • (uc_)spam_score (default: 5)

    If the score is higher than this value it'll be tagged as 'YES'. Otherwise 'NO'.

  • score_field (default: score)

    Specifies the name of the field the score is stored in. Could be set if you need multiple scores.

  • header_name (default: X-MtScore)

    The name of the header to set.

EXAMPLE

  <Plugin add-score-header>
    module = "AddScoreHeader"
    # score_field = "score"
    # header_name = "X-MtScore"
    spam_score = 5
  </Plugin>

Will return an action like:

  X-MtScore: YES score=7.5 [CTIPREP_TEMP=2.5, spamhaus-rbl=5]

Plugin: SqlList

SYNOPSIS

  <Plugin whitelist>
    module="SqlList"
    sql_query="SELECT client_ip FROM whitelist WHERE client_ip=?"
    match_action=dunno
  </Plugin>

  <Plugin blacklist>
    module="SqlList"
    sql_query="SELECT client_ip FROM blacklist WHERE client_ip=?"
    match_action="reject you are blacklisted!"
  </Plugin>

DESCRIPTION

Plugin checks the client_address against a SQL table.

Depending on wether a supplied SQL query matched actions can be taken.

PARAMETERS

The module takes the following parameters:

  • (uc_)enabled (default: "on")

    Could be set to 'off' to deactivate check. Could be used to activate/deactivate check per user.

  • sql_query (default: "SELECT client_ip FROM whitelist WHERE client_ip=INET_ATON(?)")

    Prepared SQL statement to use for checking an IP address.

    ? will be replaced by the IP address.

    The module will match if the statement returns one or more rows.

By default the plugin will do nothing. One of the following actions should be specified:

  • match_action (default: empty)

    If given this action will be returned to the MTA if the SQL query matched.

  • not_match_action (default: empty)

    If given this action will be returned to the MTA if the SQL query DID NOT matched.

  • score (default: empty)

    If given this score will be applied to the session.

EXAMPLE WITH A MYSQL TABLE

You may use the following table for storing ipv4 addresses in MySQL:

  CREATE TABLE `whitelist` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `client_ip` INT UNSIGNED NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `client_ip` (`client_ip`)
  ) ENGINE=MyISAM  DEFAULT CHARSET=latin1

  INSERT INTO whitelist VALUES(NULL, INET_ATON('127.0.0.1'));

And use it as a whitelist in mtpolicyd:

  <VirtualHost 12345>
    name="reputation"
    <Plugin whitelist>
      module="SqlList"
      sql_query="SELECT client_ip FROM whitelist WHERE client_ip=INET_ATON(?)"
      match_action="dunno"
    </Plugin>
    <Plugin trigger-greylisting>
    ...
  </VirtualHost>

Plugin: SPF

DESCRIPTION

This plugin applies Sender Policy Framework(SPF) checks.

Checks are implemented using the Mail::SPF perl module.

Actions based on the SPF result can be applied for:

  • pass (pass_mode, default: passive)
  • softfail (softfail_mode, default: passive)
  • fail (fail_mode, default: reject)

For status 'neutral' no action or score is applied.

PARAMETERS

  • (uc_)enabled (default: on)

    Enable/disable the plugin.

  • (uc_)pass_mode (default: passive)

    How to behave if the SPF checks passed successfully:

    • passive

      Just apply score. Do not return an action.

    • accept, dunno

      Will return an 'dunno' action.

  • pass_score (default: empty)

    Score to apply when the sender has been successfully checked against SPF.

  • (uc_)softfail_mode (default: passive)

    How to behave if the SPF checks returned a softfail status.

    • passive

      Just apply score. Do not return an action.

    • accept, dunno

      Will return an 'dunno' action.

    • reject

      Return an reject action.

  • softfail_score (default: empty)

    Score to apply when the SPF check returns an softfail status.

  • (uc_)fail_mode (default: reject)
    • reject

      Return an reject action.

    • passive

      Just apply score and do not return an action.

  • reject_message (default: )

    If fail_mode is set to 'reject' this message is used in the reject.

    The following pattern will be replaced in the string:

    • %LOCAL_EXPL%

      Will be replaced with a (local) explanation of the check result.

    • %AUTH_EXPL%

      Will be replaced with a URL to the explanation of the result.

      This URL could be configured with 'default_authority_explanation'.

  • fail_score (default: empty)

    Score to apply if the sender failed the SPF checks.

  • default_authority_explanation (default: See http://www.%{d}/why/id=%{S};ip=%{I};r=%{R})

    String to return as an URL pointing to an explanation of the SPF check result.

    See Mail::SPF::Server for details.

  • hostname (default: empty)

    An hostname to show in the default_authority_explanation as generating server.

  • whitelist (default: '')

    A comma separated list of IP addresses to skip.

  • check_helo (default: "on")

    Set to 'off' to disable SPF check on helo.

EXAMPLE

  <Plugin spf>
    module = "SPF"
    pass_mode = passive
    pass_score = -10
    fail_mode = reject
    #fail_score = 10
  </Plugin>

SEE ALSO

Mail::SPF, OpenSPF www.openspf.org/, RFC 7209 https://tools.ietf.org/html/rfc7208

Plugin: PostfixMap

SYNOPSIS

  <Plugin whitelist>
    module="PostfixMap"
    db_file="/etc/postfix/whitelist.db"
    match_action=dunno
  </Plugin>

  <Plugin blacklist>
    moduel="PostfixMap"
    db_file="/etc/postfix/blacklist.db"
    match_action="reject you are blacklisted!"
  </Plugin>

DESCRIPTION

Plugin checks the client_address against a postfix hash table.

It will only check if the IP address matches the list. 'OK' or a numerical value will be interpreted as a 'true' value. All other actions or values will be treaded as 'false'.

EXAMPLE TABLE

/etc/postfix/whitelist:

  123.123.123.123 OK
  123.123.122 OK
  123.12 OK
  fe80::250:56ff:fe85:56f5 OK
  fe80::250:56ff:fe83 OK

generate whitelist.db:

  $ postmap whitelist

PARAMETERS

The module takes the following parameters:

  • (uc_)enabled (default: "on")

    Could be set to 'off' to deactivate check. Could be used to activate/deactivate check per user.

By default the plugin will do nothing. One of the following actions should be specified:

  • match_action (default: empty)

    If given this action will be returned to the MTA if the SQL query matched.

  • not_match_action (default: empty)

    If given this action will be returned to the MTA if the SQL query DID NOT matched.

  • score (default: empty)

    If given this score will be applied to the session.

Plugin: SetField

DESCRIPTION

This plugin can be used to set key/values within the session.

EXAMPLE

  <Plugin set-scanned>
    module = "SetField"
    key=mail-is-scanned
    value=1
  </Plugin>

Plugin: Condition

DESCRIPTION

Will return an action, score or execute futher plugins if the specified condition matched.

PARAMETERS

  • key (required)

    The name of the variable to check.

    Syntax is

      (<scope>:)?<variable-name>

    If no scope is give it defaults to request.

    Possible scopes are:

    • session, s

      Session variables.

    • request, r

      Request attribute variables.

    Examples:

      session:user_policy
      s:user_policy
    
      request:queue_id
      r:queue_id
      queue_id

At least one of the following parameters should be given or your condition will never match:

  • match (default: empty)

    Simple string equal match.

  • re_match (default: empty)

    Match content of the session variable against an regex.

  • lt_match (default: empty)

    Match if numerical less than.

  • gt_match (default: empty)

    Match if numerical greater than.

  • invert (default: 0)

    If set to 1 the logic will be inverted.

Finally an action must be specified.

First the score will be applied the the action will be executed or if specified additional plugins will be executed.

  • action (default: empty)

    The action to return when the condition matched.

  • score (default: empty)

    The score to add if the condition matched.

  • Plugin (default: empty)

    Execute this plugins when the condition matched.

EXAMPLE: use of postfix policy_context

The policy_context of postfix could be used to trigger checks in mtpolicyd.

To activate additional checks in mtpolicyd from within postfix use may use a configuration in postfix main.cf like:

  # check, no additional checks
  check_policy_service inet:localhost:12345
  ...
  # check with additional checks!
  check_policy_service { inet:localhost:12345, policy_context=strict_checks }

In mtpolicyd.conf:

  <Plugin if-strict-checks>
    module = "Condition"
    key = "policy_context"
    match = "strict_checks"

    <Plugin strict-check>
      # ...
    </Plugin>
    # more checks ...
  </Plugin>

The policy_context feature will be available in postfix 3.1 and later.

If you need completely different checks consider using the vhost_by_policy_context (mtpolicyd) option with different virtual hosts.

EXAMPLE: execute postgrey action in postfix

If the session variable "greylisting" is "on" return the postfix action "postgrey":

  <Plugin trigger-greylisting>
    module = "Condition"
    key = "greylisting"
    match = "on"
    action = "postgrey"
  </Plugin>

The variable may be set by a UserConfig module like SqlUserConfig.

The postgrey action in postfix may look like:

  smtpd_restriction_classes = postgrey
  postgrey = check_policy_service inet:127.0.0.1:11023

Plugin: Accounting

DESCRIPTION

This plugin can be used to do accounting based on request fields.

SYNOPSIS

  <Plugin acct-clients>
    module = "Accounting"
    # per ip and user
    fields = "client_address,sasl_username"
    # statistics per month
    time_pattern = "%Y-%m"
    table_prefix = "acct_"
  </Plugin>

This will create a table acct_client_address and a table acct_sasl_username.

If a request is received containing the field the plugin will update the row in the fields table. The key is the fields value(ip or username) and the time string build from the time_pattern.

For each key the following counters are stored:

  * count
  * count_rcpt (count per recipient)
  * size
  * size_rcpt  (size * recipients)

The resulting tables will look like:

  mysql> select * from acct_client_address;
  +----+--------------+---------+-------+------------+--------+-----------+
  | id | key          | time    | count | count_rcpt | size   | size_rcpt |
  +----+--------------+---------+-------+------------+--------+-----------+
  |  1 | 192.168.0.1  | 2014-12 |    11 |         11 | 147081 |    147081 |
  |  2 | 192.168.1.1  | 2014-12 |     1 |          1 |  13371 |     13371 |
  | 12 | 192.168.2.1  | 2014-12 |    10 |        100 | 133710 |   1337100 |
  ...

PARAMETERS

The module takes the following parameters:

  • (uc_)enabled (default: on)

    Enable/disable this check.

  • fields (required)

    A comma separated list of fields used for accounting.

    For each field a table will be created.

    For a list of available fields see postfix documentation:

    http://www.postfix.org/SMTPD_POLICY_README.html

  • time_pattern (default: "%Y-%m")

    A format string for building the time key used to store counters.

    Default is to build counters on a monthly base.

    For example use:

      * "%Y-%W" for weekly
      * "%Y-%m-%d" for daily

    See "man date" for format string sequences.

  • table_prefix (default: "acct_")

    A prefix to add to every table.

    The table name will be the prefix + field_name.

Plugin: Proxy

DESCRIPTION

This module forwards the request to another policy daemon.

PARAMETERS

  • host (default: empty)

    The <host>:<port> of the target policy daemon.

  • socket_path (default: empty)

    The path to the socket of the target policy daemon.

  • keepalive (default: 0)

    Keep connection open across requests.

EXAMPLE

  <Plugin ask-postgrey>
    module = "Proxy"
    host="localhost:10023"
  </Plugin>

Plugin: GeoIPAction

DESCRIPTION

This plugin will execute an action or score based on a previous lookup done with GeoIPLookup plugin.

PARAMETERS

  • result_from (required)

    Take the GeoIP information from the result of this plugin.

    The plugin in must be executed before this plugin.

  • (uc_)enabled (default: on)

    Enable/disable this plugin.

  • country_codes (required)

    A comma separated list of 2 letter country codes to match.

  • (uc_)mode (default: reject)

    If set to 'passive' no action will be returned.

  • reject_message (default: 'delivery from %CC% (%IP%) rejected)

    Could be used to specify an custom reject message.

  • score (default: empty)

    A score to apply to the message.

Plugin: GeoIPLookup

DESCRIPTION

This plugin queries a GeoIP for the country code of the client_address. The plugin is divided in this plugin which does the Lookup and the GeoIPAction plugin which can be used to take actions based on country code.

PARAMETERS

  • database (default: /usr/share/GeoIP/GeoIP.dat)

    The path to the geoip country database.

MAXMIND GEOIP COUNTRY DATABASE

On a debian system you can install the country database with the geoip-database package.

You also download it directly from Maxmind:

http://dev.maxmind.com/geoip/geoip2/geolite2/

(choose "GeoLite2 Country/DB")

Plugin: Fail2Ban

DESCRIPTION

This plugin can be used to block an ip with iptable thru the fail2ban daemon.

For more information abount fail2ban read:

http://www.fail2ban.org/

This plugin will directly talk to the daemon thru the unix domain socket and execute an banip command:

  set <JAIL> banip <IP>

PARAMETERS

  • socket (default: /var/run/fail2ban/fail2ban.sock)

    Path to the fail2ban unix socket.

    Make sure mtpolicyd is allowed to write to this socket!

  • jail (default: postfix)

    The jail in which the ip should be banned.

EXAMPLE

Execute a ban on all client-ips which send a mail with a score of >=15:

  <Plugin ScoreBan>
    module = "ScoreAction"
    threshold = 15
    <Plugin ban-ip>
      module = "Fail2Ban"
      socket = "/var/run/fail2ban/fail2ban.sock"
      jail = "postfix"
    </Plugin>
  </Plugin>

FAIL2BAN CONFIGURATION

To allow mtpolicyd to access fail2ban you must make sure fail2ban can write to the fail2ban unix socket.

  chgrp mtpolicyd /var/run/fail2ban/fail2ban.sock
  chmod g+rwx /var/run/fail2ban/fail2ban.sock

You may want to add this to the fail2ban startup script.

You may want to use the predefined postfix jail. To activate it create /etc/fail2ban/jail.local and enable the postfix fail by setting enabled=true.

  [postfix]
  enabled = true

Plugin: Honeypot

DESCRIPTION

The Honeypot plugin creates an honeypot to trap IPs sending to unused recipient addresses.

The plugin requires that you define unused recipient addresses as honeypots. These addresses can be specified by the recipients and recipients_re parameters.

Each time an IP tries to send an mail to one of these honeypots the message will be reject if mode is 'reject' and an scoring is applied. The IP is also added to a temporary IP blacklist till an timeout is reached (parameter expire). All IPs on this blacklist will also be rejected if mode is 'reject' and scoring is applied.

EXAMPLE

  <Plugin honeypot>
    module = "Honeypot"
    recipients = "bob@company.com,joe@company.com"
    recipients_re = "^(tic|tric|trac)@(gmail|googlemail)\.de$"
  </Plugin>

PARAMETERS

  • (uc_)enabled (default: on)

    Enable/disable this check.

  • score (default: empty)

    Apply an score to this message if it is send to an honeypot address or it has been added to the honeypot before by sending an mail to an honeypot.

  • mode (default: reject)

    The default is to return an reject.

    Change to 'passive' if you just want scoring.

  • recipients (default: '')

    A comma separated list of recipients to use as honeypots.

  • recipients_re (default: '')

    A comma separated list of regular expression to match against the recipient to use them as honeypots.

  • reject_message (default: 'trapped by honeypod')

    A string to return with the reject action.

  • expire (default: 7200 (2h))

    Time in seconds till the client_ip is removed from the honeypot.

  • Plugin (default: empty)

    Execute this plugins when the condition matched.

Plugin: Action

DESCRIPTION

This plugin just returns the specified string as action.

PARAMETERS

  • action (required)

    A string with the action to return.

EXAMPLE

  <Plugin reject-all>
    module = "action"
    # any postfix action will do
    action=reject no reason
  </Plugin>

Plugin: SqlUserConfig

DESCRIPTION

This plugin will retrieve a JSON string from an SQL database and will merge the data structure into the current session.

This could be used to retrieve configuration values for users from a database.

PARAMETERS

  • sql_query (default: SELECT config FROM user_config WHERE address=?)

    The SQL query to retrieve the JSON configuration string.

    The content of the first row/column is used.

  • field (default: recipient)

    The request field used in the sql query to retrieve the user configuration.

EXAMPLE USER SPECIFIC GREYLISTING

Create the following table in the SQL database:

 CREATE TABLE `user_config` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `address` varchar(255) DEFAULT NULL,
   `config` TEXT NOT NULL,
   PRIMARY KEY (`id`),
   UNIQUE KEY `address` (`address`)
 ) ENGINE=MyISAM  DEFAULT CHARSET=latin1

 INSERT INTO TABLE `user_config` VALUES( NULL, 'karlson@vomdach.de', '{"greylisting":"on"}' );

In mtpolicyd.conf:

  db_dsn="dbi:mysql:mail"
  db_user=mail
  db_password=password

  <Plugin user-config>
    module = "SqlUserConfig"
    sql_query = "SELECT config FROM user_config WHERE address=?"
  </Plugin>
  <Plugin greylist>
    enabled = "off" # off by default
    uc_enabled = "greylisting" # override with value of key 'greylisting' is set in session
    module = "Greylist"
    score = -5
    mode = "passive"
  </Plugin>

Plugin: LdapUserConfig

DESCRIPTION

This plugin could be used to retrieve session variables/user configuration from a LDAP server.

SYNOPSIS

  ldap_host="localhost"
  ldap_binddn="cn=readonly,dc=domain,dc=com"
  ldap_password="secret"

  <Plugin user_config>
    module="LdapUserConfig"
    basedn="ou=users,dc=domain,dc=com"
    filter="(mail=%s)"
    filter_field="sasl_username"
    config_fields="mailMessageLimit,mailSendExternal"
  </Plugin>

PARAMETERS

The LDAP connection must be configured in the global configuration section of mtpolicyd. See mtpolicyd.

  • basedn (default: '')

    The basedn to use for the search.

  • filter (required)

    The filter to use for the search.

    The pattern %s will be replaced with the content of filter_field.

  • filter_field (required)

    The content of this request field will be used to replace %s in the filter string.

  • config_fields (required)

    A comma seperated list of LDAP attributes to retrieve and copy into the current mtpolicyd session.

Plugin: Stress

DESCRIPTION

Will return an action or execute futher plugins if postfix signals stress.

See postfix STRESS_README.

PARAMETERS

An action must be specified:

  • action (default: empty)

    The action to return when under stress.

  • Plugin (default: empty)

    Execute this plugins when under stress.

EXAMPLE: defer clients when under stress

To defer clients under stress:

  <Plugin stress>
    module = "Stress"
    action = "defer please try again later"
  </Plugin>

This will return an defer action and execute no futher tests.

You may want to do some whitelisting for preferred clients before this action.

Plugin: ClearFields

DESCRIPTION

This plugin could be used to reset some session variables.

PARAMETERS

  • fields (default: empty)

    A comma separated list of session variables to unset.

  • fields_prefix (default: empty)

    A comma separated list of prefixes. All session variables with this prefixes will be unset.

EXAMPLE

  <Plugin cleanup>
    module = "ClearFields"
    fields = "spamhaus-rbl,spamhaus-dbl"
  </Plugin>

Will remove both fields from the session.

  <Plugin cleanup>
    module = "ClearFields"
    fields_prefix = "spamhaus-"
  </Plugin>

Will also remove both fields and everything else starting with "spamhaus-" from the session.

Plugin: Eval

DESCRIPTION

This plugin executes a list of configured plugins but will not return the action back to mtpolicyd. Instead it writes the output of the plugins to a variable within the session.

PARAMETERS

  • store_in (required)

    The name of the key in the session to store the result of the eval'ed checks.

  • Plugin (required)

    A list of checks to execute.

EXAMPLE

  <Plugin eval-spf>
    module = "Eval"
    # store result in spf_action
    store_in="spf_action"
    <Plugin proxy-spf>
      module = "Proxy"
      host = "localhost:10023"
    </Plugin>
  </Plugin>

Plugin: ScoreAction

DESCRIPTION

Returns a action based on the score.

PARAMETERS

  • threshold (required)

    If the score is higher than this value the action will be executed.

  • match (default: gt)

    If it should match if the score if >= or <= the threshold.

    Possible values: gt, lt

  • uc_threshold (default: undef)

    If set the value for threshold will be fetched from this user-config value if defined.

  • score_field (default: score)

    Specifies the name of the field the score is stored in. Could be set if you need multiple scores.

  • action (default: empty)

    The action to be executed.

    The following patterns in the string will be replaced:

      %IP%, %SCORE%, %SCORE_DETAIL%
  • Plugin (default: empty)

    Execute this plugins when the condition matched.

EXAMPLE

Reject everything with a score >= 15. and do greylisting for the remaining request with a score >=5.

  <Plugin ScoreReject>
    module = "ScoreAction"
    threshold = 15
    action = "reject sender ip %IP% is blocked (score=%SCORE%%SCORE_DETAIL%)"
  </Plugin>
  <Plugin ScoreGreylist>
    module = "ScoreAction"
    threshold = 5
    <Plugin greylist>
      module = "Greylist"
      score = -5
      mode = "passive"
    </Plugin>
  </Plugin>

Plugin: Quota

DESCRIPTION

This plugin can be used to do accounting based on request fields.

Example

  <Plugin quota-clients>
    module = "Quota"
    table_prefix = "acct_"

    # per month
    time_pattern = "%Y-%m"
    # per ip
    field = "client_address"
    # allow 1000 mails
    metric = "count"
    threshold = 1000
    action = "defer you exceeded your monthly limit, please insert coin"
  </Plugin>

Configuration

Parameters

The module takes the following parameters:

  • (uc_)enabled (default: on)

    Enable/disable this check.

  • (uc_)field (required)

    The field used for accounting/quota.

  • (uc_)metric (required)

    The metric on which the quota should be based.

    The Accounting module stores the following metrics:

    • count

      Number of mails recivied.

    • count_rcpt

      Number of mails recivied multiplied with number of recipients.

    • size

      Size of mails recivied.

    • size_rcpt

      Size of mails recivied multiplied with number of recipients.

  • time_pattern (default: "%Y-%m")

    A format string for building the time key used to store counters.

    Default is to build counters on a monthly base.

    For example use:

      * "%Y-%W" for weekly
      * "%Y-%m-%d" for daily

    See "man date" for format string sequences.

    You must use the same time_pattern as used in for the Accounting module.

  • threshold (required)

    The quota limit.

  • action (default: defer smtp traffic quota has been exceeded)

    The action to return when the quota limit has been reached.

  • table_prefix (default: "acct_")

    A prefix to add to every table.

    The table name will be the prefix + field_name.

Plugin: DBL

DESCRIPTION

Will check the sender, helo and reverse_client_name against an domain black list.

PARAMETERS

  • domain (required)

    The domain of the blacklist to query.

  • enabled (default: on)

    Set to 'off' to disable plugin.

    Possible values: on,off

  • uc_enabled (default: empty)

    If specified the give variable within the session will overwrite the value of 'enabled' if set.

  • (uc_)sender_mode (default: reject), (uc_)helo_name_mode (default: passive), (uc_)reverse_client_name_mode (default: reject)

    Should the plugin return an reject if the check matches (reject) or just add an score (passive).

    Possible values: reject, passive

  • sender_score (default: 5)
  • helo_name_score (default: 1)
  • reverse_client_name_score (default: 2.5)

    Add the given score if check matched.

  • score_field (default: score)

    Name of the session variable the score is stored in. Could be used if multiple scores are needed.

EXAMPLE

Only the sender and the reverse_client_name check will cause an action to be executed (mode). The helo check will only add an score.

  <Plugin sh_dbl>
    module = "RBL"
    #enabled = "on"
    uc_enabled = "spamhaus"
    domain="dbl.spamhaus.org"

    # do not reject based on helo
    #helo_name_mode=passive
    #helo_name_score=1
    #sender_mode=reject
    #sender_score=5
    #reverse_client_name_mode=reject
    #reverse_client_name_score=2.5
  </Plugin>

Plugin: Greylist

DESCRIPTION

This plugin implements a greylisting mechanism with an auto whitelist.

If a client connects it will return an defer and create a greylisting "ticket" for the combination of the address of the sender, the senders address and the recipient address. The ticket will be stored in memcached and will contain the time when the client was seen for the first time. The ticket will expire after the max_retry_wait timeout.

The client will be defered until the min_retry_wait timeout has been reached. Only in the time between the min_retry_wait and max_retry_wait the request will pass the greylisting test.

When the auto-whitelist is enabled (default) a record for every client which passes the greylisting test will be stored in the autowl_table. The table is based on the combination of the sender domain and client_address. If a client passed the test at least autowl_threshold (default 3) times the greylisting test will be skipped. Additional an last_seen timestamp is stored in the record and records which are older then the autowl_expire_days will expire.

Please note the greylisting is done on a triplet based on the

  client_address + sender + recipient

The auto-white list is based on the

  client_address + sender_domain

PARAMETERS

  • (uc_)enabled (default: on)

    Enable/disable this check.

  • score (default: empty)

    Apply an score to this message if it _passed_ the greylisting test. In most cases you want to assign a negative score. (eg. -10)

  • mode (default: passive)

    The default is to return no action if the client passed the greylisting test and continue.

    You can set this 'accept' or 'dunno' if you want skip further checks.

  • defer_message (default: defer greylisting is active)

    This action is returned to the MTA if a message is defered.

    If a client retries too fast the time left till min_retry_wait is reach will be appended to the string.

  • min_retry_wait (default: 300 (5m))

    A client will have to wait at least for this timeout. (in seconds)

  • max_retry_wait (default: 7200 (2h))

    A client must retry to deliver the message before this timeout. (in seconds)

  • use_autowl (default: 1)

    Could be used to disable the use of the auto-whitelist.

  • autowl_threshold (default: 3)

    How often a client/sender_domain pair must pass the check before it is whitelisted.

  • autowl_expire_days (default: 60)

    After how many days an auto-whitelist entry will expire if no client with this client/sender pair is seen.

  • autowl_table (default: autowl)

    The name of the table to use.

    The database handle specified in the global configuration will be used. (see man mtpolicyd)

  • query_autowl, create_ticket (default: 1)

    This options could be used to disable the creation of a new ticket or to query the autowl.

    This can be used to catch early retries at the begin of your configuration before more expensive checks a processes.

    Example:

      <Plugin greylist>
        module = "Greylist"
        score = -5
        mode = "passive"
        create_ticket = 0
        query_autowl = 0
      </Plugin>
      # ... a lot of RBL checks, etc...
      <Plugin ScoreGreylist>
        module = "ScoreAction"
        threshold = 5
        <Plugin greylist>
          module = "Greylist"
          score = -5
          mode = "passive"
        </Plugin>
      </Plugin>

    This will prevent early retries from running thru all checks.

Plugin: RBL

DESCRIPTION

This plugin queries a DNS black/white list.

PARAMETERS

  • domain (required)

    The domain of the blacklist to query.

  • (uc_)enabled (default: on)

    Enable/disable this check.

  • (uc_)mode (default: reject)
    • reject

      Reject the message. (reject)

    • accept

      Stop processing an accept this message. (dunno)

    • passive

      Only apply the score if one is given.

  • reject_message (default: delivery from %IP% rejected %INFO%)

    A pattern for the reject message if mode is set to 'reject'.

  • score (default: empty)

    Apply this score if the check matched.

EXAMPLE DNS BLACKLIST

  <Plugin sorbs.net>
    module = "RBL"
    mode = "passive"
    domain="dnsbl.sorbs.net"
    score = 5
  </Plugin>

EXAMPLE DNS WHITELIST

  <Plugin dnswl.org>
    module = "RBL"
    mode = "accept" # will stop here
    domain="list.dnswl.org"
  </Plugin>

Plugin: CtIpRep

DESCRIPTION

This plugin will query the Commtouch IP Reputation service (ctipd).

The used protocol is HTTP.

The services will return a status permfail or tempfail.

PARAMETERS

  • (uc_)enabled (default: on)

    Enable/disable the plugin.

  • url (default: http://localhost:8080/ctipd/iprep)

    The URL to access the ctipd daemon.

  • key (default: empty)

    If an authentication key is required by the ctipd.

  • reject_message (default: 550 delivery from %IP% is rejected. Check at http://www.commtouch.com/Site/Resources/Check_IP_Reputation.asp. Reference code: %REFID%)

    This parameter could be used to specifiy a custom reject message if message is rejected.

  • defer_message (default: 450 delivery from %IP% is deferred,repeatedly. Send again or check at http://www.commtouch.com/Site/Resources/Check_IP_Reputation.asp. Reference code: %REFID%)

    This parameter could be used to specifiy a custom message is a message is to be defered.

  • (uc_)permfail_mode, (uc_)tempfail_mode (default: reject, defer)

    Action to take when the service return permfail/tempfail status:

    • reject
    • defer
    • passive
  • permfail_score, tempfail_score (default: empty)

    Apply the specified score.

Plugin: RBLAction

DESCRIPTION

This plugin can be used when a more complex evaluation of an RBL result is needed that just match/not-match.

With this plugin you can take the same actions as with the RBL plugin, but it can match the result with a regular expression. This allows one to take action based on the category in combined blacklists.

PARAMETERS

  • result_from (required)

    Use the query result of this RBL check.

  • (uc_)enabled (default: on)

    Enable/disable this check.

  • (uc_)mode (default: reject)
    • reject

      Reject the message. (reject)

    • accept

      Stop processing an accept this message. (dunno)

    • passive

      Only apply the score if one is given.

  • re_match (required)

    An regular expression to check the RBL result.

  • reject_message (default: delivery from %IP% rejected %INFO%)

    A pattern for the reject message if mode is set to 'reject'.

  • score (default: empty)

    Apply this score if the check matched.

EXAMPLE

  <Plugin spamhaus-rbl>
    module = "RBL"
    mode = "passive"
    domain="zen.spamhaus.org"
  </Plugin>
  <Plugin spamhaus-rbl-sbl>
    module = "RBLAction"
    result_from = "spamhaus-rbl"
    mode = "passive"
    re_match = "^127\.0\.0\.[23]$"
    score = 5
  </Plugin>
  <Plugin spamhaus-rbl-xbl>
    module = "RBLAction"
    result_from = "spamhaus-rbl"
    mode = "passive"
    re_match = "^127\.0\.0\.[4-7]$"
    score = 5
  </Plugin>
  <Plugin spamhaus-rbl-pbl>
    module = "RBLAction"
    result_from = "spamhaus-rbl"
    mode = "passive"
    re_match = "^127\.0\.0\.1[01]$"
    score = 3
  </Plugin>

Plugin: SMTPVerify

DESCRIPTION

This plugin can be used to do remote SMTP verification of addresses.

Example

To check if the recipient exists on a internal relay and mailbox is able to recieve a message of this size:

  <Plugin smtp-rcpt-check>
    module = "SMTPVerify"
    
    host = "mail.company.internal"
    sender_field = "sender"
    recipient_field = "recipient"
    # send SIZE to check quota
    size_field = "size"

    temp_fail_action = "defer %MSG%"
    perm_fail_action = "reject %MSG%"
  </Plugin>

Do some very strict checks on sender address:

  <Plugin sender-sender-check>
    module = "SMTPVerify"

    # use a verifiable address in MAIL FROM:
    sender = "horst@mydomain.tld"
    recipient_field = "sender"
    no_starttls_action = "reject sender address does not support STARTTLS"
    temp_fail_action = "defer sender address failed verification: %MSG%"
    perm_fail_action = "reject sender address does not accept mail: %MSG%"
  </Plugin>

Or do advanced checking of sender address and apply a score:

  <Plugin sender-sender-check>
    module = "SMTPVerify"

    # use a verifiable address in MAIL FROM:
    sender = "horst@mydomain.tld"
    recipient_field = "sender"
    check_tlsa = "on"
    check_openpgp = "on"

    temp_fail_score = "1"
    perm_fail_score = "3"

    has_starttls_score = "-1"
    no_starttls_score = "5"
    has_tlsa_score = "-3"
    has_openpgp_score = "-3"
  </Plugin>

Based on the score you can later apply greylisting or other actions.

Configuration

Parameters

The module takes the following parameters:

  • (uc_)enabled (default: on)

    Enable/disable this check.

  • host (default: empty)

    If defined this host will be used for checks instead of a MX.

  • port (default: 25)

    Port to use for connection.

  • check_tlsa (default: off)

    Set to 'on' to enable check if an TLSA record for the MX exists.

    This requires that your DNS resolver returnes the AD flag for DNSSEC secured records.

  • check_openpgp (default: off)

    Set to 'on' to enable check if an OPENPGPKEY records for the recipients exists.

  • sender_field (default: recipient)

    Field to take the MAIL FROM address from.

  • sender (default: empty)

    If set use this fixed sender in MAIL FROM instead of sender_field.

  • recipient_field (default: sender)

    Field to take the RCPT TO address from.

  • size_field (default: size)

    Field to take the message SIZE from.

  • perm_fail_action (default: empty)

    Action to return if the remote server returned an permanent error for this recipient.

    The string "%MSG%" will be replaced by the smtp message:

      perm_fail_action = "reject %MSG%"
  • temp_fail_action (default: empty)

    Like perm_fail_action but this message is returned when an temporary error is returned by the remote smtp server.

      temp_fail_action = "defer %MSG%"
  • perm_fail_score (default: empty)

    Score to apply when a permanent error is returned for this recipient.

  • temp_fail_score (default: empty)

    Score to apply when a temporary error is returned for this recipient.

  • has_starttls_score (default: emtpy)
  • no_starttls_score (default: emtpy)

    Score to apply when the smtp server of the recipient announces support for STARTTLS extension.

  • has_tlsa_score (default: empty)
  • no_tlsa_score (default: empty)

    Score to apply when there is a TLSA or no TLSA record for the remote SMTP server.

  • has_openpgp_score (default: empty)
  • no_openpgp_score (default: empty)

    Score to apply when a OPENPGPKEY record for the recpient exists or not exists.