Imported Upstream version 1.32
This commit is contained in:
parent
6a47d71615
commit
db065246e2
28 changed files with 6336 additions and 1832 deletions
|
@ -85,7 +85,7 @@
|
|||
--cache-no-size skip size for cache-id
|
||||
--no_parent_request_cache disable parent request cache
|
||||
--no_parent_rate_cache disable parent rate cache
|
||||
--no_parent_dns_cache disable parent dns cache
|
||||
--no_parent_dns_cache disable parent dns cache (default)
|
||||
--no_parent_cache disable all parent caches</pre>
|
||||
<pre>
|
||||
Rates:
|
||||
|
@ -99,7 +99,10 @@
|
|||
--failures <f> max respawn failure counter
|
||||
--daemons <list> list of daemons to start
|
||||
--dumpcache show cache contents
|
||||
--dumpstats show statistics</pre>
|
||||
--dumpstats show statistics
|
||||
-R, --chroot <path> chroot to <path> before start
|
||||
--delcache <item> removes an item from the request cache
|
||||
--delrate <item> removes an item from the rate cache</pre>
|
||||
<pre>
|
||||
DNS:
|
||||
-n, --nodns skip any dns based test
|
||||
|
@ -119,11 +122,18 @@
|
|||
--noidlestats disables statistics when idle
|
||||
--norulestats disables per rule statistics
|
||||
-I, --instantcfg reloads ruleset on every new request
|
||||
--config_timeout <i> parser timeout in seconds</pre>
|
||||
--config_timeout <i> parser timeout in seconds
|
||||
--keep_rates do not clear rate limit counters on reload
|
||||
--save_rates <file> save and load rate limits on disk
|
||||
--fast_limit_evaluation evaluate rate limits before ruleset is parsed</pre>
|
||||
<pre>
|
||||
Plugins:
|
||||
--plugins <file> loads postfwd plugins from file</pre>
|
||||
<pre>
|
||||
Logging:
|
||||
-l, --logname <label> label for syslog messages
|
||||
--facility <s> use syslog facility <s>
|
||||
--socktype <s> use syslog socktype <s>
|
||||
--nodnslog do not log dns results
|
||||
--anydnslog log any dns (even cached) results
|
||||
--norulelog do not log rule actions
|
||||
|
@ -170,7 +180,7 @@ which should allow straightforward and easy-to-read configurations.</p>
|
|||
<p>A configuration line consists of optional item=value pairs, separated by semicolons
|
||||
(`;`) and the appropriate desired action:</p>
|
||||
<pre>
|
||||
[ <item1>[=><~]=<value>; <item2>[=><~]=<value>; ... ] action=<result></pre>
|
||||
[ <item1>=<value>; <item2>=<value>; ... ] action=<result></pre>
|
||||
<p><em>Example:</em></p>
|
||||
<pre>
|
||||
client_address=192.168.1.1 ; sender==no@bad.local ; action=REJECT</pre>
|
||||
|
@ -199,10 +209,19 @@ or trailing whitespace characters will be ignored. Use '#' to comment your confi
|
|||
appreciate.</p>
|
||||
<p>A ruleset consists of one or multiple rules, which can be loaded from files or passed as command line
|
||||
arguments. Please see the COMMAND LINE section below for more information on this topic.</p>
|
||||
<p>Rules can span multiple lines by adding a trailing backslash ``\'' character:</p>
|
||||
<p>Since postfwd version 1.30 rules spanning span multiple lines can be defined by prefixing the following
|
||||
lines with one or multiple whitespace characters (or '}' for macros):</p>
|
||||
<pre>
|
||||
id=R_001 ; client_address=192.168.1.0/24; sender==no@bad.local; \
|
||||
action=REJECT please use your relay from there</pre>
|
||||
id=RULE001
|
||||
client_address=192.168.1.0/24
|
||||
sender==no@bad.local
|
||||
action=REJECT no access</pre>
|
||||
<p>postfwd versions prior to 1.30 require trailing ';' and '\'-characters:</p>
|
||||
<pre>
|
||||
id=RULE001; \
|
||||
client_address=192.168.1.0/24; \
|
||||
sender==no@bad.local; \
|
||||
action=REJECT no access</pre>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="items">ITEMS</a></h2>
|
||||
|
@ -268,8 +287,14 @@ arguments. Please see the COMMAND LINE section below for more information on thi
|
|||
this enables version based checks in your rulesets
|
||||
(e.g. for migration). works with old versions too,
|
||||
because a non-existing item always returns false:
|
||||
id=R01; version~=1.10; sender_domain==some.org \
|
||||
# version >= 1.10
|
||||
id=R01; version~=1\.[1-9][0-9]; sender_domain==some.org \
|
||||
; action=REJECT sorry no access</pre>
|
||||
<pre>
|
||||
ratecount - only available for rate(), size() and rcpt() actions.
|
||||
contains the actual limit counter:
|
||||
id=R01; action=rate(sender/200/600/REJECT limit of 200 exceeded [$$ratecount hits])
|
||||
id=R02; action=rate(sender/100/600/WARN limit of 100 exceeded [$$ratecount hits])</pre>
|
||||
<p>Besides these you can specify any attribute of the postfix policy delegation protocol.
|
||||
Feel free to combine them the way you need it (have a look at the EXAMPLES section below).</p>
|
||||
<p>Most values can be specified as regular expressions (PCRE). Please see the table below
|
||||
|
@ -319,34 +344,33 @@ for details:</p>
|
|||
encryption_keysize=256 mask = numeric, will match if keysize >= 256
|
||||
...</pre>
|
||||
<p>the current list can be found at <a href="http://www.postfix.org/SMTPD_POLICY_README.html">http://www.postfix.org/SMTPD_POLICY_README.html</a>. Please read carefully about which
|
||||
attribute can be used at which level of the smtp transaction (e.g. size will only work reliably at END_OF_DATA level).
|
||||
attribute can be used at which level of the smtp transaction (e.g. size will only work reliably at END-OF-MESSAGE level).
|
||||
Pattern matching is performed case insensitive.</p>
|
||||
<p>Multiple use of the same item is allowed and will compared as logical OR, which means that this will work as expected:</p>
|
||||
<pre>
|
||||
id=TRUST001; action=OK; encryption_keysize=64; \
|
||||
ccert_fingerprint=11:22:33:44:55:66:77:88:99; \
|
||||
ccert_fingerprint=22:33:44:55:66:77:88:99:00; \
|
||||
ccert_fingerprint=33:44:55:66:77:88:99:00:11; \
|
||||
id=TRUST001; action=OK; encryption_keysize=64
|
||||
ccert_fingerprint=11:22:33:44:55:66:77:88:99
|
||||
ccert_fingerprint=22:33:44:55:66:77:88:99:00
|
||||
ccert_fingerprint=33:44:55:66:77:88:99:00:11
|
||||
sender=@domain\.local$</pre>
|
||||
<p>client_address, rbl and rhsbl items may also be specified as whitespace-or-comma-separated values:</p>
|
||||
<pre>
|
||||
id=SKIP01; action=dunno; \
|
||||
id=SKIP01; action=dunno
|
||||
client_address=192.168.1.0/24, 172.16.254.23
|
||||
id=SKIP02; action=dunno; \
|
||||
client_address= 10.10.3.32 \
|
||||
10.216.222.0/27</pre>
|
||||
id=SKIP02; action=dunno
|
||||
client_address= 10.10.3.32 10.216.222.0/27</pre>
|
||||
<p>The following items must be unique:</p>
|
||||
<pre>
|
||||
id, minimum and maximum values, rblcount and rhsblcount</pre>
|
||||
<p>Any item can be negated by preceeding '!!' to it, e.g.:</p>
|
||||
<pre>
|
||||
id=TLS001 ; hostname=!!^secure\.trust\.local$ ; action=REJECT only secure.trust.local please</pre>
|
||||
id=HOST001 ; hostname == !!secure.trust.local ; action=REJECT only secure.trust.local please</pre>
|
||||
<p>or using the right compare operator:</p>
|
||||
<pre>
|
||||
id=USER01 ; sasl_username !~ /^(bob|alice)$/ ; action=REJECT who is that?</pre>
|
||||
id=HOST001 ; hostname != secure.trust.local ; action=REJECT only secure.trust.local please</pre>
|
||||
<p>To avoid confusion with regexps or simply for better visibility you can use '!!(...)':</p>
|
||||
<pre>
|
||||
id=USER01 ; sasl_username=!!( /^(bob|alice)$/ ) ; action=REJECT who is that?</pre>
|
||||
id=USER01 ; sasl_username =~ !!( /^(bob|alice)$/ ) ; action=REJECT who is that?</pre>
|
||||
<p>Request attributes can be compared by preceeding '$$' characters, e.g.:</p>
|
||||
<pre>
|
||||
id=R-003 ; client_name = !! $$helo_name ; action=WARN helo does not match DNS
|
||||
|
@ -354,6 +378,29 @@ Pattern matching is performed case insensitive.</p>
|
|||
id=R-003 ; client_name = !!($$(helo_name)) ; action=WARN helo does not match DNS</pre>
|
||||
<p>This is only valid for PCRE values (see list above). The comparison will be performed as case insensitive exact match.
|
||||
Use the '-vv' option to debug.</p>
|
||||
<p>These special items will be reset for any new rule:</p>
|
||||
<pre>
|
||||
rblcount - contains the number of RBL answers
|
||||
rhsblcount - contains the number of RHSBL answers
|
||||
matches - contains the number of matched items
|
||||
dnsbltext - contains the dns TXT part of all RBL and RHSBL replies in the form
|
||||
rbltype:rblname:<txt>; rbltype:rblname:<txt>; ...</pre>
|
||||
<p>These special items will be changed for any matching rule:</p>
|
||||
<pre>
|
||||
request_hits - contains ids of all matching rules</pre>
|
||||
<p>This means that it might be necessary to save them, if you plan to use these values in later rules:</p>
|
||||
<pre>
|
||||
# set vals
|
||||
id=RBL01 ; rhsblcount=all; rblcount=all
|
||||
action=set(HIT_rhls=$$rhsblcount,HIT_rbls=$$rblcount,HIT_txt=$$dnsbltext)
|
||||
rbl=list.dsbl.org, bl.spamcop.net, dnsbl.sorbs.net, zen.spamhaus.org
|
||||
rhsbl_client=rddn.dnsbl.net.au, rhsbl.ahbl.org, rhsbl.sorbs.net
|
||||
rhsbl_sender=rddn.dnsbl.net.au, rhsbl.ahbl.org, rhsbl.sorbs.net</pre>
|
||||
<pre>
|
||||
# compare
|
||||
id=RBL02 ; HIT_rhls>=1 ; HIT_rbls>=1 ; action=554 5.7.1 blocked using $$HIT_rhls RHSBLs and $$HIT_rbls RBLs [INFO: $$HIT_txt]
|
||||
id=RBL03 ; HIT_rhls>=2 ; action=554 5.7.1 blocked using $$HIT_rhls RHSBLs [INFO: $$HIT_txt]
|
||||
id=RBL04 ; HIT_rbls>=2 ; action=554 5.7.1 blocked using $$HIT_rbls RBLs [INFO: $$HIT_txt]</pre>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="files">FILES</a></h2>
|
||||
|
@ -373,15 +420,15 @@ Use the '-vv' option to debug.</p>
|
|||
id=R001 ; ccert_fingerprint==table:/etc/postfwd/wl_ccerts ; action=DUNNO</pre>
|
||||
<p>This will ignore the right-hand value. Items can be mixed:</p>
|
||||
<pre>
|
||||
id=R002 ; action=REJECT \
|
||||
client_name==unknown; \
|
||||
id=R002 ; action=REJECT
|
||||
client_name==unknown
|
||||
client_name==<a href="file:/etc/postfwd/blacklisted">file:/etc/postfwd/blacklisted</a></pre>
|
||||
<p>and for non pcre (comma separated) items:</p>
|
||||
<pre>
|
||||
id=R003 ; action=REJECT \
|
||||
id=R003 ; action=REJECT
|
||||
client_address==10.1.1.1, <a href="file:/etc/postfwd/blacklisted">file:/etc/postfwd/blacklisted</a></pre>
|
||||
<pre>
|
||||
id=R004 ; action=REJECT \
|
||||
id=R004 ; action=REJECT
|
||||
rbl=myrbl.home.local, zen.spamhaus.org, <a href="file:/etc/postfwd/rbls_changing">file:/etc/postfwd/rbls_changing</a></pre>
|
||||
<p>You can check your configuration with the --show_config option at the command line:</p>
|
||||
<pre>
|
||||
|
@ -479,16 +526,16 @@ rule containing only an action statement:</p>
|
|||
please note that <action> is currently limited to postfix actions (no postfwd actions)!
|
||||
# no more than 3 requests per 5 minutes
|
||||
# from the same "unknown" client
|
||||
id=RATE01 ; client_name==unknown ; \
|
||||
action==rate(client_address/3/300/450 4.7.1 sorry, max 3 requests per 5 minutes)</pre>
|
||||
id=RATE01 ; client_name==unknown
|
||||
action=rate(client_address/3/300/450 4.7.1 sorry, max 3 requests per 5 minutes)</pre>
|
||||
<pre>
|
||||
size (<item>/<max>/<time>/<action>)
|
||||
this command works similar to the rate() command with the difference, that the rate counter is
|
||||
increased by the request's size attribute. to do this reliably you should call postfwd2 from
|
||||
smtpd_end_of_data_restrictions. if you want to be sure, you could check it within the ruleset:
|
||||
# size limit 1.5mb per hour per client
|
||||
id=SIZE01 ; state==END_OF_DATA ; client_address==!!(10.1.1.1); \
|
||||
action==size(client_address/1572864/3600/450 4.7.1 sorry, max 1.5mb per hour)</pre>
|
||||
id=SIZE01 ; protocol_state==END-OF-MESSAGE ; client_address==!!(10.1.1.1)
|
||||
action=size(client_address/1572864/3600/450 4.7.1 sorry, max 1.5mb per hour)</pre>
|
||||
<pre>
|
||||
rcpt (<item>/<max>/<time>/<action>)
|
||||
this command works similar to the rate() command with the difference, that the rate counter is
|
||||
|
@ -496,8 +543,8 @@ rule containing only an action statement:</p>
|
|||
from smtpd_data_restrictions or smtpd_end_of_data_restrictions. if you want to be sure, you could
|
||||
check it within the ruleset:
|
||||
# recipient count limit 3 per hour per client
|
||||
id=RCPT01 ; state==END_OF_DATA ; client_address==!!(10.1.1.1); \
|
||||
action==rcpt(client_address/3/3600/450 4.7.1 sorry, max 3 recipients per hour)</pre>
|
||||
id=RCPT01 ; protocol_state==END-OF-MESSAGE ; client_address==!!(10.1.1.1)
|
||||
action=rcpt(client_address/3/3600/450 4.7.1 sorry, max 3 recipients per hour)</pre>
|
||||
<pre>
|
||||
ask (<addr>:<port>[:<ignore>])
|
||||
allows to delegate the policy decision to another policy service (e.g. postgrey). the first
|
||||
|
@ -508,6 +555,11 @@ rule containing only an action statement:</p>
|
|||
# example2: query postgrey but ignore it's answer, if it matches 'DUNNO'
|
||||
# and continue parsing postfwd's ruleset
|
||||
id=GREY; client_address==10.1.1.1; action=ask(127.0.0.1:10031:^dunno$)</pre>
|
||||
<pre>
|
||||
mail(server/helo/from/to/subject/body)
|
||||
Very basic mail command, that sends a message with the given arguments. LIMITATIONS:
|
||||
This basically performs a telnet. No authentication or TLS are available. Additionally it does
|
||||
not track notification state and will notify you any time, the corresponding rule hits.</pre>
|
||||
<pre>
|
||||
wait (<delay>)
|
||||
pauses the program execution for <delay> seconds. use this for
|
||||
|
@ -515,7 +567,7 @@ rule containing only an action statement:</p>
|
|||
<pre>
|
||||
note (<string>)
|
||||
just logs the given string and continues parsing the ruleset.
|
||||
if the string is empty, nothing will be logged.</pre>
|
||||
if the string is empty, nothing will be logged (noop).</pre>
|
||||
<pre>
|
||||
quit (<code>)
|
||||
terminates the program with the given exit-code. postfix doesn`t
|
||||
|
@ -523,29 +575,6 @@ rule containing only an action statement:</p>
|
|||
<p>You can reference to request attributes, like</p>
|
||||
<pre>
|
||||
id=R-HELO ; helo_name=^[^\.]+$ ; action=REJECT invalid helo '$$helo_name'</pre>
|
||||
<p>These special attributes will be reset for any new rule:</p>
|
||||
<pre>
|
||||
rblcount - contains the number of RBL answers
|
||||
rhsblcount - contains the number of RHSBL answers
|
||||
matches - contains the number of matched items
|
||||
dnsbltext - contains the dns TXT part of all RBL and RHSBL replies in the form
|
||||
rbltype:rblname:<txt>; rbltype:rblname:<txt>; ...</pre>
|
||||
<p>These special attributes will be changed for any matching rule:</p>
|
||||
<pre>
|
||||
request_hits - contains ids of all matching rules</pre>
|
||||
<p>This means that it might be necessary to save them, if you plan to use these values in later rules:</p>
|
||||
<pre>
|
||||
# set vals
|
||||
id=RBL01 ; rhsblcount=all ; rblcount=all ; \
|
||||
rbl=list.dsbl.org, bl.spamcop.net, dnsbl.sorbs.net, zen.spamhaus.org ; \
|
||||
rhsbl_client=rddn.dnsbl.net.au, rhsbl.ahbl.org, rhsbl.sorbs.net ; \
|
||||
rhsbl_sender=rddn.dnsbl.net.au, rhsbl.ahbl.org, rhsbl.sorbs.net ; \
|
||||
action=set(HIT_rhls=$$rhsblcount,HIT_rbls=$$rblcount,HIT_txt=$$dnsbltext)</pre>
|
||||
<pre>
|
||||
# compare
|
||||
id=RBL02 ; HIT_rhls>=1 ; HIT_rbls>=1 ; action=554 5.7.1 blocked using $$HIT_rhls RHSBLs and $$HIT_rbls RBLs [INFO: $$HIT_txt]
|
||||
id=RBL03 ; HIT_rhls>=2 ; action=554 5.7.1 blocked using $$HIT_rhls RHSBLs [INFO: $$HIT_txt]
|
||||
id=RBL04 ; HIT_rbls>=2 ; action=554 5.7.1 blocked using $$HIT_rbls RBLs [INFO: $$HIT_txt]</pre>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="macros_acls">MACROS/ACLS</a></h2>
|
||||
|
@ -568,18 +597,18 @@ First the macros have to be defined as follows:</p>
|
|||
&&GONOW ; &&RBLS ; client_name=[\.-_](adsl|dynamic|ppp|)[\.-_]</pre>
|
||||
<p>Macros can contain macros, too:</p>
|
||||
<pre>
|
||||
# definition (note the trailing "\" characters)
|
||||
&&RBLS { \
|
||||
rbl=zen.spamhaus.org ; \
|
||||
rbl=list.dsbl.org ; \
|
||||
rbl=bl.spamcop.net ; \
|
||||
rbl=dnsbl.sorbs.net ; \
|
||||
rbl=ix.dnsbl.manitu.net ; \
|
||||
# definition
|
||||
&&RBLS{
|
||||
rbl=zen.spamhaus.org
|
||||
rbl=list.dsbl.org
|
||||
rbl=bl.spamcop.net
|
||||
rbl=dnsbl.sorbs.net
|
||||
rbl=ix.dnsbl.manitu.net
|
||||
};
|
||||
&&DYNAMIC { \
|
||||
client_name=^unknown$ ; \
|
||||
client_name=(\d+[\.-_]){4} ; \
|
||||
client_name=[\.-_](adsl|dynamic|ppp|)[\.-_] ; \
|
||||
&&DYNAMIC{
|
||||
client_name=^unknown$
|
||||
client_name=(\d+[\.-_]){4}
|
||||
client_name=[\.-_](adsl|dynamic|ppp|)[\.-_]
|
||||
};
|
||||
&&GOAWAY { &&RBLS; &&DYNAMIC; };
|
||||
# rules
|
||||
|
@ -588,7 +617,141 @@ First the macros have to be defined as follows:</p>
|
|||
<p>
|
||||
</p>
|
||||
<h2><a name="plugins">PLUGINS</a></h2>
|
||||
<p>Please visit <a href="http://www.postfwd.org/postfwd.plugins">http://www.postfwd.org/postfwd.plugins</a></p>
|
||||
<p><strong>Description</strong></p>
|
||||
<p>The plugin interface allow you to define your own checks and enhance postfwd's
|
||||
functionality. Feel free to share useful things!</p>
|
||||
<p><strong>Warning</strong></p>
|
||||
<p>Note that the plugin interface is still at devel stage. Please test your plugins
|
||||
carefully, because errors may cause postfwd to break! It is also
|
||||
allowed to override attributes or built-in functions, but be sure that you know
|
||||
what you do because some of them are used internally.</p>
|
||||
<p>Please keep security in mind, when you access sensible ressources and never, ever
|
||||
run postfwd as privileged user! Also never trust your input (especially hostnames,
|
||||
and e-mail addresses).</p>
|
||||
<p><strong>ITEMS</strong></p>
|
||||
<p>Item plugins are perl subroutines which integrate additional attributes to requests
|
||||
before they are evaluated against postfwd's ruleset like any other item of the
|
||||
policy delegation protocol. This allows you to create your own checks.</p>
|
||||
<p>plugin-items can not be used selective. these functions will be executed for every
|
||||
request postfwd receives, so keep performance in mind.</p>
|
||||
<pre>
|
||||
SYNOPSIS: %result = postfwd_items_plugin{<name>}(%request)</pre>
|
||||
<p>means that your subroutine, called <name>, has access to a hash called %request,
|
||||
which contains all request attributes, like $request{client_name} and must
|
||||
return a value in the following form:</p>
|
||||
<pre>
|
||||
save: $result{<item>} = <value></pre>
|
||||
<p>this creates the new item <item> containing <value>, which will be integrated in
|
||||
the policy delegation request and therefore may be used in postfwd's ruleset.</p>
|
||||
<pre>
|
||||
# do NOT remove the next line
|
||||
%postfwd_items_plugin = (</pre>
|
||||
<pre>
|
||||
# EXAMPLES - integrated in postfwd. no need to activate them here.
|
||||
|
||||
# allows to check postfwd version in ruleset
|
||||
"version" => sub {
|
||||
my(%request) = @_;
|
||||
my(%result) = (
|
||||
"version" => $NAME." ".$VERSION,
|
||||
);
|
||||
return %result;
|
||||
},
|
||||
|
||||
# sender_domain and recipient_domain
|
||||
"address_parts" => sub {
|
||||
my(%request) = @_;
|
||||
my(%result) = ();
|
||||
$request{sender} =~ /@([^@]*)$/;
|
||||
$result{sender_domain} = ($1 || '');
|
||||
$request{recipient} =~ /@([^@]*)$/;
|
||||
$result{recipient_domain} = ($1 || '');
|
||||
return %result;
|
||||
},</pre>
|
||||
<pre>
|
||||
# do NOT remove the next line
|
||||
);</pre>
|
||||
<p><strong>COMPARE</strong></p>
|
||||
<p>Compare plugins allow you to define how your new items should be compared to the ruleset.
|
||||
These are optional. If you don't specify one, the default (== for exact match, =~ for PCRE, ...)
|
||||
will be used.</p>
|
||||
<pre>
|
||||
SYNOPSIS: <item> => sub { return &{$postfwd_compare{<type>}}(@_); },</pre>
|
||||
<pre>
|
||||
# do NOT remove the next line
|
||||
%postfwd_compare_plugin = (</pre>
|
||||
<pre>
|
||||
EXAMPLES - integrated in postfwd. no need to activate them here.
|
||||
|
||||
# Simple example
|
||||
# SYNOPSIS: <result> = <item> (return &{$postfwd_compare{<type>}}(@_))
|
||||
"client_address" => sub { return &{$postfwd_compare{cidr}}(@_); },
|
||||
"size" => sub { return &{$postfwd_compare{numeric}}(@_); },
|
||||
"recipient_count" => sub { return &{$postfwd_compare{numeric}}(@_); },
|
||||
|
||||
# Complex example
|
||||
# SYNOPSIS: <result> = <item>(<operator>, <ruleset value>, <request value>, <request>)
|
||||
"numeric" => sub {
|
||||
my($cmp,$val,$myitem,%request) = @_;
|
||||
my($myresult) = undef; $myitem ||= "0"; $val ||= "0";
|
||||
if ($cmp eq '==') {
|
||||
$myresult = ($myitem == $val);
|
||||
} elsif ($cmp eq '=<') {
|
||||
$myresult = ($myitem <= $val);
|
||||
} elsif ($cmp eq '=>') {
|
||||
$myresult = ($myitem >= $val);
|
||||
} elsif ($cmp eq '!=') {
|
||||
$myresult = not($myitem == $val);
|
||||
} elsif ($cmp eq '!<') {
|
||||
$myresult = not($myitem <= $val);
|
||||
} elsif ($cmp eq '!>') {
|
||||
$myresult = not($myitem >= $val);
|
||||
} else {
|
||||
$myresult = ($myitem >= $val);
|
||||
};
|
||||
return $myresult;
|
||||
},</pre>
|
||||
<pre>
|
||||
# do NOT remove the next line
|
||||
);</pre>
|
||||
<p><strong>ACTIONS</strong></p>
|
||||
<p>Action plugins allow to define new postfwd actions. By setting the $stop-flag you can decide to
|
||||
continue or to stop parsing the ruleset.</p>
|
||||
<pre>
|
||||
SYNOPSIS: (<stop rule parsing>, <next rule index>, <return action>, <logprefix>, <request>) =
|
||||
<action> (<current rule index>, <current time>, <command name>, <argument>, <logprefix>, <request>)</pre>
|
||||
<pre>
|
||||
# do NOT remove the next line
|
||||
%postfwd_actions_plugin = (</pre>
|
||||
<pre>
|
||||
# EXAMPLES - integrated in postfwd. no need to activate them here.
|
||||
|
||||
# note(<logstring>) command
|
||||
"note" => sub {
|
||||
my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
|
||||
my($myaction) = $default_action; my($stop) = 0;
|
||||
mylogs 'info', "[RULES] ".$myline." - note: ".$myarg if $myarg;
|
||||
return ($stop,$index,$myaction,$myline,%request);
|
||||
},
|
||||
|
||||
# skips next <myarg> rules
|
||||
"skip" => sub {
|
||||
my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
|
||||
my($myaction) = $default_action; my($stop) = 0;
|
||||
$index += $myarg if ( $myarg and not(($index + $myarg) > $#Rules) );
|
||||
return ($stop,$index,$myaction,$myline,%request);
|
||||
},
|
||||
|
||||
# dumps current request contents to syslog
|
||||
"dumprequest" => sub {
|
||||
my($index,$now,$mycmd,$myarg,$myline,%request) = @_;
|
||||
my($myaction) = $default_action; my($stop) = 0;
|
||||
map { mylogs 'info', "[DUMP] rule=$index, Attribute: $_=$request{$_}" } (keys %request);
|
||||
return ($stop,$index,$myaction,$myline,%request);
|
||||
},</pre>
|
||||
<pre>
|
||||
# do NOT remove the next line
|
||||
);</pre>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="command_line">COMMAND LINE</a></h2>
|
||||
|
@ -603,18 +766,13 @@ that at least one of the following is required for postfwd2 to work.</p>
|
|||
-r, --rule <rule>
|
||||
Adds <rule> to ruleset. Remember that you might have to quote
|
||||
strings that contain whitespaces or shell characters.</pre>
|
||||
<p><em>Plugins</em></p>
|
||||
<pre>
|
||||
--plugins
|
||||
A file containing plugin routines for postfwd. Please see the
|
||||
PLUGINS section for more information.</pre>
|
||||
<p><em>Scoring</em></p>
|
||||
<pre>
|
||||
-s, --scores <val>=<action>
|
||||
Returns <action> to postfix, when the request's score exceeds <val></pre>
|
||||
<p>Multiple usage is allowed. Just chain your arguments, like:</p>
|
||||
<pre>
|
||||
postfwd2 -r "<item>=<value>;action=<result>" -f <file> -f <file> --plugins <file> ...
|
||||
postfwd2 -r "<item>=<value>;action=<result>" -f <file> -f <file> ...
|
||||
or
|
||||
postfwd2 --scores 4.5="WARN high score" --scores 5.0="REJECT postfwd2 score too high" ...</pre>
|
||||
<p>In case of multiple scores, the highest match will count. The order of the arguments will be
|
||||
|
@ -625,13 +783,13 @@ The following arguments will control it's behaviour in this case.</p>
|
|||
<pre>
|
||||
-d, --daemon
|
||||
postfwd2 will run as daemon and listen on the network for incoming
|
||||
queries (default 127.0.0.1:10040).</pre>
|
||||
queries (default 127.0.0.1:10045).</pre>
|
||||
<pre>
|
||||
-i, --interface <dev>
|
||||
Bind postfwd2 to the specified interface (default 127.0.0.1).</pre>
|
||||
<pre>
|
||||
-p, --port <port>
|
||||
postfwd2 listens on the specified port (default tcp/10040).</pre>
|
||||
postfwd2 listens on the specified port (default tcp/10045).</pre>
|
||||
<pre>
|
||||
--proto <type>
|
||||
The protocol type for postfwd's socket. Currently you may use 'tcp' or 'unix' here.
|
||||
|
@ -657,10 +815,17 @@ The following arguments will control it's behaviour in this case.</p>
|
|||
<pre>
|
||||
-R, --chroot <path>
|
||||
Chroot the process to the specified path.
|
||||
Test this before using - you might need some libs there.</pre>
|
||||
Please look at <a href="http://postfwd.org/postfwd2-chroot.html">http://postfwd.org/postfwd2-chroot.html</a> before use!</pre>
|
||||
<pre>
|
||||
--pidfile <path>
|
||||
The process id will be saved in the specified file.</pre>
|
||||
<pre>
|
||||
--facility <f>
|
||||
sets the syslog facility, default is 'mail'</pre>
|
||||
<pre>
|
||||
--socktype <s>
|
||||
sets the Sys::Syslog socktype to 'native', 'inet' or 'unix'.
|
||||
Default is to auto-detect this depening on module version and os.</pre>
|
||||
<pre>
|
||||
-l, --logname <label>
|
||||
Labels the syslog messages. Useful when running multiple
|
||||
|
@ -668,6 +833,11 @@ The following arguments will control it's behaviour in this case.</p>
|
|||
<pre>
|
||||
--loglen <int>
|
||||
Truncates any syslog message after <int> characters.</pre>
|
||||
<p><em>Plugins</em></p>
|
||||
<pre>
|
||||
--plugins <file>
|
||||
Loads postfwd plugins from file. Please see <a href="http://postfwd.org/postfwd.plugins">http://postfwd.org/postfwd.plugins</a>
|
||||
or the plugins.postfwd.sample that is available from the tarball for more info.</pre>
|
||||
<p><em>Optional arguments</em></p>
|
||||
<p>These parameters influence the way postfwd2 is working. Any of them can be combined.</p>
|
||||
<pre>
|
||||
|
@ -794,7 +964,22 @@ The following arguments will control it's behaviour in this case.</p>
|
|||
timeout in seconds to parse a single configuration line. if exceeded, the rule will
|
||||
be skipped. this is used to prevent problems due to large files or loops.
|
||||
|
||||
I<Informational arguments></pre>
|
||||
--keep_rates (default=0)
|
||||
With this option set postfwd2 does not clear the rate limit counters on reload. Please
|
||||
note that you have to restart (not reload) postfwd with this option if you change
|
||||
any rate limit rules.</pre>
|
||||
<pre>
|
||||
--save_rates (default=none)
|
||||
With this option postfwd saves existing rate limit counters to disk and reloads them
|
||||
on program start. This allows persistent rate limits across program restarts or reboots.
|
||||
Please note that postfwd needs read and write access to the specified file.</pre>
|
||||
<pre>
|
||||
--fast_limit_evaluation (default=0)
|
||||
Once a ratelimit was set by the ruleset, future requests will be evaluated against it
|
||||
before consulting the ruleset. This mode was the default behaviour until v1.30.
|
||||
With this mode rate limits will be faster, but also eventually set up
|
||||
whitelisting-rules within the ruleset might not work as expected.</pre>
|
||||
<p><em>Informational arguments</em></p>
|
||||
<p>These arguments are for command line usage only. Never ever use them with postfix!</p>
|
||||
<pre>
|
||||
-C, --showconfig
|
||||
|
@ -815,6 +1000,26 @@ I<Informational arguments></pre>
|
|||
-P, --perfmon
|
||||
This option turns of any syslogging and output. It is included
|
||||
for performance testing.</pre>
|
||||
<pre>
|
||||
--dumpstats
|
||||
Displays program usage statistics.</pre>
|
||||
<pre>
|
||||
--dumpcache
|
||||
Displays cache contents.</pre>
|
||||
<pre>
|
||||
--delcache <item>
|
||||
Removes an item from the request cache. Use --dumpcache to identify objects.
|
||||
E.g.:
|
||||
# postfwd --dumpcache
|
||||
...
|
||||
%rate_cache -> %sender=gmato@jqvo.org -> %RATE002+2_600 -> @count -> '1'
|
||||
%rate_cache -> %sender=gmato@jqvo.org -> %RATE002+2_600 -> @maxcount -> '2'
|
||||
...
|
||||
# postfwd --delrate="sender=gmato@jqvo.org"
|
||||
rate cache item 'sender=gmato@jqvo.org' removed</pre>
|
||||
<pre>
|
||||
--delrate <item>
|
||||
Removes an item from the rate cache. Use --dumpcache to identify objects.</pre>
|
||||
<p>
|
||||
</p>
|
||||
<h2><a name="refresh">REFRESH</a></h2>
|
||||
|
@ -854,18 +1059,25 @@ the '-I' switch to have your configuration refreshed for every request postfwd2
|
|||
# 1. 30MB for systems in *.customer1.tld
|
||||
# 2. 20MB for SASL user joejob
|
||||
# 3. 10MB default
|
||||
id=SZ001; state==END-OF-MESSAGE; action=DUNNO; size<=30000000 ; client_name=\.customer1.tld$
|
||||
id=SZ002; state==END-OF-MESSAGE; action=DUNNO; size<=20000000 ; sasl_username==joejob
|
||||
id=SZ002; state==END-OF-MESSAGE; action=DUNNO; size<=10000000
|
||||
id=SZ100; state==END-OF-MESSAGE; action=REJECT message too large</pre>
|
||||
id=SZ001; protocol_state==END-OF-MESSAGE; action=DUNNO; size<=30000000 ; client_name=\.customer1.tld$
|
||||
id=SZ002; protocol_state==END-OF-MESSAGE; action=DUNNO; size<=20000000 ; sasl_username==joejob
|
||||
id=SZ002; protocol_state==END-OF-MESSAGE; action=DUNNO; size<=10000000
|
||||
id=SZ100; protocol_state==END-OF-MESSAGE; action=REJECT message too large</pre>
|
||||
<pre>
|
||||
## Selective Greylisting
|
||||
##
|
||||
## Note that postfwd does not include greylisting. This setup requires a running postgrey service
|
||||
## at port 10031 and the following postfix restriction class in your main.cf:
|
||||
##
|
||||
## smtpd_restriction_classes = check_postgrey, ...
|
||||
## check_postgrey = check_policy_service inet:127.0.0.1:10031
|
||||
#
|
||||
# 1. if listed on zen.spamhaus.org with results 127.0.0.10 or .11, dns cache timeout 1200s
|
||||
# 2. Client has no rDNS
|
||||
# 3. Client comes from several dialin domains
|
||||
id=GR001; action=greylisting ; rbl=dul.dnsbl.sorbs.net, zen.spamhaus.org/127.0.0.1[01]/1200
|
||||
id=GR002; action=greylisting ; client_name=^unknown$
|
||||
id=GR003; action=greylisting ; client_name=\.(t-ipconnect|alicedsl|ish)\.de$</pre>
|
||||
id=GR001; action=check_postgrey ; rbl=dul.dnsbl.sorbs.net, zen.spamhaus.org/127.0.0.1[01]/1200
|
||||
id=GR002; action=check_postgrey ; client_name=^unknown$
|
||||
id=GR003; action=check_postgrey ; client_name=\.(t-ipconnect|alicedsl|ish)\.de$</pre>
|
||||
<pre>
|
||||
## Date Time
|
||||
date=24.12.2007-26.12.2007 ; action=450 4.7.1 office closed during christmas
|
||||
|
@ -873,7 +1085,7 @@ the '-I' switch to have your configuration refreshed for every request postfwd2
|
|||
time=-07:00:00 ; sasl_username=jim ; action=450 4.7.1 to early for you, jim
|
||||
time=22:00:00- ; sasl_username=jim ; action=450 4.7.1 to late now, jim
|
||||
months=-Apr ; action=450 4.7.1 see you in may
|
||||
days=!!Mon-Fri ; action=greylist</pre>
|
||||
days=!!Mon-Fri ; action=check_postgrey</pre>
|
||||
<pre>
|
||||
## Usage of jump
|
||||
# The following allows a message size of 30MB for different
|
||||
|
@ -883,8 +1095,8 @@ the '-I' switch to have your configuration refreshed for every request postfwd2
|
|||
id=R003 ; action=jump(R100) ; ccert_fingerprint=AA:BB:CC:DD:...
|
||||
id=R004 ; action=jump(R100) ; ccert_fingerprint=AF:BE:CD:DC:...
|
||||
id=R005 ; action=jump(R100) ; ccert_fingerprint=DD:CC:BB:DD:...
|
||||
id=R099 ; state==END-OF-MESSAGE; action=REJECT message too big (max. 10MB); size=10000000
|
||||
id=R100 ; state==END-OF-MESSAGE; action=REJECT message too big (max. 30MB); size=30000000</pre>
|
||||
id=R099 ; protocol_state==END-OF-MESSAGE; action=REJECT message too big (max. 10MB); size=10000000
|
||||
id=R100 ; protocol_state==END-OF-MESSAGE; action=REJECT message too big (max. 30MB); size=30000000</pre>
|
||||
<pre>
|
||||
## Usage of score
|
||||
# The following rejects a mail, if the client
|
||||
|
@ -892,8 +1104,8 @@ the '-I' switch to have your configuration refreshed for every request postfwd2
|
|||
# - is listed in 1 RBL or 1 RHSBL and has no correct rDNS
|
||||
# - other clients without correct rDNS will be greylist-checked
|
||||
# - some whitelists are used to lower the score
|
||||
id=S01 ; score=2.6 ; action=greylisting
|
||||
id=S02 ; score=5.0 ; action=REJECT postfwd2 score too high
|
||||
id=S01 ; score=2.6 ; action=check_postgrey
|
||||
id=S02 ; score=5.0 ; action=REJECT postfwd score too high
|
||||
id=R00 ; action=score(-1.0) ; rbl=exemptions.ahbl.org,list.dnswl.org,query.bondedsender.org,spf.trusted-forwarder.org
|
||||
id=R01 ; action=score(2.5) ; rbl=bl.spamcop.net, list.dsbl.org, dnsbl.sorbs.net
|
||||
id=R02 ; action=score(2.5) ; rhsbl=rhsbl.ahbl.org, rhsbl.sorbs.net
|
||||
|
@ -905,10 +1117,10 @@ the '-I' switch to have your configuration refreshed for every request postfwd2
|
|||
# The following temporary rejects requests from "unknown" clients, if they
|
||||
# 1. exceeded 30 requests per hour or
|
||||
# 2. tried to send more than 1.5mb within 10 minutes
|
||||
id=RATE01 ; client_name==unknown ; state==RCPT ; \
|
||||
action==rate(client_address/30/3600/450 4.7.1 sorry, max 30 requests per hour)
|
||||
id=SIZE01 ; client_name==unknown ; state==END_OF_DATA ; \
|
||||
action==size(client_address/1572864/600/450 4.7.1 sorry, max 1.5mb per 10 minutes)</pre>
|
||||
id=RATE01 ; client_name==unknown ; protocol_state==RCPT
|
||||
action=rate(client_address/30/3600/450 4.7.1 sorry, max 30 requests per hour)
|
||||
id=SIZE01 ; client_name==unknown ; protocol_state==END-OF-MESSAGE
|
||||
action=size(client_address/1572864/600/450 4.7.1 sorry, max 1.5mb per 10 minutes)</pre>
|
||||
<pre>
|
||||
## Macros
|
||||
# definition
|
||||
|
@ -921,34 +1133,34 @@ the '-I' switch to have your configuration refreshed for every request postfwd2
|
|||
<pre>
|
||||
## Groups
|
||||
# definition
|
||||
&&RBLS { \
|
||||
rbl=zen.spamhaus.org ; \
|
||||
rbl=list.dsbl.org ; \
|
||||
rbl=bl.spamcop.net ; \
|
||||
rbl=dnsbl.sorbs.net ; \
|
||||
rbl=ix.dnsbl.manitu.net ; \
|
||||
&&RBLS{
|
||||
rbl=zen.spamhaus.org
|
||||
rbl=list.dsbl.org
|
||||
rbl=bl.spamcop.net
|
||||
rbl=dnsbl.sorbs.net
|
||||
rbl=ix.dnsbl.manitu.net
|
||||
};
|
||||
&&RHSBLS { \
|
||||
&&RHSBLS{
|
||||
...
|
||||
};
|
||||
&&DYNAMIC { \
|
||||
client_name==unknown ; \
|
||||
client_name~=(\d+[\.-_]){4} ; \
|
||||
client_name~=[\.-_](adsl|dynamic|ppp|)[\.-_] ; \
|
||||
&&DYNAMIC{
|
||||
client_name==unknown
|
||||
client_name~=(\d+[\.-_]){4}
|
||||
client_name~=[\.-_](adsl|dynamic|ppp|)[\.-_]
|
||||
...
|
||||
};
|
||||
&&BAD_HELO { \
|
||||
helo_name==my.name.tld; \
|
||||
helo_name~=^([^\.]+)$; \
|
||||
helo_name~=\.(local|lan)$; \
|
||||
&&BAD_HELO{
|
||||
helo_name==my.name.tld
|
||||
helo_name~=^([^\.]+)$
|
||||
helo_name~=\.(local|lan)$
|
||||
...
|
||||
};
|
||||
&&MAINTENANCE { \
|
||||
date=15.01.2007 ; \
|
||||
date=15.04.2007 ; \
|
||||
date=15.07.2007 ; \
|
||||
date=15.10.2007 ; \
|
||||
time=03:00:00 - 04:00:00 ; \
|
||||
&&MAINTENANCE{
|
||||
date=15.01.2007
|
||||
date=15.04.2007
|
||||
date=15.07.2007
|
||||
date=15.10.2007
|
||||
time=03:00:00 - 04:00:00
|
||||
};
|
||||
# rules
|
||||
id=COMBINED ; &&RBLS ; &&DYNAMIC ; action=REJECT dynamic client and listed on RBL
|
||||
|
@ -965,7 +1177,7 @@ the '-I' switch to have your configuration refreshed for every request postfwd2
|
|||
<pre>
|
||||
## combined with enhanced rbl features
|
||||
#
|
||||
id=RBL01 ; rhsblcount=all ; rblcount=all ; &&RBLS ; &&RHSBLS ; \
|
||||
id=RBL01 ; rhsblcount=all ; rblcount=all ; &&RBLS ; &&RHSBLS
|
||||
action=set(HIT_dnsbls=$$rhsblcount,HIT_dnsbls+=$$rblcount,HIT_dnstxt=$$dnsbltext)
|
||||
id=RBL02 ; HIT_dnsbls>=2 ; action=554 5.7.1 blocked using $$HIT_dnsbls DNSBLs [INFO: $$HIT_dnstxt]</pre>
|
||||
<p>
|
||||
|
@ -1068,21 +1280,21 @@ place a last catch-all rule to change that behaviour:</p>
|
|||
postfwd2 will spawn multiple child processes which communicate with a parent cache. This is
|
||||
the prefered way to use postfwd2 in high volume environments. Start postfwd2 with the following parameters:</p>
|
||||
<pre>
|
||||
postfwd2 -d -f /etc/postfwd.cf -i 127.0.0.1 -p 10040 -u nobody -g nobody -S</pre>
|
||||
postfwd2 -d -f /etc/postfwd.cf -i 127.0.0.1 -p 10045 -u nobody -g nobody -S</pre>
|
||||
<p>For efficient caching you should check if you can use the options --cacheid, --cache-rdomain-only,
|
||||
--cache-no-sender and --cache-no-size.</p>
|
||||
<p>Now check your syslogs (default facility ``mail'') for a line like:</p>
|
||||
<pre>
|
||||
Aug 9 23:00:24 mail postfwd[5158]: postfwd2 n.nn ready for input</pre>
|
||||
<p>and use `netstat -an|grep 10040` to check for something like</p>
|
||||
<p>and use `netstat -an|grep 10045` to check for something like</p>
|
||||
<pre>
|
||||
tcp 0 0 127.0.0.1:10040 0.0.0.0:* LISTEN</pre>
|
||||
tcp 0 0 127.0.0.1:10045 0.0.0.0:* LISTEN</pre>
|
||||
<p>If everything works, open your postfix main.cf and insert the following</p>
|
||||
<pre>
|
||||
127.0.0.1:10040_time_limit = 3600 <--- integration
|
||||
127.0.0.1:10045_time_limit = 3600 <--- integration
|
||||
smtpd_recipient_restrictions = permit_mynetworks <--- recommended
|
||||
reject_unauth_destination <--- recommended
|
||||
check_policy_service inet:127.0.0.1:10040 <--- integration</pre>
|
||||
check_policy_service inet:127.0.0.1:10045 <--- integration</pre>
|
||||
<p>Reload your configuration with `postfix reload` and watch your logs. In it works you should see
|
||||
lines like the following in your mail log:</p>
|
||||
<pre>
|
||||
|
@ -1098,9 +1310,9 @@ tables. First create a file /etc/postfix/policy containing:</p>
|
|||
<pre>
|
||||
# Restriction Classes
|
||||
smtpd_restriction_classes = postfwdcheck, <some more>... <--- integration
|
||||
postfwdcheck = check_policy_service inet:127.0.0.1:10040 <--- integration</pre>
|
||||
postfwdcheck = check_policy_service inet:127.0.0.1:10045 <--- integration</pre>
|
||||
<pre>
|
||||
127.0.0.1:10040_time_limit = 3600 <--- integration
|
||||
127.0.0.1:10045_time_limit = 3600 <--- integration
|
||||
smtpd_recipient_restrictions = permit_mynetworks, <--- recommended
|
||||
reject_unauth_destination, <--- recommended
|
||||
... <--- optional
|
||||
|
@ -1122,7 +1334,7 @@ Simply change it to meet your requirements and use</p>
|
|||
action=<whateveryouconfigured></pre>
|
||||
<p>For network tests I use netcat:</p>
|
||||
<pre>
|
||||
nc 127.0.0.1 10040 <request.sample</pre>
|
||||
nc 127.0.0.1 10045 <request.sample</pre>
|
||||
<p>to send a request to postfwd. If you receive nothing, make sure that postfwd2 is running and
|
||||
listening on the specified network settings.</p>
|
||||
<p>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue