2 # $Id: filter_innd.pl 7860 2008-06-07 12:46:49Z iulius $
4 # Sample Perl filtering file for the innd hooks.
7 # This file gets loaded at innd process startup, and everytime a
8 # "ctlinnd reload filter.perl 'reason'" or a
9 # "ctlinnd reload all 'reason'" is done.
11 # Before this file is loaded, the perl routine `filter_before_reload' is
12 # called, and after it's finished loading, the perl routine
13 # `filter_after_reload' is called. See startup_innd.pl for more details.
15 # The following routines can be defined here for use by innd:
17 # sub filter_art { ... }
19 # This routine is called before every article is accepted for
20 # posting. Is is called with no arguments, but has access to
21 # all the non-empty standard headers of the article via the
22 # global associative array `%hdr.' If it returns the empty
23 # string ("") then the article is accepted. If it returns any
24 # non-null string value, then the article is rejected and the
25 # returned string value is logged as the reason why.
27 # The standard headers are:
29 # Approved, Control, Date, Distribution, Expires,
30 # From, Lines, Message-ID, Newsgroups, Path,
31 # Reply-To, Sender, Subject, Supersedes, Bytes,
32 # Also-Control, References
34 # sub filter_mode { ... }
36 # This routine is called every time `go', `pause', or
37 # `throttle' is called. It is called with no arguments and
38 # returns no value. The global associative array `%mode' has
39 # three keyed values stored in it:
41 # 'Mode' The current mode
42 # ("running", "paused", "throttled")
43 # 'NewMode" The new mode
44 # 'reason' The reason given.
46 # For example: %mode = ('Mode', 'running',
47 # 'NewMode', 'throttled',
48 # 'reason', 'doing nightly backups')
50 # If filter_art is not defined when this file is done loading, then
51 # filtering is disabled. If any syntax error occurs when loading the file,
52 # then filtering is disabled.
54 # sub filter_messageid { ... }
56 # This routine is called when each article (in streaming
57 # mode only) is checked to see if INN wants to accept the
58 # article. If it returns the empty string, the article
59 # is accepted. If it returns a non-empty value, the
60 # article is refused. It is called with one argument,
61 # the message-id to check.
66 # Called on each article innd receives from a peer. Return "" to accept,
67 # and any other non-null string to reject. If rejecting the string returned
68 # will be part of the logged reason.
72 my $rval = "" ; # Assume we'll accept. Cannot be `0'
74 ### Remove two leading '##' from the following section (and then
75 ### "ctlinnd reload filter.perl 'reason'" and the filter will reject articles that
76 ### have "make money" in the subject, or are posted to more than 10
79 ## my ($maxgroups) = 10 ;
81 ### Normally this output would be lost, but if you run innd with '-d -f' you
82 ### can see what's going on.
84 ### foreach $key (sort keys %hdr) {
85 ### print "Header:\t$key Value:\t $hdr{$key}\n" ;
88 ## if ($hdr{"Subject"} =~ /\$*make.*money.*\$*/i ) {
89 ## $rval = "no money requests here"
90 ## } elsif ( ( @_ = split(",",$hdr{'Newsgroups'}) ) > $maxgroups ) {
91 ## $rval = "too many groups" ;
92 ### Kill article with "Re: " but no References:
93 ## } elsif ($hdr{'Subject'} =~ /^Re: /o and $hdr{'References'} eq "") {
94 ## $rval = "Followup without References:";
95 ### Kill article with invalid From:
96 ## } elsif ($hdr{'From'} =~ /^\w*$/o or
97 ## $hdr{'From'} !~ /^(.+?)\@([-\w\d]+\.)*([-\w\d]+)\.([-\w\d]{2,})$/o) {
98 ## $rval = "From: is invalid, must be user\@[host.]domain.tld";
101 ### print "Accepting\n" if ! $rval ;
107 if ($mode{'NewMode'} eq "throttled" || $mode{'NewMode'} eq "paused") {
108 # print "Closing spam database\n" ; # won't kill server.
109 # &close_spam_database ;
111 # print "Opening spam database\n" ; # won't kill server
112 # &open_spam_database ;
116 sub filter_messageid {
117 my ($messageid) = @_;
119 # $rval = 'No' if ($messageid =~ /a\.spam\.domain>?/i);
127 ###########################################################################
129 ## Another sample. More elaborate, but cleaner... from Christophe
130 ## Wolfhugel <wolf@pasteur.fr>.
134 #### Regular expressions we reject.
135 #### Format : Header => regexp => reason
138 ## 'make.*money.*fast' => 'MMF rejected',
139 ## 'cash.*cash.*cash' => 'Cash rejected'
145 ## my(@ng, $i, $j, $k, $l);
147 ## if ($hdr{'From'} !~ /\@/o) {
148 ## $rval = 'Invalid From';
150 ## while (($i, $j) = each %reject) {
151 ## while (($k, $l) = each %{$j}) {
152 ## if ($hdr{$i} =~ /$k/i) {
159 ## @ng = split(/,/, $hdr{'Newsgroups'});
161 ## $rval = 'ECP rejected';
172 ### 'Subject' => 'Make money fast',
173 ### 'From' => 'bozo@gov.org'
179 ###########################################################################
181 ## From Chrisophe Wolfhugel again (wolf@pasteur.fr). This is not
185 ##Just for the fun, I've added following code to filter_innd.pl :
187 ## ## Keep track of the From and subject.
188 ## $i = "$hdr{'From'} $hdr{'Subject'}";
189 ## push(@history, $i);
192 ## ## Reject the EMP.
193 ## if ($history{$i} > 10) {
194 ## $rval = "EMP rejected (appeared $history{$i} times): $i";
197 ## ## Remove too old things.
198 ## while ($#history > 1000) {
199 ## delete($history{shift(@history)});
202 ##It is pretty successfull in detecting and refusing excessive multi-posting.
203 ##Same sender, same subject, appearing more than 10 times without the last
204 ##1000 articles gets junked.
206 ##Already catched a few hundreds :
208 ##Nov 20 08:27:23.175 - vishnu.jussieu.fr <3292ac9a.4064710@nntp.cts.com> 437 EMP rejected (btr@trenet.com Be a Beta Tester!)
210 ##That was just for the pleasure. It is still sucking a non significant CPU
211 ##time on my slow Alpha.