This time i’ll show you how to randomize your smtp outbound’s IP addresses. This can be done via transport map. But, since ordinary Postfix lookup tables store information as (key, value) pairs. it will provide static value only. we need someting that can manipulate the value (right hand side) of a lookup table. In order to answer random transport value.
first come to mind was tcp_tables, tcp_tables lookup table gives some flexibility for us to execute our tiny perl script that will randomizing transport. that’s the basic idea.
Ok, here’s the first part, create perl script call random.pl, anyway this script only provide answer in “catch-all” manner. so it will randomized, all outgoing mail.
# cd /etc/postfix # vi random.pl
#!/usr/bin/perl -w # author: Hari Hendaryanto <hari.h -at- csmcom.com> use strict; use warnings; use Sys::Syslog qw(:DEFAULT setlogsock); # # our transports array, we will define this in master.cf as transport services # our @array = ( 'rotate1:', 'rotate2:', 'rotate3:', 'rotate4:', 'rotate5:' ); # # Initalize and open syslog. # openlog('postfix/randomizer','pid','mail'); # # Autoflush standard output. # select STDOUT; $|++; while (<>) { chomp; # randomizing transports array my $random_smtp = int(rand(scalar(@array))); if (/^get\s(.+)$/i) { print "200 $array[$random_smtp]\n"; syslog("info","Using: %s Transport Service", $random_smtp); next; } print "200 smtp:"; }
Make it executable
# chmod 755 random.pl
master.cf parts
Run the scripts via postfix spawn daemon service.
127.0.0.1:2527 inet n n n - 0 spawn user=nobody argv=/etc/postfix/random.pl
add 5 smtp client services called rotate1, rotate2, rotate3, rotate4, rotate5, that bind to its own ip
address and has uniq syslog/helo name.
# random smtp rotate1 unix - - n - - smtp -o syslog_name=postfix-rotate1 -o smtp_helo_name=smtp1.example.com -o smtp_bind_address=1.2.3.1 rotate2 unix - - n - - smtp -o syslog_name=postfix-rotate2 -o smtp_helo_name=smtp2.example.com -o smtp_bind_address=1.2.3.2 rotate3 unix - - n - - smtp -o syslog_name=postfix-rotate3 -o smtp_helo_name=smtp3.example.com -o smtp_bind_address=1.2.3.3 rotate4 unix - - n - - smtp -o syslog_name=postfix-rotate4 -o smtp_helo_name=smtp4.example.com -o smtp_bind_address=1.2.3.4 rotate5 unix - - n - - smtp -o syslog_name=postfix-rotate5 -o smtp_helo_name=smtp5.example.com -o smtp_bind_address=1.2.3.5
Before we actually implement our randomize transport, let’s make sure that the setting actually work.
Reload postfix
# postfix reload
Run this query fiew times, and you’ll see the perl script will return “random answer” transport
# postmap -q "whatever" tcp:127.0.0.1:2527 rotate1:
# postmap -q "whatever" tcp:127.0.0.1:2527 rotate5:
And so on..
Note on “whatever”, since the script acted in “catch-all” mode as i’ve mentioned earlier, what ever postfix transport_maps client asked. it will be answered with random values such as rotate1, rotate2, rotate3, rotate4, rotate5 in randomized fashion.
main.cf parts
Add these lines
transport_maps = tcp:[127.0.0.1]:2527 127.0.0.1:2527_time_limit = 3600s
Reload postfix
that’s it. example log would be like these and that’s indicate that randomizer is working.
Month date 12:26:53 host postfix-rotate1/smtp[4252]: A1CA68480A4: to=<xxx@example.com>, relay=mx.example.com.com[xx.xx.xxx.xx]:25], delay=3.6, delays=0.69/0.01/0.81/2, dsn=2.0.0, status=sent (250 ok dirdel) --snip-- Month date 12:27:06 host postfix-rotate5/smtp[4253]: 41C2E8480A4: to=<xxx@example.net>, relay=mx.example.net[xx.xxx.xxx.xxx]:25], delay=6, delays=0.14/0.01/0.85/5, dsn=2.0.0, status=sent (250 ok dirdel) --snip-- Month date 12:27:22 host postfix-rotate3/smtp[4277]: 4BA9F8480A4: to=<xxx@example.org>, relay=mx.example.org[xx.xxx.xx.xxx]:25], delay=7.9, delays=0.85/0.02/0.61/6.4, dsn=2.0.0, status=sent (250 ok dirdel)
disclaimer:
I’m not taking any responsible if the reader “misuse” this tutorial.the tutorial is provide as-is for experimental purposes.
I like your new tut, would probably perform better with more IPs than your IPtables tut… What do you think would be the max of IPs a setup like this could handle to rotate?
it depend on hardware resource, i think. as usual, this tutorial is just a prototype, but it work. 🙂
I will try it out at the beginning of the year and let you know how it performs 😉
Thank you, this is very neat.
Do not forget to add best_mx_transport = local of you may face the dreaded “mail loops back to myself”.
Also, I modified your script to add “weight” to the SMTP clients, so that randomness is not truly random. This is useful if you add a new IP address to the pool, so it does not get blacklisted as soon as it starts sending emails.
my %pool = (
“smtp1” => 20,
“smtp2” => 20,
“smtp3” => 20,
“smtp4” => 40
);
Last but not least, how do you maintain specific transport for specific domains? Eg some SMTP servers require a “slow transport” such as what is described in http://www.pubbs.net/postfix/200909/98526/
You would need to process the request in order to check the target domain, to see if you return a random SMTP or a specific transport.
Regards,
Amaury
that’s cool with weighted feature you’ve added. fyi, the reason i’ve wrote this script was not for doing spammy things. this just for fun in my spare time 🙂 i work in legal ISP
if you want to filter specific domain/destination to certain transport. you have just to “hardcoded” in the script.
create conditional filter before default action/randomize. ie
to_slow_yahoo: can be randomize too with slow transport specific settings and specific ip pools
says, …to_slow_yahoo1: to_slow_yahoo2: to_slow_yahoo3: etc…
this untested yet
Regarding specific transports I came up with a similar solution, although it is used the other way around:
– normal mail go through a specific transport name “standard”
– mail sent to mailservers using conservative SMTP rates (such as RIM SMTP relays or Orange MXs) go through the randomizer. This way only the emails which need to be randomized are randomized, and they can be sent without much delay to their recipient.
This is not very efficient as you lose the “db” format which is favored by Postfix for this matter.
Last but not least you should remember that this technique (known as “snowshoeing” in the email deliverability community) is frowned upon and that it should not be abused, even to perform legit operations…
about postfix “db”, it’s not quite true that you’re loosing them. you can still access them through perl
little example, for “hash” lookup table
hash file
i know this technique similar to snowshoeing :). that’s why i put disclaimer at the bottom of my posting.
however, you can tune your outgoing not too greedy with concurency recipients, messages, or connection, set your dns reverse.
if your traffic are legit, it’s like you own 100 machine in single box if you have 100 ip 🙂
Hi,
could you please post your modificated version with “weight” implemented? I try to implement it, but it is not working… I am not a very good programmer 🙁
Thank you
Lukas
“Do not forget to add best_mx_transport = local of you may face the dreaded “mail loops back to myself””
If you use postfix with virtuals users :
best_mx_transport = virtual
Regards,
Cidou
since i used it just for smtp relay, in experiment, no local/virtual user, so it doesn’t really matter.
but thanks for noticing anyway
I’m finally implementing this for some testing, but I have stumbled across something.
I already have a transport_maps entry pointing:
transport_maps = hash:/etc/postfix/transport
In that file I have entries for specific domains that will use another relay server, e.g.
ch***.com smtp:***.***.211.74
Any ideas on how I can combine my existing transport_maps with yours?
try this
Works great 😉
Do you have an idea on how to implement this based on sending domain?
E.g. mails from domain1.com get a random in the perl from rotate1 – rotate3, domain2.com get random in the perl from rotate4-rotate9, domain3.net get random in the perol from rotate10-rotate12 – and the master contains the IP, helo_name etc
Basically what I am looking for, is a way to tell the perl from which array it should take a random based on the senderdomain.
that cannot be done in transport_maps, maybe you can use sender_dependent_relayhost_maps. i’ve never try it, though.
Hello,
Thanks for your great tutorials.
With reference to:
Amaury says: january 22, 2011 at 2:14 am
my %pool = (
“smtp1″ => 20,
“smtp2″ => 20,
“smtp3″ => 20,
“smtp4″ => 40
);
I am a newbie and I would like to add that feature.
Could you please add this feature to your tutorial?
I do not know how or where.
i think it’s not as simple by adding %pool hash in original code. that’s only variable. but basically that refer to “weight value” you can access with:
you should add “round robin weighted” algorithm rather than randomness to the script.
http://kb.linuxvirtualserver.org/wiki/Weighted_Round-Robin_Scheduling.
this example might not what you want, but it’s simple, you can play with this code.
require List::Util::WeightedRoundRobin module
This code still randomize but not as random as original script.
Hello,
Is there a way to change rotator every XX emails sent with
this method like in “postfix-smtp-outgoing-ip-rotator-using-iptables”?
I like the iptables method and it works very well but
it does not rotate the hostname, so there is bad inboxing rate.
Is there a way to rotate the hostname with the iptables method?
try this:
http://www.kutukupret.com/2011/05/22/postfix-rotating-outgoing-ip-using-tcp_table-and-perl/
hello,
thx for the script.
i have a small problem.
i send an email and look to the header:
Received: from smtp.example.1 (EHLO smtp.example.1) [xx.xx.xx.xx]
…
Received: by MYHOSTNAME.COM (Postfix, from userid 48)
ip and domain rotating works find – but why in header is written my hostname? how i can change the hostname that it will be the same like the smtp_helo_name.
i tried
rotate1 unix – – n – – smtp
-o syslog_name=postfix-rotate1
-o myhostname=smtp.example.1
-o smtp_bind_address=XX.XX.XX.XX
-o myhostname=smtp.example.1
but it doesnt work.
can you help me?
may be you want
note on -o smtp_helo_name=smtp.example.1
same with rest of rotate2, rotate3…
Guys, a really quick dirtyfix for rotate-weightning in 10% steps is to duplicate the entries in the array, e.g.:
our @array = (
‘rotate1:’,
‘rotate1:’,
‘rotate1:’,
‘rotate2:’,
‘rotate3:’,
‘rotate3:’,
‘rotate4:’,
‘rotate4:’,
‘rotate5:’,
‘rotate5:’
);
that would be okay, but using rand function the results still always random.
i wrote something more interesting here:
http://www.kutukupret.com/2011/05/22/postfix-rotating-outgoing-ip-using-tcp_table-and-perl/
Hi;
It not works in my postfix server. i am getting “postmap: fatal: unsupported dictionary type: tcp” error.Are you doing freelance jobs ? I need this immediatly.Thanks
your postfix installation does not support tcp_table, i suggest installing the latest distribution.
i used to do freelance job when i have time.
when using the tcp random transport table , the local mail which send to root will log an loopback error
tgis article intended works on smtp relay not local mail, but someone in this comment suggest to set best_mx_transport = local
Cidou says:
February 24, 2011 at 9:25 am (Edit)
“Do not forget to add best_mx_transport = local of you may face the dreaded “mail loops back to myself””
If you use postfix with virtuals users :
best_mx_transport = virtual
Regards,
Cidou
I already have a transport_maps entry pointing:
transport_maps = mysql:/etc/postfix/mysql_transport_maps
error: postfix/smtpd[20302]: NOQUEUE: reject: RCPT from localhost[127.0.0.1]: 550 5.1.1 : Recipient address rejected: User unknown; from= to= proto=ESMTP helo=
I try
transport_maps = mysql:/etc/postfix/mysql_transport_maps, tcp:[127.0.0.1]:2527
but cannot resolve
How did you test that?why there’s no “from” address , “to” address and helo?
Just a feedback. The script is running ok but…but…after two days of sending I get the following error :”smtp postfix/qmgr[20602]: fatal: fcntl F_DUPFD 128: Too many open files”.
Regards
Andrei 🙂
that’s postfix errors, look likes you ran out of file descriptor, you should tuned up you box, increase maximum file that can be opened (man ulimit).
i ran this setup years without any problem 🙂
What value do you suggest it will be enough? Thank you for you kind support.
well, that depends on your hardware..
Hey,
I’m using your code but when sending an e-mail to myself, I’m getting the following error message in the log file:
to=, relay=none, delay=1.9, delays=0.21/0/1.7/0, dsn=5.4.6, status=bounced (mail for *** loops back to myself
where *** is my domain.
Any idea where it comes from?
postmap -q “whatever” tcp:127.0.0.1:2527
postmap: warning: read TCP map reply from 127.0.0.1:2527: malformed reply: Can’t open -o: No such file or directory at /etc/postfix/random.pl line 23.
postmap: fatal: tcp:127.0.0.1:2527: query error: Operation now in progress
What i’m doing wrong?
Thanks!
post your whole script here
PS:
line 23 on my script is:
while () {
when i check
postmap -q “whatever” tcp:127.0.0.1:2527
then back message : “postmap: fatal: unsupported dictionary type: tcp”
how do i fix it?
what version of postfix did you use? you have to upgrade to recent postfix in order for tcp table to work
hi,
i have completed all step, but running no good. it cannot sending out email, connect always online.
how do i fix it?
look the netstat , its ” TIME WAIT”
hello,
need your help.
i run the follow as :
[root@mail ~]# postmap -q “whatever” tcp:127.0.0.1:2527
and get back message
rotate1:
but it cannot sent out email.connect always online ,
netstat -antp | grep 2527
tcp 0 0 *.*.*.*:25 *.*.*.*:44980 ESTABLISHED 1903/spawn
outlook show in the connecting.
log in messages:
Feb 21 19:46:20 mail syslogd 1.4.1: restart.
Feb 21 19:46:20 mail iscsid: iSCSI logger with pid=1496 started!
Feb 21 19:46:20 mail iscsid: Missing or Invalid version from /sys/module/scsi_transport_iscsi/version. Make sure a up to date scsi_transport_iscsi module is loaded and a up todate version of iscsid is running. Exiting…
Feb 21 19:46:22 mail init: no more processes left in this runlevel
hi, do you have time help me for setting this perl ?
I have the following config in master:
rotate5 unix – – n – – smtp
-o syslog_name=postfix-rotate5
-o smtp_helo_name=smtp5.example.com
-o smtp_bind_address=1.2.3.4
-o myhostname=realdomain5.com
But I can’t figure out how to randomize the hostname of the actual server.
For instance:
echo “test” | mail test@test.com
The e-mail headers still show the source as the physical server:
To: test@test.com
Message-Id:
Date: Fri, 18 May 2012 02:50:18 -0400 (EDT)
From: root@freebsd1.myserver.com
The same would happen using PHPMail.
So the master config of mydomain or myhostname does not work… or does not work as I would hope 🙂
The message ID did not post properly.
I was trying to show that the real name of the server appears in the message ID.
I have the following config in master:
rotate5 unix – – n – – smtp
-o syslog_name=postfix-rotate5
-o smtp_helo_name=smtp5.example.com
-o smtp_bind_address=1.2.3.4
-o myhostname=realdomain5.com
But I can’t figure out how to randomize the hostname of the actual server.
For instance:
echo “test” | mail test@test.com
The e-mail headers still show the source as the physical server:
Message-Id: 201205189090980980998.D11090090991721C@freebsd1.myserver.com
well, when you’re using “mail” command for testing in server, apparantly it will call “sendmail” command, which is not goes through tansport_maps. so ramdomize script will never work. and we cannot override “myhostname” in master.cf, AFAIK.
Hello.
I’m using your post for implementing random rotation with 10 IPs and all is working great.
Do you have an idea how to implement random rotation based on sender domain ?
– @example.com, use random IPs from 1…5
– @example.net, use random IPs from 6…8
– @example.org, use random IPs from 9…10
Please contact me if you need more info.
Regards,
/Sorin
i wrote article about sender based outgoing mail, just look for related article and combine those article with this randomize smtp
cheers
Hello.
I did see this article [http://www.kutukupret.com/2011/05/28/postfix-bind-sender-outgoing-ip-based-on-geoip-location], but I’m not so good in Perl.
Based on this, if I’ll use the code below, I will get Sender domain or Destination domain ?
while () {
chomp;
if (/^get\s(.+)$/i) {
# extract domain from email
my @email = split(/@/, $1);
my $domain = $email[1];
On the other hand, if I can’t make it work, are you available for a quick freelance job, to sort this out ?
Regards,
/Sorin
yes, you can modified perl script into something like that, extracting every recipient domain, and create array for each domain.
and so on..something like that..
right now, i’m bussy with my main job, i still don’t have spare time to make any experiment.. i don’t even have any chance updating my blog 😀
I was thinking of something like that, the only problem is by using that code I’ll get “To: email address (recipient)”. I will need “From: email address (sender)”.
Any hint how can I get that in ?
Do I have to pass sender in main.cf ? If yes, how can I process it from Perl ?
I’ve tried several scenarios and all wrong 🙁
Thanks in advance.
instead of using transport_maps, you can try using sender_dependent_default_transport_maps, however this feature exist prior to postfix-2.7-20091209 and newer.
main.cf
i’ve never tested that, but that would be work, i guess 🙂
This script works fine and dandy for outgoing mail but if you try to send mail into the server you get loopback errors and the mail fails. Any idea on how to correct this so mail sent out can be replied to and the mail coming into the server lands in the users mail box instead of being bounced?
actually, i wrote this article intended for outgoing submission emails only, but someone set it could be fix with this set
http://www.kutukupret.com/2010/12/06/postfix-randomizing-outgoing-ip-using-tcp_table-and-perl/comment-page-2/#comment-21962
I’ve deployed this configuration, but it has a strange behaviour…
Delivered-To: jesusrafael@gmail.com
Received: by 10.194.16.5 with SMTP id b5csp211917wjd;
Sun, 11 Nov 2012 13:18:54 -0800 (PST)
Received: by 10.69.1.1 with SMTP id bc1mr52225163pbd.102.1352668734095;
Sun, 11 Nov 2012 13:18:54 -0800 (PST)
Return-Path:
Received: from mail2.quedondeycuanto.com (mail3.quedondeycuanto.com. [184.95.62.36])
by mx.google.com with ESMTP id ux7si6960278pbc.12.2012.11.11.13.18.53;
Sun, 11 Nov 2012 13:18:53 -0800 (PST)
Received-SPF: pass (google.com: domain of info@quedondeycuanto.com designates 184.95.62.36 as permitted sender) client-ip=184.95.62.36;
Authentication-Results: mx.google.com; spf=pass (google.com: domain of info@quedondeycuanto.com designates 184.95.62.36 as permitted sender) smtp.mail=info@quedondeycuanto.com
Received: by ns1.quedondeycuanto.com (Postfix, from userid 514)
id 79FA76EE006A; Sun, 11 Nov 2012 17:18:52 -0400 (AST)
From: "Correo Destinatario"
Subject: prueba
To: jesusrafael@gmail.com
Message-Id:
Cc: gsusrafael@hotmail.com
X-Originating-IP: 190.167.170.29
X-Mailer: Usermin 1.520
Date: Sun, 11 Nov 2012 17:18:52 -0400 (AST)
Content-Type: text/plain
could you please explain this to me?
can you point me what exactly “strange behaviour” specifically? i’ve just seen different helo name bound to different ip/hostname there.
that might be typo in your master.cf.
It isn’t a typo, anyways i’ll check it again…
from mail2.quedondeycuanto.com (mail3.quedondeycuanto.com. [184.95.62.36])
but the rotator must only change the ip address and its respective hostname, unlike is shown above
i’ve never seen that failure before, if you sure not doing any typo, could it be you dns setup not properly propagate(gmail resolver cache old data).
well, everything is possible.
i can send you the main.cf and the master.cf to your mail if you don’t mind… to ensure there is no mistake in those configs
sure, you can post here master.cf rotate related part.
Right now there is other problem…
This is the mail system at host ns1.quedondeycuanto.com.
I'm sorry to have to inform you that your message could not
be delivered to one or more recipients. It's attached below.
For further assistance, please send mail to postmaster.
If you do so, please include this problem report. You can
delete your own text from the attached returned message.
The mail system
(expanded from
): unknown user:
"jjescobar.quedondeycuanto@ns1.quedondeycuanto.com"
Final-Recipient: rfc822; jjescobar.quedondeycuanto@ns1.quedondeycuanto.com
Original-Recipient: rfc822;jjescobar@quedondeycuanto.com
Action: failed
Status: 5.1.1
Diagnostic-Code: X-Postfix; unknown user:
"jjescobar.quedondeycuanto@ns1.quedondeycuanto.com"
This is the log part i got…
Nov 18 23:11:05 ns1 postfix/virtual[12699]: 2AE0D6EE0082: to=jjescobar.quedondeycuanto@ns1.quedondeycuanto.com>, orig_to=, relay=virtual, delay=1.4, delays=1.3/0.01/0/0.03, dsn=5.1.1, status=bounced (unknown user: "jjescobar.quedondeycuanto@ns1.quedondeycuanto.com")
when i first wrote the article, it was intended to be used for outgoing email only, no local/virtual user in the system.
script works in catchall ways. but you can always make exception for local/virtual user in the script.
example:
cheers
Excellent, now is working like a charm!!!!!!
Thanks for all!!!!!!
Hi I would like to have postfix listen to as many as 20-30 different IP/Domain combinations and when sending email use the specific IP/Domain info in the header as was used by the client.
For example:
User 1 uses the domain mail.mymail1.com to send email with IP 1.1.1.1
User 2 uses the domain mail.mymail2.com to send email with IP 2.2.2.2
I need the header of each email to use that specific domain/ip per user.
Please Help,
Thanks
that would be involving header_checks on each domain to replace/append custom header. i’m not figuring that out yet.
Using your solution how we can implement Throttling per domain? It’s possible? Because Throttling involve to manipule the transport too.
Thanks,
Wilson
you can make exception for some domain in perl script, can i see how did you throttle mails?
Hi…. I have seen this tutorial. Right now i am following this tutorial. Every thing is fine. But the mail log report is not showing like below.
Month date 12:26:53 host postfix-rotate1/smtp[4252]: A1CA68480A4: to=, relay=mx.example.com.com[xx.xx.xxx.xx]:25], delay=3.6, delays=0.69/0.01/0.81/2, dsn=2.0.0, status=sent (250 ok dirdel)
my mail server mail log is given below.
Aug 26 17:55:02 ms14 postfix/local[18140]: 26F3D2C1D7D: to=, orig_to=, relay=local, delay=0.81, delays=0.68/0.06/0/0.08, dsn=2.0.0, status=sent (delivered to maildir)
but i am not seeing mail log report like below
postfix-rotate1/smtp[4252]
where did i mistake i am not getting ? Please solve the issue
Adv…… Thanks
hi to all ………..
first thanks for this tutorial.
I followed this tutorial as it is.
i am facing one problem with mail log. I am not getting like what you have given.
Month date 12:26:53 host postfix-rotate1/smtp[4252]: A1CA68480A4: to=, relay=mx.example.com.com[xx.xx.xxx.xx]:25], delay=3.6, delays=0.69/0.01/0.81/2, dsn=2.0.0, status=sent (250 ok dirdel)
please my maillog is given below
Aug 27 17:39:57 ms14 postfix/smtp[23233]: B2E942C1D7D: to=, relay=mta5.am0.yahoodns.net[98.138.112.33]:25, delay=4.6, delays=0.23/0/2/2.4, dsn=2.0.0, status=sent (250 ok dirdel)
please check it once and tell me where did i mistake ?
advanced thanks
………..
let’s see what you’ve got in your master.cf
Dear leenoux,
thanks for your reply. please check it my master.cf
#
2 # Postfix master process configuration file. For details on the format
3 # of the file, see the master(5) manual page (command: “man 5 master”).
4 #
5 # Do not forget to execute “postfix reload” after editing this file.
6 #
7 # ==========================================================================
8 # service type private unpriv chroot wakeup maxproc command + args
9 # (yes) (yes) (yes) (never) (100)
10 # ==========================================================================
11 smtp inet n – n – – smtpd
12 submission inet n – n – – smtpd
13
14 smtps inet n – n – – smtpd
15 -o smtpd_sasl_auth_enable=yes
16 -o smtpd_reject_unlisted_sender=ye
17 -o smtpd_sasl_security_options=noanonymous
18 -o smtpd_sasl_local_domain=hire-now.com
19 -o header_checks=
20 -o body_checks=
21 -o smtpd_client_restrictions=permit_sasl_authenticated,reject_unauth_destination
22 -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject_unauth_destination
23 -o smtpd_sasl_security_options=noanonymous,noplaintext
24 -o smtpd_sasl_tls_security_options=noanonymous
25 -o broken_sasl_auth_clients=yes
26
27 #submission inet n – n – – smtpd
28 # -o smtpd_tls_security_level=encrypt
29 # -o smtpd_sasl_auth_enable=yes
30 # -o smtpd_client_restrictions=permit_sasl_authenticated,reject
31 # -o milter_macro_daemon_name=ORIGINATING
32 #smtps inet n – n – – smtpd
33 # -o smtpd_tls_wrappermode=yes
34 # -o smtpd_sasl_auth_enable=yes
35 # -o smtpd_client_restrictions=permit_sasl_authenticated,reject
36 # -o milter_macro_daemon_name=ORIGINATING
37 #628 inet n – n – – qmqpd
38 pickup fifo n – n 60 1 pickup
39 cleanup unix n – n – 0 cleanup
40 qmgr fifo n – n 300 1 qmgr
41 #qmgr fifo n – n 300 1 oqmgr
42 tlsmgr unix – – n 1000? 1 tlsmgr
43 rewrite unix – – n – – trivial-rewrite
44 bounce unix – – n – 0 bounce
45 defer unix – – n – 0 bounce
46 trace unix – – n – 0 bounce
47 verify unix – – n – 1 verify
48 flush unix n – n 1000? 0 flush
49 proxymap unix – – n – – proxymap
50 proxywrite unix – – n – 1 proxymap
51 smtp unix – – n – – smtp
52 # When relaying mail as backup MX, disable fallback_relay to avoid MX loops
53 relay unix – – n – – smtp
54 -o smtp_fallback_relay=
55 # -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
56 showq unix n – n – – showq
57 error unix – – n – – error
58 retry unix – – n – – error
59 discard unix – – n – – discard
60 local unix – n n – – local
61 virtual unix – n n – – virtual
62 lmtp unix – – n – – lmtp
63 anvil unix – – n – 1 anvil
64 scache unix – – n – 1 scache
65 #
66 # ====================================================================
67 # Interfaces to non-Postfix software. Be sure to examine the manual
68 # pages of the non-Postfix software to find out what options it wants.
69 #
70 # Many of the following services use the Postfix pipe(8) delivery
71 # agent. See the pipe(8) man page for information about ${recipient}
72 # and other message envelope options.
73 # ====================================================================
74 #
75 # maildrop. See the Postfix MAILDROP_README file for details.
76 # Also specify in main.cf: maildrop_destination_recipient_limit=1
77 #
78 #maildrop unix – n n – – pipe
79 # flags=DRhu user=vmail argv=/usr/local/bin/maildrop -d ${recipient}
80 #
81 # ====================================================================
82 #
83 # The Cyrus deliver program has changed incompatibly, multiple times.
84 #
85 #old-cyrus unix – n n – – pipe
86 # flags=R user=cyrus argv=/usr/lib/cyrus-imapd/deliver -e -m ${extension} ${user}
87 #
88 # ====================================================================
89 #
90 # Cyrus 2.1.5 (Amos Gouaux)
91 # Also specify in main.cf: cyrus_destination_recipient_limit=1
92 #
93 #cyrus unix – n n – – pipe
94 # user=cyrus argv=/usr/lib/cyrus-imapd/deliver -e -r ${sender} -m ${extension} ${user}
95 #
96 # ====================================================================
97 #
98 # See the Postfix UUCP_README file for configuration details.
99 #
100 #uucp unix – n n – – pipe
101 # flags=Fqhu user=uucp argv=uux -r -n -z -a$sender – $nexthop!rmail ($recipient)
102 #
103 # ====================================================================
104 #
105 # Other external delivery methods.
106 #
107 #ifmail unix – n n – – pipe
108 # flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
109 #
110 #bsmtp unix – n n – – pipe
111 # flags=Fq. user=bsmtp argv=/usr/local/sbin/bsmtp -f $sender $nexthop $recipient
112 #
113 #scalemail-backend unix – n n – 2 pipe
114 # flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store
115 # ${nexthop} ${user} ${extension}
116 #
117 #mailman unix – n n – – pipe
118 # flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
119 # ${nexthop} ${user}
120 policy unix – n n – 0 spawn user=nobody argv=/usr/bin/perl /usr/lib/postfix/postfix-policyd-spf-perl
121
122 ## Round-robin outgoing smtp
123
124 127.0.0.1:2527 inet n n n – 0 spawn user=nobody argv=/etc/postfix/random.pl
125 #127.0.0.1:23000 inet n n n – 0 spawn user=nobody argv=/etc/postfix/random.pl
126
127 ## random smtp
128
129 #rotate1 unix – – n – – smtp
130 # -o syslog_name=postfix-rotate1
131 # -o smtp_helo_name=ms14.mydomain.com
132 # -o smtp_bind_address=X.X.X.1
133
134
135 rotate1 unix – – n – – smtp
136 -o syslog_name=postfix-rotate1
137 -o smtp_helo_name=ms0.mydomain.com
138 -o smtp_bind_address=X.X.X.2
139
140 rotate2 unix – – n – – smtp
141 -o syslog_name=postfix-rotate2
142 -o smtp_helo_name=ms1.mydomain.com
143 -o smtp_bind_address=X.X.X.3
……………..
which postfix version are you using? is it suporting for tcp_table? when i first create this randomizing methode it’s for outgoing gateway/relay only. not mixing beetween virtual/local maildir and relaying. (there’s a hack in perl script just search in related comments below)
and don’t forget to create bunch of ip aliasing otherwise postfix would fail to bind an ip address.
Dear leenoux,
postfix version is: postfix-2.9.1-1.rhel5.x86_64 and
[root@xxx ~]# postconf -m
btree
cidr
environ
fail
hash
internal
ldap
memcache
nis
proxy
regexp
static
tcp
texthash
unix
I have created IP aliases. like eth0:1, eth0:2, etc.,
still i am not getting maillog status like
postfix-rotate1/smtp[4252]
postfix-rotate2/smtp[4252]
how can i get the maillog status like that ?
…………………
what is in transport_maps? seems like your transport_maps doesn’t read from tcp table and fall to default smtp.
Dear Loonoux,
transport_map details are given below
transport_maps = tcp:/etc/postfix/transport, tcp:127.0.0.1:2527
will I do any changes on transport_maps ?
what is in tcp:/etc/postfix/transport ? when you need to exclude mail for local/virtual delivery, you should do it in perl script. there’s examples at comments section.
Dear Loonoux,
I am having 3 Public IPS
1. one is given STATIC IP
2. installed postfix with dovecot
3. created two IPs as aliases of ethernet, ie., eth0:1, eth0:2
4. created perl script
5. added few lines to main.cf and master.cf from your tutorial for IP rotation.
I am not getting any errors. But i am not seeing the result in maillog as
postfix-rotate1/smtp[4252]
postfix-rotate2/smtp[4252]
is there required any modifications to get the result ?
Incoming mail rejecting…. Log is appended here
Dec 24 07:30:51 host postfix/smtpd[6219]: 989408406FB: client=mail-ve0-f174.google.com[209.85.128.174]
Dec 24 07:30:51 host postfix/randomizer[6225]: Using: smtp16: Transport Service
Dec 24 07:30:51 host postfix/randomizer[6225]: Using: smtp17: Transport Service
Dec 24 07:30:51 host postfix/smtpd[6219]: 989408406FB: reject: RCPT from mail-ve0-f174.google.com[209.85.128.174]: 550 5.1.1 : Recipient address rejected: User unknown in local recipient table; from= to= proto=ESMTP helo=
Dec 24 07:30:51 host postfix/cleanup[6226]: 989408406FB: message-id=
Dec 24 07:30:51 host opendkim[2281]: 989408406FB: mail-ve0-f174.google.com [209.85.128.174] not internal
Dec 24 07:30:51 host opendkim[2281]: 989408406FB: not authenticated
Dec 24 07:30:51 host opendkim[2281]: 989408406FB: DKIM verification successful
Dec 24 07:30:51 host opendkim[2281]: 989408406FB: s=20120113 d=gmail.com SSL
Dec 24 07:30:51 host postfix/qmgr[6216]: 989408406FB: from=, size=2010, nrcpt=2 (queue active)
Dec 24 07:30:51 host postfix/randomizer[6225]: Using: smtp18: Transport Service
Dec 24 07:30:51 host postfix/randomizer[6225]: Using: smtp1: Transport Service
Dec 24 07:30:51 host postfix/smtpd[6219]: disconnect from mail-ve0-f174.google.com[209.85.128.174]
Dec 24 07:30:51 host postfix-rotate1/smtp[6227]: 989408406FB: to=, relay=none, delay=0.34, delays=0.18/0.01/0.14/0, dsn=5.4.6, status=bounced (mail for amritanews.com loops back to myself)
Dec 24 07:30:51 host postfix-rotate1/smtp[6228]: 989408406FB: to=, relay=none, delay=0.34, delays=0.18/0.01/0.14/0, dsn=5.4.6, status=bounced (mail for amritanews.com loops back to myself)
Dec 24 07:30:51 host postfix/cleanup[6226]: E8CF38406FD: message-id=
Dec 24 07:30:51 host postfix/qmgr[6216]: E8CF38406FD: from=, size=4273, nrcpt=1 (queue active)
Dec 24 07:30:51 host postfix/randomizer[6225]: Using: smtp2: Transport Service
Dec 24 07:30:51 host postfix/bounce[6230]: 989408406FB: sender non-delivery notification: E8CF38406FD
Dec 24 07:30:51 host postfix/qmgr[6216]: 989408406FB: removed
Dec 24 07:30:52 host postfix-rotate1/smtp[6231]: connect to gmail-smtp-in.l.google.com[2607:f8b0:400d:c02::1a]:25: Network is unreachable
Dec 24 07:30:52 host postfix-rotate1/smtp[6231]: E8CF38406FD: to=, relay=gmail-smtp-in.l.google.com[173.194.68.26]:25, delay=0.99, delays=0.01/0.01/0.59/0.38, dsn=2.0.0, status=sent (250 2.0.0 OK 1387888253 j7si17727126qab.167 – gsmtp)
Dec 24 07:30:52 host postfix/qmgr[6216]: E8CF38406FD: removed
Hi Leenoux, thank you for a wonderfull script.
I am using it for over 2 years without issues but I have just noticed a strange behaviour/bug?
It always uses the first MX record. When the recepient server replay with 4xx code than postfix should try a different MX server, but it does not. It just queues the message and tries the same MX server again.
Without this script it works fine.
Do you know where the issue could be? What should I fix? Thank you
I have a question about headers. The rotation may or may not be working. Part of my header says server3, but the ip addresses being shown is actually server1. No matter which hostname is shown, it always shows the same xx.xxx.xxx.9 ip address. Server3 would be the xx.xxx.xxx.11 address. Any thoughts? Here is the header.
Authentication-Results: hotmail.com; spf=pass (sender IP is XX.XXX.XXX.9) smtp.mailfrom=admin@mydomain.com; dkim=pass header.d=mydomain.com; x-hmca=pass header.id=marketing@mydomain.com
X-SID-PRA: marketing@mydomain.com
X-AUTH-Result: PASS
X-SID-Result: PASS
Received: from server3.mydomain.com ([XX.XXX.XXX.9]) by SNT0-MC1-F43.Snt0.hotmail.com with Microsoft SMTPSVC(6.0.3790.4900);
Tue, 15 Apr 2014 15:12:07 -0700
show me your master.cf configuration for ip XX.XXX.XXX.9 and xx.xxx.xxx.11 (smtp_bind_address), don’t forget to check dns part, are server1 and server3 point to the right ip address (both A record and PTR record)?
DNS is fine okay
.9 is pointing to server1
.11 is pointing to server3
.12 is pointing to server4
PTR records are all set up correctly too.
Here is my master.cf minus some stuff
smtp inet n – n – – smtpd
#smtp inet n – – – 1 postscreen
#smtpd pass – – – – – smtpd
#dnsblog unix – – – – 0 dnsblog
#tlsproxy unix – – – – 0 tlsproxy
submission inet n – n – – smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
# -o milter_macro_daemon_name=ORIGINATING
smtps inet n – n – – smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
127.0.0.1:10025 inet n – – – – smtpd
-o content_filter=
-o local_recipient_maps=
-o relay_recipient_maps=
-o smtpd_restriction_classes=
-o smtpd_client_restrictions=
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks=127.0.0.0/8
-o strict_rfc821_envelopes=yes
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks,no_milters
yahoo unix – – n – – smtp
-o syslog_name=postfix-yahoo
#random
127.0.0.1:2527 inet n n n – 0 spawn
user=nobody argv=/etc/postfix/random.pl
# random smtp
rotate1 unix – – n – – smtp
-o syslog_name=postfix-rotate1
-o myhostname=server1.mydomain.com
-o smtp_helo_name=server1.mydomain.com
-o smtp_bind_address=xxx.xxx.xxx.9
rotate2 unix – – n – – smtp
-o syslog_name=postfix-rotate2
-o myhostname=server3.mydomain.com
-o smtp_helo_name=server3.mydomain.com
-o smtp_bind_address=xxx.xxx.xxx.11
rotate3 unix – – n – – smtp
-o syslog_name=postfix-rotate3
-o myhostname=server4.mydomain.com
-o smtp_helo_name=server4.mydomain.com
-o smtp_bind_address=xxx.xxx.xxx.12
master.cf part is okay, still not clear your real configuration on DNS, you can check your A record an PTR record at least, let me know your real hostname so i can check it out from here.
server1.iaminsuranceagent.com
server2…
server3…
server4…
looks fine from here
# dig a server1.iaminsuranceagent.com +short
50.245.192.9
# dig -x 50.245.192.9 +short
server1.iaminsuranceagent.com.
# dig a server3.iaminsuranceagent.com +short
# dig -x 50.245.192.11 +short
server3.iaminsuranceagent.com.
might be hotmail resolver, just give another try
Thanks for a great script. I got it working. But there is one question. Please tell me, how do I make it so tough to bind to each (rigidly designate) IP-address separate address Mail-From. For example:
rotate1 Mail-From – info@mail1.my-site.com
rotate1 Mail-From – info@mail2.my-site.com
rotate1 Mail-From – info@mail3.my-site.com
It is necessary for the proper email provider is authenticated when checking SPF, DKIM-recording. For each IP/domen, its separate SPF, DKIM-record.
i’m not really sure, maybe you should check this postfix feature: sender_dependent_default_transport_maps
hy Leenoux, thanks for your amazing tutorials and scripts.
I try to applicate this on zpanel/centos 6 without success how can i update my postfix for use tcp tables???
thanks in advance cool dude!
try download source package from here http://postfix.wl0.org/
Hi!
My program sends letters and mailing at the same address all mail-FROM (Return-Path 🙂
To in headings incoming letters correctly formed DKIM signing, I need to replace the address of mail-FROM (Return-Path 🙂 to the address from which you are sending.
To this I added to each transport one line:
rotate1 unix – n – smtp
-o smtp_bind_address = hhh.hh.28.20
-o smtp_helo_name = mail1.oni4you.com
-o myhostname = mail1.oni4you.com
-o syslog_name = postfix-rotate1
-o sender_canonical_maps = hash :/ etc/postfix/canonical_maps1.cf
rotate2 unix – n – smtp
-o smtp_bind_address = hhh.hh.28.21
-o smtp_helo_name = mail2.oni4you.com
-o myhostname = mail2.oni4you.com
-o syslog_name = postfix-rotate2
-o sender_canonical_maps = hash :/ etc/postfix/canonical_maps2.cf
rotate3 unix – n – smtp
-o smtp_bind_address = hhh.hh.30.83
-o smtp_helo_name = oni4you.com
-o myhostname = mx.oni4you.com
-o syslog_name = postfix-rotate3
Then I created 2 files
canonical_maps1.cf
@ oni4you.com @ mail1.oni4you.com
and
canonical_maps2.cf
@ oni4you.com @ mail2.oni4you.com
performed
# Postmap hash :/ etc / postfix / canonical_maps
for each file,
But it does not work! Could you tell me where is the error?
I’m not sure if this site is still alive in 2020, but I have a question about the “catch-all” behavior with this script. Is it possible to use it in conjunction with a regular transport_maps table in order to define specific destinations for discard or relay to other smtp servers while allowing all non-matching messages to be fed to the random.pl script?
well, it’s still alive. sure, go ahead, i’ll give my best shot to answer your question. i’m little bit rusty though 😀
Good to hear, Hari! I’ll rephrase my question with an example. If I’m using the script on this page with an array of IP addresses, and the following defined in /etc/postfix/main.cf:
transport_maps = hash:/etc/postfix/transport, tcp:127.0.0.1:2527
And, if I put the following in /etc/postfix/transport:
user1@example.com smtp:[1.2.3.4] #relay this user to another SMTP server
everything will work just fine. The email address above will get relayed elsewhere and all other non-matching email will get a random transport entry via your script. However, if I put the following in /etc/postfix/transport:
example.com smtp:[1.2.3.4] #send ALL email for example.com to another SMTP server
this does not work at all. This entry is ignored and email for example.com follows the same path as all other email. Any ideas why the pattern matching doesn’t work here, and any suggestions to fix?
Thx!
can i see your main.cf, transport_maps part. AFAIK, i will put all catch-all and exclussion in tcp_tables perl script(need some modification).