Here’s a short and pretty self-desctriptive recipe to make your Postfix to send outgoing messages from different IP-addresses switching them on a round-robin basis.
First of all, we’ll need the list of IP-addresses in our roundabout, let’s put them to the /etc/postfix/roundabout
file:
1 2 3 4 |
172.16.13.1 172.16.13.2 172.16.13.3 172.16.13.4 |
Then we’ll need the script to add IP-address aliases to our network interface. Surely, you can add them to the operating system configuration, but I’d suggest you to keep them all to the same /etc/postfix/roundabout
file, so let’s put it to the /root/bin/roundabout_aliases.sh
file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
#!/bin/bash PATH=/bin:/sbin ROUNDABOUT_SPOOL=/etc/postfix/roundabout DEVICE=eth0 if [ ! -r "${ROUNDABOUT_SPOOL}" ]; then echo "Can't read Roundabout configuration (${ROUNDABOUT_SPOOL})" >&2 exit 13 fi COUNT=0 FOUND=0 ADDRESSES=($(ip addr show "${DEVICE}" | sed -r -n "s/^[[:space:]]*inet ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\/([0-9]{1,2}).*$/\1/gp")) while read LINE; do ADDRESS=$(echo "${LINE}" | sed -nr "s/^[[:space:]]*([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})[[:space:]]*\$/\1/pi") if [ -z "${ADDRESS}" ]; then continue fi for TEST in ${ADDRESSES[@]}; do if [ "${TEST}" = "${ADDRESS}" ]; then continue 2; fi done ip address add "${ADDRESS}" dev "${DEVICE}" done < "${ROUNDABOUT_SPOOL}" |
If we want this script to be invoked automatically when the network interface starts, let’s create or modify the /sbin/ifup-local
script (if we have a CentOS/RedHat-based system):
1 2 3 4 5 |
#!/bin/sh if [ "$1" -eq "eth0" ]; then /root/bin/roundabout_aliases.sh fi |
And now, the last, but not ever least, let’s implement the little script to change the smtp_bind_address
value in our /etc/postfix/postfix.conf
configuration. Let’s call it /root/bin/roundabout-postfix.sh
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
#!/bin/bash PATH=/bin:/sbin:/usr/sbin ROUNDABOUT_SPOOL=/etc/postfix/roundabout POSTFIX_CONFIG=/etc/postfix/main.cf if [ ! -r "${POSTFIX_CONFIG}" ]; then echo "Can’t read Postfix configuration (${POSTFIX_CONFIG})" >&2 exit 13 fi SMTP_BIND_ADDRESS=$(cat "${POSTFIX_CONFIG}" | sed -nr "s/^[[:space:]]*smtp_bind_address[[:space:]]*=[[:space:]]*([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})[[:space:]]*\$/\1/pi") if [ -z "${SMTP_BIND_ADDRESS}" ]; then echo "Can’t determine the current IP-address" >&2 exit 13 fi if [ ! -r "${ROUNDABOUT_SPOOL}" ]; then echo "Can’t read Roundabout configuration (${ROUNDABOUT_SPOOL})" >&2 exit 13 fi COUNT=0 FOUND=0 while read LINE; do ADDRESS=$(echo "${LINE}" | sed -nr "s/^[[:space:]]*([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})[[:space:]]*\$/\1/pi") if [ -z "${ADDRESS}" ]; then continue fi COUNT=$((COUNT+1)) if [ "${COUNT}" -eq 1 ]; then ADDRESS1="${ADDRESS}" fi if [ "${FOUND}" -eq 1 ]; then SMTP_BIND_ADDRESS_NEW="${LINE}" break fi if [ "${LINE}" = "${SMTP_BIND_ADDRESS}" ]; then FOUND=1 fi done < "${ROUNDABOUT_SPOOL}" if [ -z "${ADDRESS1}" ]; then echo "There are no entries in the Roundabout spool" >&2 exit 13 fi if [ -z "${SMTP_BIND_ADDRESS_NEW}" ]; then SMTP_BIND_ADDRESS_NEW="${ADDRESS1}" fi sed -r -i -e "s/^[[:space:]]*smtp_bind_address[[:space:]]*=[[:space:]]*([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})[[:space:]]*\$/smtp_bind_address = ${SMTP_BIND_ADDRESS_NEW}/i" "${POSTFIX_CONFIG}" if [ "${?}" -ne 0 ]; then echo "Something went wrong :-(" >&2 exit 13 fi postfix reload >/dev/null 2>&1 if [ "${?}" -ne 0 ]; then echo "Something went wrong :-(" >&2 exit 13 fi |
You can run this script by cron or when certain event happens (e.g., when the current IP-address has been blacklisted).
And don’t forget to add something like smtp_bind_address = 0.0.0.0
to the /etc/postfix/main.cf
file before to run this script for the first time, in other case it won’t find the IP-address to be changed! 🙂