Postfix Bind Sender Domain To Dedicated Outgoing IP Address

Recently there have been requests for sending mail with source IP addresses that depend on the envelope sender, it’s very usefull to protect IP-based domain reputations of different customers.

New Feature in postfix postfix-2.7-20091209 is sender_dependent_default_transport_maps

sender_dependent_default_transport_maps (default: empty)

    A sender-dependent override for the global default_transport parameter setting.
    The tables are searched by the envelope sender address and @domain.
    A lookup result of DUNNO terminates the search without overriding the global default_transport parameter setting.
    This information is overruled with the transport(5) table.

    Note: this overrides default_transport, not transport_maps, and therefore the expected syntax is that of default_transport.
          This feature does not support the transport_maps syntax for null transport, null nexthop, or null email addresses.

    For safety reasons, this feature does not allow $number substitutions in regular expression maps.

    This feature is available in Postfix 2.7 and later.

Create file called sdd_transport_maps.regexp:

/@customer1-dom\.tld$/		customer1:
/@customer2-dom\.tld$/		customer2:
/@customer3-dom\.tld$/		customer3:
..... next .....

In master.cf create special transport called customer1, customer2, customer3….and so on

customer1  unix -       -       n       -       -       smtp
   -o smtp_bind_address=1.1.1.1
   -o smtp_helo_name=customer1-dom.tld
   -o syslog_name=postfix-customer1

customer2  unix -       -       n       -       -       smtp
   -o smtp_bind_address=1.1.1.2
   -o smtp_helo_name=customer2-dom.tld
   -o syslog_name=postfix-customer2

customer3  unix -       -       n       -       -       smtp
   -o smtp_bind_address=1.1.1.3
   -o smtp_helo_name=customer3-dom.tld
   -o syslog_name=postfix-customer3

..... next .....

In main.cf add sender_dependent_default_transport_maps line:

sender_dependent_default_transport_maps = regexp:/etc/postfix/sdd_transport_maps.regexp

Don’t forget to create ip aliasing for each ip address in smtp_bind_address

reload postfix

# postfix reload

35 Comments

    • admin admin

      what part that does not work? πŸ™‚ if you explain what are you going to achieve, maybe i can help you πŸ™‚

      • Alex_Wolf

        postfix 2.7.1

        insert in main.cf

        sender_dependent_default_transport_maps = regexp:/etc/postfix/sdd_transport_maps.regexp

        insert in sdd_transport_maps.regexp

        /@mydomen1\.ru$/ smtp1:
        /@mydomen2\.ru$/ smtp2:

        insert in master.cf

        smtp1 unix – – n – – smtp
        -o smtp_bind_address=xxx.xxx.xxx.155
        -o smtp_helo_name=mail.mydomen1.ru
        smtp2 unix – – n – – smtp
        -o smtp_bind_address=xxx.xxx.xxx.156
        -o smtp_helo_name=mail.mydomen2.ru

        postmap -q “admin@mydomen1.ru” regexp:/etc/postfix/sdd_transport_maps.regexp

        smtp1:

        postmap -q “admin@mydomen2.ru” regexp:/etc/postfix/sdd_transport_maps.regexp

        smtp2:

        i don’t know that not work ????

        • what did you mean by not work? postmap query return as expected.
          query key was admin@mydomen1.ru, result value was smtp1: that’s how it supposed to work, when you send email using admin@mydomen1.ru envelope, it will be routed to smtp1: transport service, and will delivered directly to destinations which bind to specific source ip address and helo name.

          however, this just overrides default_transport, when you define something in transport_map which has higher precedence, the informations will be overruled.

          cmiiw

        • Alex_Wolf

          what mean – Don’t forget to create ip aliasing for each ip address in smtp_bind_address ???
          ——–
          may be this

          main.cf
          smtp_bind_address=0.0.0.0 ???
          or etc/aliases

          smtp1: smtp_bind_address ???
          or ???

          which record needs to be done ?

          perhaps because of this record is not working πŸ˜‰

          • yes, you need to create ip aliasing in order to make smtp_bind_address work

  1. affiliategod

    hey i followed your tutorial but its not working,  your my domain is test.com…. what do  i type for the filter in the transportmap?

    i tried adding * customer1: also test.com customer1: and restarted postfix with nothing happening. when i edit the smtp address and helo server in main.cf works but i need to get this working for smtp clients… how to change ip per domain acct outgoing?

    • admin admin

      what postfix's version did you use? in order to enable sender_dependent_default_transport_maps you need at least postfix 2.7

  2. affiliategod

    how do you insert domain.com into the regexp expression i have tried this and it doesnt work… only thing that works is wheni had "* customer1" to a hash transportmap.. i tried to do the same for the sender_dependent_default_transport_maps and it doesnt work

    • admin admin

      do you compile postfix with regexp table support?
      try postconf -m see if you have regexp support
      # postconf -m
      btree
      cdb
      cidr
      environ
      hash
      internal
      ldap
      mysql
      nis
      pcre
      pgsql
      proxy
      regexp
      static
      tcp
      unix

  3. affiliategod

    I got /@domain\.com$/ and it still doesnt work

  4. Hi,
    I was unable to reproduce this postfix feature would it make a difference if i put the domains in a hashed file ?
    What would be the quickest way to debug this?
    rgds
     
    Leon

    • admin admin

       you can use any postfix indexed lookup tables. hash for example

      according to http://www.postfix.org/postconf.5.html#sender_dependent_default_transport_maps

      "The tables are searched by the envelope sender address and @domain"

      so we must define every user email address in hash table(not only domain). example:

      user@customer1-dom.tld      customer1:
      user@customer2-dom.tld      customer2:
      user@customer3-dom.tld      customer3:

      don't forget to postmap the hash table

      using regexp or pcre can saves time

       

      when regexp available as shown in example, you can do postmap -q <query string> <regexp:/path/to/table>

       

      example:

      postmap -q "whateverusername@customer1-dom.tld" regexp:/path/to/table

      this should be resulting:

      customer1:

    • admin admin

      or you can also put domain sender list on sql table: example mysql:

      sender_dependent_default_transport_maps = mysql:/etc/postfix/sender_dependent_mysql

      sender_dependent_mysql :

      user = user
      password = password
      hosts = localhost
      dbname = postfixdb
      query = SELECT sender_transport FROM table WHERE domain='%d'

      table format:
      | domain                            | sender_transport  |
      | customer1-dom.tld | customer1:             |
      | customer2-dom.tld | customer2:             |
      | customer3-dom.tld | customer3:             |
       

    • admin admin

      well it suppossed to be worked either if @ is in pattern.

      • Hi
        I'm sure it will work with the @ sign in the regexp but my machine was configured to mail using the whole hostname   :  machinename.domainname.tld
        the regexp needs to be adjusted accordingly  either by dropping the @ or  using @machinename.domainname.tld
        I hope that helps someone debugging
         
         
        Regards,
        Leon Berkers

  5. Alex_Wolf

    postconf -m
    result
    …..
    regexp
    …..

    and postconf -d

    result
    sender_dependent_default_transport_maps =
    what mean?

  6. Marco

    Great this!

    But I would dedicated outgoing IP address based on source client IP instead of domain envelope sender.
    How can I achieve this?
    Thanks a lot
    Marco

    • main.cf

      smtpd_recipient_restrictions =
      ...
      ...
      check_client_access hash:/etc/postfix/client_ip
      ....
      

      client_ip

      1.2.3.4	FILTER	ip-client-1:
      4.3.2.1	FILTER	ip-client-2:
      ...
      ...
      

      master.cf

      ip-client-1  unix -       -       n       -       -       smtp
         -o smtp_bind_address=1.2.3.4
         -o smtp_helo_name=ip-client-1-dom.tld
         -o syslog_name=postfix-ip-client-1
       
      ip-client-2  unix -       -       n       -       -       smtp
         -o smtp_bind_address=4.3.2.1
         -o smtp_helo_name=ip-client-2-dom.tld
         -o syslog_name=postfix-ip-client-2
      
  7. BioGuyver

    Great article and it might do what I want for some stuff.
    I am also interested in a way to have a single machine that a client can send mail thru based on the IP address they are told to mail to. For Instance if a client is told the mailserver is on 192.168.10.10 I want them to connect and auth using their creds they have on the box and then mail to be sent from 192.168.10.10. I don’t want to challenge the client for any more info than the creds needed to send mail.
    I want then to setup a second client and have them send to the same server but on 192.168.10.11 and have their mail delivered from 192.168.10.11.
    The reason being is that I offer SMTP outbound for a few clients just to help them out so their network devices etc can phone home. They were all sharing the same smtp server and then someone got hacked and spammed the world. This got my SMTP server blacklisted so i want to swap over to each client having their own ip so they can’t blacklist other clients.
    This is the closest and best Article I have found so far. Do you have any hints? Advice on doing this or know if a howto that describes it? My google fu is failing me today πŸ™

    Thanks
    Ja

  8. Sachin

    Hi there,

    Thanks for this article, it seems to be the ONLY solution to defining domain specific outbound address in postfix.

    However, I do not understand the line “Don’t forget to create ip aliasing for each ip address in smtp_bind_address”

    IP aliasing is to create aliases for network interface eth0 e.g. eth0:1 -> x.x.x.1, eth0:2 -> x.x.x.2 etc which is working fine (tested apache virtual hosts). But then what would be the value for the smtp_bind_address parameter in main.cf?

    Should it be smtp_bind_address = {IP Address of eth0}?

    • when you bind an address using smtp_bind_address without real/alias address postfix would be happily throw errors πŸ˜€
      the purpose is when user@customer1-dom.tld send an email, it will be routed to customer1: and statically bound to ip address 1.1.1.1

      customer1  unix -       -       n       -       -       smtp
         -o smtp_bind_address=1.1.1.1
      

      hope that’s help πŸ™‚

  9. Joe V

    Exactly what I needed. It worked perfectly first try. Thanks!!

  10. Esteban

    Does this means that it will generate a specific outbound queue for those transports?

    • no, in order to make multiple queue you must use multiple instances

  11. David

    Unfortunately i’m not having as much luck as others, though i’m doing exactly what’s shown here and other sites.

    My postfix version 2.9.5 on CentOS 6.3 blatantly refuses to bind IPs based on these headers. It will always use the eth0 IP and not the eth0:1, eth0:2, etc.

    I’ve tried using regexp and shown in this example as well as hash table but same result.

    master.cf (eth0 = 1.1.1.1, eth0:1 = 1.1.1.2, eth0:2 = 1.1.1.3)


    smtp inet n - n - - smtpd
    pickup fifo n - n 60 1 pickup
    cleanup unix n - n - 0 cleanup
    qmgr fifo n - n 300 1 qmgr
    tlsmgr unix - - n 1000? 1 tlsmgr
    rewrite unix - - n - - trivial-rewrite
    bounce unix - - n - 0 bounce
    defer unix - - n - 0 bounce
    trace unix - - n - 0 bounce
    verify unix - - n - 1 verify
    flush unix n - n 1000? 0 flush
    proxymap unix - - n - - proxymap
    proxywrite unix - - n - 1 proxymap
    smtp unix - - n - - smtp
    relay unix - - n - - smtp
    -o smtp_fallback_relay=
    showq unix n - n - - showq
    error unix - - n - - error
    retry unix - - n - - error
    discard unix - - n - - discard
    local unix - n n - - local
    virtual unix - n n - - virtual
    lmtp unix - - n - - lmtp
    anvil unix - - n - 1 anvil
    scache unix - - n - 1 scache

    one unix - - n - - smtp
    -o smtp_bind_address=1.1.1.2
    -o smtp_helo_name=mail1.one.com

    two unix - - n - - smtp
    -o smtp_bind_address=1.1.1.3
    -o smtp_helo_name=mail1.one.com

    main.cf

    sender_dependent_default_transport_maps = regexp:/etc/postfix/sdd_transport_maps.regexp

    sdd_transport_maps.regexp

    /@one\.com$/ one:
    /@two\.com$/ two:

    Yeah, i’ve postmapped all these files, reloaded postfix, even restarted it and then restarted the server. my postfix also indeed supports regexp.

    Is there any debugging i can enable to figure this out?

    • there’s nothing to do with postfix map, does your ip aliasing really up?show me postfix errors | warning log

  12. Alan

    Hi,

    I tried this and my mails are not went through. It is stuck any were. Could you please help me to configure this.

  13. Alan

    Hi,

    I am using poastfic 2.10.x. Please help me to create ip aliasing for each ip address in smtp_bind_address.

    Thank you.

Leave a Reply

Your email address will not be published. Required fields are marked *