Eurosonic/Noorderslag

Op dit moment zit ik op de basis-EHBO-post van Noorderslag, leuk wat voor klusjes je kan krijgen als je je diploma hebt gehaald :).

Gister was ik deel van een loopteam op Eurosonic en daar werden Gerard en ik waarrempel geinterviewd door een meisje van 3voor12, lees het stukje hier (mirror)!

Postfix Relay Recipient Maps

A friend of mine, whose server acts as secondary mailserver for my domains, suggested I read http://macnugget.org/projects/postfixrelaymaps/ and proposed to implement it to reduce spam by refusing mail for non-existing users. For the specific ideas I recommend you read the article.

The solution offered did not match my situation, so I had to modify it a bit. The first problem was that the original script parses only /etc/passwd and the aliasfiles of Postfix itself. I also have virtual aliases and multiple domains, so I modified it to parse those too, you can download it here (parse_relays.pl.gz). At that moment I was thinking about how to automate it further.

The original script uses scp to transfer a generated file and the database generated from that to the secondary mailserver. It checked if there were any changes before doing that though, this meant that if I were to automate that, it would be with a crontab and thus polling. Luckily there are more efficient methods in Linux: inotify.

Inotify is a kernel-subsystem which can watch files for events, like opening, writing and closing and it does this without polling! I installed inotify-tools and use the inotifywait tool to watch a couple of files, if they are altered the shellscript continues running and will parse the files and send the result to the secondary mailserver, where a new database will be generated.

#!/bin/sh
 
FILES="/etc/passwd /etc/aliases.db /etc/postfix/aliases.db \
        /etc/postfix/virtual.db /etc/postfix/domains"
 
case "$1" in
    start)
        echo "Starting Postfix Relay updater."
        /root/bin/update_relays.sh &
        exit
        ;;
    stop)
        exit
        ;;
esac
 
while true; do
    # Wait for filemodifications
    inotifywait -qqe MODIFY ${FILES}
 
    # Sleep half a second to prevent bashing
    sleep 0.5
 
    # Send the file to the secondary mailserver
    /root/bin/parse_relays.pl |
        ssh -qTi ~/.ssh/postfix_relay user@mail2.example.org
done

To automate the transfer to the secondary mailserver, I generated a ssh-key on the primary (ssh-keyget -t dsa -f /path/to/key). The public-key part of this key should be transfered to the secondary mailserver and placed in ~/.ssh/authorized_keys, prepended by something like from="1.2.3.4",command="/home/user/bin/receive_relays.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty.

receive_relays.sh is executed at the moment an ssh-connection comes in which authenticates itself with the generated key. It places everything from stdin in ~/.relay/relay_example_org and runs postmap on it.

#!/bin/sh
 
RELAY_FILE="/home/user/.relay/relay_example_org"
 
# Update the file
cat >${RELAY_FILE}
 
# Create the Postfix database
/usr/sbin/postmap ${RELAY_FILE}

If Postfix is configured correctly (see the part about relay_recipient_maps in above article) all should be well and completely automated!