Forum Discussion

Scott_Albrech_8's avatar
Scott_Albrech_8
Icon for Nimbostratus rankNimbostratus
Feb 03, 2005

regexp looking for email addresses in iRule

Toying with some stuff and thought I'd like to scan TCP payload for email addresses, preferably in the "MAIL FROM", but I'm starting much bigger for sake of easing into this. Anyhoo, not having much luck. Here's what I *thought* would work:

 

 

when CLIENT_DATA {

 

if { [regexp -nocase {*@somedomain.com} [TCP::payload]] } {

 

reject

 

}

 

}

 

 

Am I missing something here?
  • rapmaster_c_127's avatar
    rapmaster_c_127
    Historic F5 Account
    Hi,

     

     

    I believe you're posting in the wrong forum. You probably want the v9 iRules forum, not iControl, which is our API to configure the system.

     

     

    I'm a bit swamped right now, but to give you a quick, short answer, the problem is that SMTP is an interactive protocol. As in, you connect and get a banner, then you send the next command, get a response, etc. etc.

     

     

    We can inject data/respond to a TCP stream. Take a look at the TCP::respond command. I'll try to write in more detail later, but perhaps someone else on the forum can assist for now. (And as I mentioned, you might want to move the thread so others get to see it.)
  • Ooops, sorry about mis-posting. I don't see any way to move the thread, can a moderator do that?
  • rapmaster_c_127's avatar
    rapmaster_c_127
    Historic F5 Account
    I've moved it over for you. I have a bunch of meetings right now, but hopefully someone will see this and get creative! (Yes there are ways to do this; it's actually a fun little project.)
  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    I'm not sure what your ultimate goal is, but here is a very simple example rule that will scan for something (like an e-mail address) in a connection and reset it if found (however, it will not find strings that span TCP packets, but this should not be a problem with most SMTP clients):

     
     when CLIENT_ACCEPTED { 
        TCP::collect 
     } 
     when CLIENT_DATA { 
        if { [TCP::payload] contains "joe@foobar.com" } { 
           reject 
        } else { 
            Release the current payload onto the server 
           TCP::release 
            But still collect the next data from the client 
           TCP::collect 
        } 
     } 
     
  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    I should also add, that when using this approach, you can't use it to select the pool based on the search. You will likely want to have the pool already on the virtual server.

     

     

    The reason you can't use this type of an approach to make change the pool is that you need an SMTP server to interact with the client before the client sends the MAIL FROM: line. This means that the client has to be connected to the server before it will send the lines you want to interrogate. iRules could be written to simulate the server and proxy until the MAIL FROM: line is received, but no one has volunteered to take on that project yet. See post:

     

     

    http://devcentral.f5.com/default.aspx?tabid=28&view=topic&forumid=5&postid=1510
  • I don't know what I'm trying to accomplish with this yet either, aside from having a lot of fun thinking about possibilities. iRules are very powerful and a lot of fun to play around with!

     

     

    Thanks, I'll give your suggestion a try.
  • Well, that has the same result I was seeing before. I hangs the SMTP session. I moved the TCP::release around and get a bit of interaction but still not a totally interactive SMTP session. I don't know if I understand the whole mechanism well enough to fiddle too much. But I tried this which made some headway:

      
      when CLIENT_ACCEPTED {  
          TCP::collect 100  
          TCP::release  
       }  
       when CLIENT_DATA {  
          if { [TCP::payload] contains "joe@foobar.com" } {  
             reject  
          } else {  
              Release the current payload onto the server  
             TCP::release  
              But still collect the next data from the client  
             TCP::collect 500  
          }  
       }  
       

    Am I on the right track there? That gets me to at least the 220 in the transaction, but then it hangs again.
  • I figured out my issue. My understanding of what was vaguely written in the manual led me to the following, which got past the hanging of the SMTP session on first connect (waiting for the 220 on client_accepted):

       
     when CLIENT_ACCEPTED {  
        TCP::collect  
        TCP::release  
     }  
     when CLIENT_DATA {  
        if { [regexp -nocase {mail from:} [TCP::payload]] } {    
           TCP::respond "554 Message Rejected\r\n"  
           reject  
        } else {  
            Release the current payload onto the server   
           TCP::release  
            But still collect the next data from the client   
           TCP::collect  
        }  
     }  
     

    If my logic is correct (oh, and I have doubt!), I added in the TCP release in the CLIENT_ACCEPTED because I don't really care to collect any data at that point in the very initial SMTP connection (I just want a 220 to begin sending) but from reading parts of the manual you need to start a collect in that area in order to process more CLIENT_DATA in other areas (rcpt to, mail from). So, that cured the hang and allows the session to move on.

    Anyway, works quite well. Thanks for all the pointers.