SURBL Prototype

Problem this snippet solves:

BIG-IP MSM has IP-based AntiSpam feature but IP-based AntiSpam can be a cause of trouble for the following reasons:

  • DHCP assigned global IP possibly blocked
  • Business mail which is sent from Windows bot infected (and sender does not know infected), is also blocked
  • So IP-based AntiSpam is NOT good solution.

It is much better to check URI in the e-mail. Most of Spam message has a simple purpose, reader to visit their web site.

SURBL is URI based blacklist via DNS, to find a "http://~" in the e-mail and check this URL.

For Example, http://domain.com/ is found at the e-mail message body, check

nslookup domain.com.multi.surbl.org

and the result will be not found or 127.0.0.X and X is a blacklist score.

This basic iRule can use only for telnet based SMTP typing. It is needed to weight the result of DNS looking up. Now result replied after typing ., spam will not blocked.

So this easy approach of anti-spam feature, more than 50% spam message will be deleted.

And if you are interested in SURBL, please see also following URI.

http://www.surbl.org/

  • ESMTP is not supported now.

Code :

# =========================================
# THIS SAMPLE IS NOT OFFICIALLY SUPPORTED.
# =========================================
# THIS PROGRAM IS BASED ON SMTP PROXY sample at
# http://devcentral.f5.com/s/Wiki/default.aspx/iRules/SMTPProxy.html
#

when CLIENT_ACCEPTED {
    set chelo ""
    set cfrom ""
    set crcpt ""    
    TCP::respond "220 BIG-IP SMTP PROXY;\r\n"
    log local0. "220 BIG-IP SMTP PROXY;\r\n"
    TCP::collect
}

when CLIENT_DATA {

    set cdata [TCP::payload]
    log local0. "payload(1) [TCP::payload]"

    if { [ string length $cdata ] <= 0 } {
        return
    }
    if { not ( $cdata contains "\r\n" ) } {
        log local0. "get <$cdata> so far"
        return
    }
    if { [string tolower $cdata] starts_with "helo" or \
[string tolower $cdata] starts_with "ehlo" \
or [string tolower $cdata] starts_with "rset" } {
        set chelo [TCP::payload]
        log local0. "get helo <$cdata>"
        TCP::respond "250 Hello [IP::client_addr] pleased to meet you.\r\n"
        TCP::payload replace 0 [string length $chelo] ""
        log local0. "payload(HELO) [TCP::payload]"
        return
    }

    if { [string tolower $cdata] starts_with "mail from:" } {
        set cfrom [TCP::payload]
        log local0. "get from <$cfrom>"
        TCP::respond "250 sender ok\r\n"
        TCP::payload replace 0 [string length $cfrom] ""
        log local0. "payload(MAILFROM) [TCP::payload]"
        return
    }
    if { [string tolower $cdata] starts_with "rcpt to:" } {
        set crcpt "$crcpt[TCP::payload]"
        log local0. "get rcpt <$crcpt>"
        TCP::respond "250 recipient ok\r\n"
        TCP::payload replace 0 [string length [TCP::payload]] ""
        log local0. "payload(RCPTTO) [TCP::payload]"
        return
    }
    if { [string tolower $cdata] starts_with "data\r\n" } {
        log local0. "get data <$cdata>"
        TCP::payload replace 0 0 $chelo$cfrom$crcpt
    }
# SURBL
    if { [findstr [string tolower $cdata] "http://" 7 "/"] contains "." } {
        set THEURI "[findstr $cdata "http://" 7 "/"].multi.surbl.org"
        log local0. "THEURI seems: $THEURI"
        NAME::lookup $THEURI
    }

    log local0. "payload(2) [TCP::payload]"
    TCP::release
    TCP::collect
}

# DNS RESULT
when NAME_RESOLVED {
  set THEIP [NAME::response]
  log local0. "RESPONSE for $THEURI: $THEIP"
  if { $THEIP contains "127.0.0." } {
    log local0. "$THEURI is listed on multi.surbl.org"
    TCP::respond "500 NG SURBL LIST FOUND.\r\n"
    reject
    TCP::close
  }
}

when SERVER_CONNECTED {
    log "server connected"
    TCP::collect
}

when SERVER_DATA {
    set sdata [TCP::payload]
    log local0. "payload(1) <[TCP::payload]>"

    if { $sdata starts_with "220" } {
        log local0. "get data 220 <$sdata>"
        TCP::payload replace 0 [string length $sdata] ""
        return
    }
    if { $sdata contains "\r\n354 " } {
        log local0. "get data 354 <$sdata>"
        TCP::payload replace 0 [string length $sdata] "354\r\n"
    }
    if { [ string length $sdata ] <= 0 } {
        return
    }
    log local0. "payload(2) <[TCP::payload]>"
    TCP::release
    TCP::collect
}

when CLIENT_CLOSED {
    log local0. "client closed"
}
Published Mar 18, 2015
Version 1.0

Was this article helpful?

No CommentsBe the first to comment