# POSTLICYD configuration # # Postlicyd configuration contains: # - a set of filter definition # - the entry point in the filters for each smtp states # # The configuration format use 2 types of data: # Token: [[:alpha:]]([[:alnum:]_]*) # String: string format is a bit more complex. It can be one of the two following # format: # - C-like strings "[^\n\r]*". In this kind of string, the \ character is used to # escape any character \c = c (\n = n, \\ = \, ...). This format allow non-ascii # strings and string concatenation " abcd " "ef" = " abcd ef". # - ASCII-only strings can be written without double-quotes. They can be splitted # into several lines using shell-like escaping of EOL. A string begins and ends on # on a non-blank character. This king of string can not contain semi-colons. # eg: # The following format are equivalent: # (1) this is a str\ # (1) ing # # (2) "this is a string" # # (3) "this " "is a " # (3) "string" # # Most of the configuration use a format: # Token = String ; # # When not in a string, spaces and line breaks are ignored. You can use comments # everywhere out of a string. It starts with a '#' character and ends at the end of the # line. Comments are strictly equivalents to white spaces. # FILTER DEFINITION # # A definition of a filter contains: # - the name of the filter. This name MUST be uniq (non-uniq names can lead to undefined # behaviour) # - a type # - a list of type-specific parameters # - a list of hooks (on_hookname) # # Format: # A filter look likes that: # # filter_name { # type = type_name; # param1 = parameter value 1; # ... # on_hook1 = action1; # on_hook2 = action2; # ... # } # # Hooks: # A filter can returns different values. Each return value is given a name. The # configuration associates an action to run to a return value name. # # A hook action has the format: (counter:id:incr:)?(filter_name|postfix:ACTION) # # The action can contains the reference to a counter to update. This counters are "message"-wide # counters that stay valid until the end of the filtering of the message. This counters are useful # to trig different actions depending on the number of failures encountered during the processing # of a message. There are 64 counters (0..63), accessible from all the filters. By specifying # counter:id:incr as a prefix of the hook action, you tell postlicyd to add (incr) to counter # (id) when this hook is reached. The "counter" filter type allow you to run actions depending # on the value of a counter. # # The action can be either a postfix access(5) value or a filter name. Postfix access # parameters must be prefixed by 'postfix:'. The text argument given to a postfix reply # may contain format strings to be replaced by the parameters of the query. This arguments # have the following format: ${fieldname} # # eg: # on_match = postfix:REJECT Blacklisted; # on_fail = postfix:450 Greylisted, see http://www.example.org/${sender_domain}.html # on_error = counter:0:1:postfix:DUNNO # on_match = counter:63:10:whitelist # # Filter: # Current defined filter types are: # - iplist: match the client_address against one or more blacklist files from a rbl # Parameters: # - file: (no)?lock:weight:filename # declare a file to load. If lock is given, the klist is locked into the # RAM. The weight is a number giving the weight of this blaclist file in the # score of the IP # - rbldns: (no)?lock:weight:filename # this is an alias for file. # - dns: weight:hostname # use a rbl via DNS resolution with the given weight. If a DNS lookup error occurs # the IP is considered as beeing "not found". # - soft_threshold: score (default: 1) # minimum score to match the soft_match return value # - hard_threshold: score (default: 1) # minimum score to match the hard_match return value # Return value: # The score of a query is the sum of the weight of the blacklist it matched. # - If the IP can not be parsed, returns error # - If no rbl was available (no file and all dns down), returns error. # - If the score is strictly greater >= than hard_threshold, returns hard_match # - If the score is strictly greater >= than soft_threshold, returns soft_match # - Else, returns fail # Lookup in a rbl spamhaus_and_abuseat { type = iplist; # configuration file = lock:10:/var/spool/postlicyd/rbl.spamhaus.org; file = lock:1:/var/spool/postlicyd/cbl.abuseat.org; soft_threshold = 1; hard_threshold = 11; # hooks on_soft_match = greylist; on_hard_match = postfix:REJECT optional text; on_fail = postfix:OK; on_error = postfix:DUNNO; } # - strlist: match strings from the query against a list of list. # Parameters: # - file: (no)?lock:(partial-)?(pre|suf)fix:weight:filename # declare a file to load. If lock is given, the list is locked into the # RAM. Prefix/Suffix is a parameter to tell the matcher which is the most # efficient storage order. The strings are internally stored into a trie that # allow high compression if a lot of prefix are shared by several strings. If # you choose "prefix", string are stored in the natural order in memory and # prefix compression is performed. If you choose "suffix", strings are stored # in reverse order in memory and suffix compression is performed. If you add "partial-" # to the match order, the entry will match if the file contains a prefix (resp. suffix) # of the string. The weight is a number giving the weight of this list in the string score. # e.g.: # * a file that contains ".polytechnique.org" in "partial-suffix" mode will match # all subdomains of "polytechnique.org". # * a file that contains "postmaster@" in "partial-prefix" mode will match all # postmaster emails. # * a file open without "partial-" modifier match exact strings. # - rbldns: (no)?lock:weight:filename # declare a rbldns zone file to load. This is exactly the same as file excepted that it wraps # parsing of hostname to split them into 2 categories: # * names beginning with '*' are sorted as 'domains' and are matched as suffix # * names starting with an alphanumirical character are sorted as 'hostnames' and are # process via exact matching. # - dns: weight:hostname # use a rhbl via DNS resolution with the given weight. If a DNS lookup error occurs # the hostname is considered as beeing "not found". This can only be used with "hostnames" # typed fields. # - soft_threshold: score (default: 1) # minimum score to match the soft_match return value # - hard_threshold: score (default: 1) # minimum score to match the hard_match return value # - fields: field_name(,field_name)* # list of field the match the string against. # currently only email OR hostname fields are supported. You MUST choose only # one of these types per strlist, and be carefull that the field you requested # are available in the protocol state you want to use this filter for. # * hostname fields: helo_name, client_name, reverse_client_name, sender_domain, # recipient_domain # * email fields: sender, recipient # No space is allowed in this parameter. # Return value: # The score of a query is the sum of the weight of the list it matched. # - If no rhbl was available (no file and all dns down), returns error. # - If the score is strictly greater >= than hard_threshold, returns hard_match # - If the score is strictly greater >= than soft_threshold, returns soft_match # - Else, returns fail # State: # - to match helo_name, you must be on HELO state or later # (stmpd_helo_restrictions) # - to match sender, you must be on MAIL state or later # (smtpd_sender_restrictions) # - to match recipient, you must on RCPT state (stmpd_recipient_restrictions) # - client_name and reverse_client_name are always available # Whitelist some clients client_whitelist { type = strlist; # configuration file = lock:1:suffix:/var/spool/postlicyd/client_whitelist; rbldns = lock:1:/va/spool/postlicyd/abuse.rfc-ignorant.org; fields = client_name,sender_domain,helo_name; # hooks on_hard_match = postfix:OK; on_fail = spamhaus_and_abuseat; } # - greylist: greylister # Paramters: # - path: /my/path/ (required) # path where to store the greylist database # - prefix: name (default: "") # prefix to the name of the greylist database # - lookup_by_host: boolean (default: false) # perform lookup per host. The default behaviour is to remove the last number of the IP # to match a domain. This behaviour is disabled if a part of the IP is contained in the # hostname (look like a dialup ip from a provider). With this flag on, the "domain" # matching is always disable. # - no_sender: boolean (default: false) # do not use the sender address. Default behaviour is to greylist using the tuple # (client_address, sender, recipient). With this flag on, the sender is not used. # - no_recipient: boolean (default: false) # same as no_sender but with recipient. # - delay: number (default: 300) # number of seconds the client must wait before retrial. # - retry_window: (default: 2 * 24 * 3600) # number of seconds we wait for a retry. # - client_awl: number (default: 5) # number of successful greylisting before the client get whitelisted (0 means, # no-auto-whitelist). # - max_age: number (default: 30 * 3600) # lifetime of a greylist/whitelist session: ie, if a client does ne reappear during # max_age seconds, the entries associated to this client are invalidated. # Return value: # - if the client is whitelisted, returns whitelist # - if the client is greylisted, returns greylist # - if a error occured (not currently possible), returns error # State: # this filter is a recipient filter and works in RCPT state onl if no_recipient # is not specified (smtpd_recipient_restrictions). If no_sender is not given, this # requires a sender name, and so must be called after MAIL TO. # Perform greylisting greylist { type = greylist; # configuration path = /var/spool/postlicyd/; prefix = greylist_; # hooks on_greylist = postfix:DEFER_IF_PERMIT optional text; on_whitelist = postfix:OK; } # - match: direct matching against the query fields # Parameters: # - match_all: boolean # if true, the filter won't match until all conditions # are verified. If false, the filter match on the first # verified condition. # - condition: field_name OP (value) # * the field_name is one of the field name of the query # emitted by postfix. This list with description of each # field is available at: # http://www.postfix.org/SMTPD_POLICY_README.html # postlicyd also support fields sender_domain and recipient_domain # * OP is an operator. Available operators are: # == field_name is strictly equal to value # =i field_name is case insensitively equal to value # != field_name is not equal to value # !i field_name is not case insensitively equal to value # >= field_name contains value # >i field_name contains case insensitively value # <= field_name is contained by value # = debian.org; condition = recipient #=; # hook on_match = postfix:OK; on_fail = counter:0:1:greylist; } # - counter: trig actions depending on the value of a counter # Parameters: # - counter: the id of the counter to trig on (0 -> 63) # - hard_threshold: minimum counter value to trig the hard_match hook # - soft_threshold: minimum counter value to trig the soft_match hook # Return value: # - hard_match if the counter with the given id is greater or equal to hard_threshold # - soft_match if the counter value is between soft_threshold and hard_threshold # - fail if the counter value is below soft_match # match if the counter 0 value is greater than 8, or between 5 and 7 counter { type = counter; # configuration counter = 0; hard_threshold = 8; soft_threshold = 5; # hook on_hard_match = postfix:REJECT ${sender_domain}; on_soft_match = greylist; on_fail = counter:1:10:match; } # ENTRY POINTS # # Access policy daemon can be used at several protocol states. For each of this states, # you can define a different entry point in the filtering tree. This entry points have # the following format: # # state = filter_name; # # The filter_name MUST be one of the filter you previously defined. # # The available states are: # - client_filter: called on CONNECT state (smtpd_client_restrictions) # - helo_filter (or ehlo_filter): called on HELO/EHLO command (smtpd_helo_restrictions) # - sender_filter: called on the MAIL FROM command (stmpd_sender_restrictions) # - recipient_filter: called on the RCPT TO command (smtpd_recipient_restrictions) # - data_filter: called on the DATA command (smtpd_data_restrictions) # - end_of_data_filter: called on the END-OF-DATA command # (smtpd_end_of_data_restrictions) # - etrn_filter: called on the ETRN command (stmpd_etrn_restrictions) # - verify_filter: called on the VRFY command (no postfix hook ?) recipient_filter = client_whitelist; # SERVER PORT # # Port to which the server is bound. The default is 10000. If the port is specified as # a command line parameter, the value specified on command line overides this value. # # You must RESTART the server to change the port (reload does not affect the port). port = 10000; # vim:set syntax=conf: