Forum Discussion

jpavel's avatar
jpavel
Icon for Nimbostratus rankNimbostratus
Jan 10, 2012

iRule based on SMTP receiver domain

Hello iRule experts,

 

 

unfortunately I am an irule beginner and therefore I need some help.

 

 

One of our customers would like to direct traffic based on the SMTP receiver domain.

 

Emails for the receiver "user@east.com" for example should be load balanced to server pool "pool_east" and emails for "user@west.com" should be load balanced to server pool "pool_west".

 

 

In my opinion irule is a way to accomplish that.

 

Can anybody give me an idea how this irule has to look like?

 

 

Many thanks in advance

 

 

Joerg

 

6 Replies

  • have you seen this one? even it is based on sender domain, i think it may be helpful.

     

     

    SMTP Proxy - Send to specific pool based on sender domain by James Denton

     

    http://devcentral.f5.com/wiki/iRules.SMTP-Proxy-Send-to-specific-pool-based-on-sender-domain.ashx
  • jpavel's avatar
    jpavel
    Icon for Nimbostratus rankNimbostratus
    Hi nitass,

     

     

    yes, I have seen this one but unfortunately I have no idea how this irule is working and it also seems very complex to me with many arguments and parameters I may be do not need.

     

    Do you maybe know a simple rule which may fit into my requirements?
  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account
    Unfortunately, given the way that SMTP works, there isn't a simple way to go about what you're looking for. The recipient is not sent in the first communication, rather it takes multiple responses from the server for the client to actually send the data you're looking to route based on. This means that you have to impersonate the server within the iRule, and replay all necessary requests from the client to the server once you've selected a server. This, as you can imagine, gets complex.

     

     

    The iRule that nitass posted the link to is doing pretty much exactly what you're looking for, routing based on domain. It is complex though, you're right, and would need thorough testing to ensure it didn't cause problems in your environment. If you were looking to route on something exceedingly simple like an HTTP host or the like, that would be a no brainer. Unfortunately given the intricacies of SMTP there is only so much simplification that we can offer.

     

     

    Hopefully that helps explain the situation, at least, even if it doesn't offer you a simpler solution.

     

     

    Colin
  • jpavel's avatar
    jpavel
    Icon for Nimbostratus rankNimbostratus
    Hi Colin,

     

     

    thanks for your explanation.

     

    I will check our with our customer what we will do here.

     

     

    Joerg

     

  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account
    Sure thing! I wish I had a better answer for you, but some protocols are just more difficult to imitate than others. ;)

     

     

    Colin
  • i just cut small part from James and put it in smtp proxy codeshare. hoping it might be easier for you to see how it works.

    [root@ve1023:Active] config  b virtual bar list
    virtual bar {
       snat automap
       destination 172.28.19.79:25
       ip protocol 6
       rules myrule
    }
    [root@ve1023:Active] config  b rule myrule list
    rule myrule {
       when CLIENT_ACCEPTED {
        set chelo ""
        set cfrom ""
        set crcpt ""
        TCP::respond "220\r\n"
        log local0. "client accepted"
        TCP::collect
    }
    
    when CLIENT_DATA {
        set cdata [TCP::payload]
        if { [ string length $cdata ] <= 0 } {
            return
        }
        if { not ( $cdata contains "\r\n" ) } {
            log local0. "get $cdata so far"
            return
        }
        if { $cdata starts_with "HELO" } {
            set chelo [TCP::payload]
            log local0. "get helo $cdata"
            TCP::respond "250 OK\r\n"
            TCP::payload replace 0 [string length $chelo] ""
            return
        }
        if { $cdata starts_with "MAIL FROM:" } {
            set cfrom [TCP::payload]
            log local0. "get from $cfrom"
            TCP::respond "250 OK\r\n"
            TCP::payload replace 0 [string length $cfrom] ""
            return
        }
    
        if { $cdata starts_with "RCPT TO:" } {
            set crcpt "$crcpt[TCP::payload]"
            log local0. "get rcpt $crcpt"
    
            set rcptaddr [regsub -all \[\\r\\n\\s\] [TCP::payload] ""]
            set rcptaddr [findstr $rcptaddr ":" 1]
            set rcptdomain [findstr $rcptaddr "@" 1]
            log local0. "get rcpt domain $rcptdomain"
    
            TCP::respond "250 OK\r\n"
            TCP::payload replace 0 [string length [TCP::payload]] ""
    
            if {$rcptdomain equals "abc.com"} {
                    log local0. "foo1"
                    pool foo1
            } else {
                    log local0. "foo2"
                    pool foo2
            }
    
            return
        }
    
        if { $cdata starts_with "DATA" } {
            log local0. "get data $cdata"
            TCP::payload replace 0 0 $chelo$cfrom$crcpt
        }
        log local0. "payload [TCP::payload]"
        TCP::release
        TCP::collect
    }
    
    when SERVER_CONNECTED {
        log "server connected"
        TCP::collect
    }
    
    when SERVER_DATA {
        set sdata [TCP::payload]
    
        if { $sdata starts_with "220" } {
            log local0. "get data $sdata"
            TCP::payload replace 0 [string length $sdata] ""
            return
        }
        if { $sdata contains "\r\n354 " } {
            log local0. "get data $sdata"
            TCP::payload replace 0 [string length $sdata] "354\r\n"
        }
        if { [ string length $sdata ] <= 0 } {
            return
        }
        log local0. "payload [TCP::payload]"
        TCP::release
        TCP::collect
    }
    
    when CLIENT_CLOSED {
        log local0. "client closed"
    }
    }
    [root@ve1023:Active] config  b pool foo1 list
    bpool foo1 {
       members 200.200.200.101:25 {}
    }
    [root@ve1023:Active] config  b pool foo2 list
    pool foo2 {
       members 200.200.200.102:25 {}
    }
    
    [root@ve1023:Active] config  tail -f /var/log/ltm
    Jan 13 04:07:34 local/tmm info tmm[26866]: Rule myrule CLIENT_ACCEPTED: client accepted
    Jan 13 04:07:39 local/tmm info tmm[26866]: Rule myrule CLIENT_DATA: get helo HELO me  
    Jan 13 04:08:08 local/tmm info tmm[26866]: Rule myrule CLIENT_DATA: get from MAIL FROM:goldenretriever@f5.com  
    Jan 13 04:08:19 local/tmm info tmm[26866]: Rule myrule CLIENT_DATA: get rcpt RCPT TO:superman@abc.com  
    Jan 13 04:08:19 local/tmm info tmm[26866]: Rule myrule CLIENT_DATA: get rcpt domain abc.com
    Jan 13 04:08:19 local/tmm info tmm[26866]: Rule myrule CLIENT_DATA: foo1
    
    [root@ve1023:Active] config  tail -f /var/log/ltm
    Jan 13 04:09:27 local/tmm info tmm[26866]: Rule myrule CLIENT_ACCEPTED: client accepted
    Jan 13 04:09:29 local/tmm info tmm[26866]: Rule myrule CLIENT_DATA: get helo HELO me  
    Jan 13 04:09:37 local/tmm info tmm[26866]: Rule myrule CLIENT_DATA: get from MAIL FROM:goldenretriever@f5.com  
    Jan 13 04:09:48 local/tmm info tmm[26866]: Rule myrule CLIENT_DATA: get rcpt RCPT TO:santa@xyz.com  
    Jan 13 04:09:48 local/tmm info tmm[26866]: Rule myrule CLIENT_DATA: get rcpt domain xyz.com
    Jan 13 04:09:48 local/tmm info tmm[26866]: Rule myrule CLIENT_DATA: foo2