# Auto-updating my /etc/postfix/maps/sender_access

## freke

I don't do scripts much  :Sad: , but after checking my postfix-logs today I counted 138 connections from different IPs trying to send spam to my domain - all with from=<purchase@kalyanimotors.com>.

I added it to my /etc/postfix/maps/sender_access

```
purchase@kalyanimotors.com REJECT
```

updated the db with postmap hash:sender_access and made sure it was used in my main.cf restrictions.

Got me thinking though; a simple script could probably show me the most rejected sender-address from my /var/log/postfix/current and maybe even automagically add it to /etc/postfix/maps/sender_access and do a postfix reload....

Anyone fluent in grep, gawk, wc, sed or whatever might be needed to do that?  :Wink: 

The log-lines are like this

```
May 10 20:13:44 [postfix/smtpd] NOQUEUE: reject: RCPT from unknown[31.200.52.93]: 554 5.7.1 Service unavailable; Client host [31.200.52.93] blocked using tr.dnsbl.vlh.dk; Blocked using GeoIP - not accepting mail from Turkey, see http://whatismyipaddress.com/ip/31.200.52.93; from=<BoyerDarwin44599@carobcommunications.com> to=<Mike93@vlh.dk> proto=ESMTP helo=<[31.200.52.93]>

May 10 20:14:27 [postfix/smtpd] NOQUEUE: reject: RCPT from unknown[187.172.57.214]: 554 5.7.1 Service unavailable; Client host [187.172.57.214] blocked using mx.dnsbl.vlh.dk; Blocked using GeoIP - not accepting mail from Mexico, see http://whatismyipaddress.com/ip/187.172.57.214; from=<GardnerAngelica6946@intercars.lt> to=<Tawnie@vlh.dk> proto=ESMTP helo=<dsl-187-172-57-214-dyn.prod-infinitum.com.mx>

May 10 20:14:55 [postfix/smtpd] NOQUEUE: reject: RCPT from 104-40-238-49.southernonline.net[49.238.40.104]: 554 5.7.1 <purchase@kalyanimotors.com>: Sender address rejected: Access denied; from=<purchase@kalyanimotors.com> to=<KevinKimberlySinuk@vlh.dk> proto=ESMTP helo=<104-40-238-49.southernonline.net>

```

----------

## Fred Krogh

It seems we are having similar problems with grey listing.  So I've got a reduction from 200 spams a day to about 40.  But each of those has been extra work trying to get something in my configuration files that will avoid getting the same problem twice.  I like your idea of automatically getting data from the log files (mine in in /var/log/messages).   I used sed one time maybe 10 or 20 years ago, so I should be able to use it again.  My problem is that even if I were doing it by hand, I'm not sure what I should extract.  I don't want to get the same spam twice, but I don't want to prevent mail I want from being available.

I don't find the postfix documents that easy to understand.  I believe sender_access is for mail that is to delivered from the host machine.  I'm not clear on client_access.  Is that for clients that want to send mail from this host, or for clients that want to have the host receive their mail?

So for sender_access I have in mind something like this: *Quote:*   

> my_buddy@  OK
> 
> someone_else@their_email_address OK
> 
> lots more like these
> ...

 

The hope is that if I reject a domain the appears in the OK part of the list the mail still arrives.  I'm concerned that sed will pick up valid mail and make up an entry for the bottom part of the list.  If this works as I hope then that should not be a problem.  Otherwise, how do we insure that sed is not picking up domain names for valid mail?

I'll try to do something with sed as soon as I'm clear on what to extract.  Thanks,

Fred

----------

## khayyam

freke ...

there is probably numerious blacklisting scripts out there for postfix, but this bascially produces the desired output (input is the above log snippit). 

```
# awk '{gsub(/[<|>|:]/,"") ; if ($15~/rejected/) print $12,"REJECT"}' input

purchase@kalyanimotors.com REJECT
```

You would probably want to sort/uniq, and compare to the current sender_access, plus do some sanity checking and/or reversion to the previous sender_access if postfix fails to restart. That said, I'm sure there are better solutions out there ... that is just a quick stab at the problem.

best ... khay

----------

## Fred Krogh

I am now thinking more of writing code in C, that could be called as a cronjob.  It would do the following.

1. Get a date/time from a special file, see 5 below.  Open the log file, and the sender_access file.

2. Allocate plenty of memory for the sender_access file and save it in an array.

2. Search the log file for a date later than the date from 1 above.

3. Look for postfix if found look for @.  Check if sender@address in in the "OK" section of the sender_access file.  If so look for the next @, etc.  When not in the "OK" section continue with 4.

4. Search for the sender@address in the "REJECT" section of the sender_access file.  If no match, write at the bottom of the sender_access array.  On a partial match, replace the "REJECT" entry with a shorter version.  Write all changes to a changes file.

5. When get to the end of the log file, write the date/time to that special file mentioned in 1.

6. Mail the changes file to the administrator for postfix on this machine.

7. Sort the lines in the "REJECT" part of the sender access array, move the current sender_access file to a backup and write the sender_access array to the sender_access file.

8. call postmap to rehash the sender_access file.

9. Optional depending on circumstances, reload postfix.

This doesn't look that hard to do, but does it makes sense?  Any thoughts welcome.

----------

## freke

Thanks - I'll have a close look on it.

I only posted a few limited lines of the log - the from=<address> is not always in the same place/field - but you sure got me going, thx  :Very Happy: 

It might have been a spur of the moment and influence of a couple of beers  :Smile: 

I wouldn't really want to do this too automagically.

Also this is is the only/first from= address I've noticed this abusive (it reached a count of 548 in 24 hrs - but has gone now).

And none of the spam from the address got through - I just would like to block it as early in the process as possibly (I'd like to save as much processing power as possible  :Smile: )

----------

## Fred Krogh

I probably don't need to know what you want to look for.  I've started the process of writing code.  No code is actually written, but I'm getting closer to knowing what I want to do.  I'll have my own hash table that will be saved in a file, and reloaded when the program is run.  It will make entries that are marked as candidates for adding to sender_access, and some mechanism for a person to make this happen.  The part of scanning the message file should be the easy part.  The whole thing does not look to bad.

----------

## Fred Krogh

I'm confused about access lists.  Looking at http://www.postfix.org/postconf.5.html#smtpd_client_restrictions I see among other things:

check_sender_access type:table

Search the specified access(5) database for the MAIL FROM address, domain, parent domains, or localpart@, and execute the corresponding action.

check_sender_a_access type:table

Search the specified access(5) database for the IP addresses for the MAIL FROM domain, and execute the corresponding action. Note: a result of "OK" is not allowed for safety reasons. Instead, use DUNNO in order to exclude specific hosts from blacklists. This feature is available in Postfix 3.0 and later.

check_client_access type:table

Search the specified access database for the client hostname, parent domains, client IP address, or networks obtained by stripping least significant octets. See the access(5) manual page for details.

Given the second one listed, I have to think that the last is to check whether an IP address is allowed to send mail from the current host.  It would be nice if "client" were defined.  Could anyone verify that client means this is for the outgoing mail?

Also it seems that in addition to collecting stuff for check_sender_access one could also collect data for check_sender_a_access, on the theory that perhaps the spammers are unlikely to spoof both.  Having both does not seem to carry a lot of overhead, as one could check one and if is found not worry about the other.  But if one is not found, then the other could be collected as well.

Also for IP addresses, one might want to use a cidr type entry for some email addresses, and a simple hash for the others.  So can one have both

   check_sender_a_access hash:/etc/postfix/maps/sender_a_access   and

   check_sender_a_access cidr:/etc/postfix/maps/sender_a_access_cidr

It seems I'm spending all my time trying to understand just what the postfix tables do, rather than writing code.

----------

