Forum Discussion
SMTP STARTTLS iRule
I need help with getting a STARTTLS iRule working for SMTP on our 1600's. We are on version 10.2.1. And to be clear it is working but there are a few tweaks I can't figure out. The main issue is that when I telnet to the VIP I can't do an SMTP conversation. It throws "530 Must issue a STARTTLS command first". If I fire up Outlook Express I am able to use port 25/TLS just fine and the smtp.log with Outlook Express shows a normal conversation. How to get the conversation to work? Here is the code:
when CLIENT_ACCEPTED {
SSL::disable
}
when SERVER_CONNECTED {
TCP::collect
}
when CLIENT_DATA {
set lcpayload [string tolower [TCP::payload]]
if { $lcpayload starts_with "ehlo" } {
TCP::respond "250-STARTTLS\r\n250 OK\r\n"
TCP::payload replace 0 [TCP::payload length] ""
TCP::release
TCP::collect
} elseif { $lcpayload starts_with "starttls" } {
TCP::respond "220 Ready to start TLS\r\n"
TCP::payload replace 0 [TCP::payload length] ""
TCP::release
SSL::enable
} else {
TCP::respond "530 Must issue a STARTTLS command first\r\n"
TCP::payload replace 0 [TCP::payload length] ""
TCP::release
TCP::collect
}
}
when SERVER_DATA {
TCP::release
clientside { TCP::collect }
}
35 Replies
- Damion
Cirrus
What about something more along this:
when CLIENT_ACCEPTED {
SSL::disable
}
when SERVER_CONNECTED {
TCP::collect
}
when CLIENT_DATA {
set lcpayload [string tolower [TCP::payload]]
if { $lcpayload starts_with "ehlo" } {
TCP::release
TCP::collect
} elseif { $lcpayload starts_with "starttls" } {
TCP::respond "220 Ready to start TLS\r\n"
TCP::payload replace 0 [TCP::payload length] ""
TCP::release
SSL::enable
} else {
TCP::release
TCP::collect
}
}
when SERVER_DATA {
TCP::release
clientside { TCP::collect }
} - kraigk_52257
Nimbostratus
Clear text on port 25 worked with that code Damion but TLS/SSL failed, "250 CHUNKING" error. Says server does not support SSL. - Nat_Thirasuttakorn
Employee
I think we are getting closer. üôÇ
I believe, we might change the ehlo block to one of either 2 options
if { $lcpayload starts_with "ehlo" } {
TCP::release
TCP::collect
}
1) use original method but include all features that server support example:set response "250-mail.company.com Hello\r\n\" append response "250-PIPELINING\r\n" append response "250-DNS\r\n" append response "250-ENHANCEDSTATUSCODES\r\n" append response "250-AUTH GSSAPI NTLM LOGIN\r\n" append response "250-8BITMIME\r\n" append response "250-BINARYMIME\r\n" append response "250-CHUNKING\r\n" append response "250 STARTTLS\r\n" TCP::respond $response
2) do something like...
set ehlo 0
if { $lcpayload starts_with "ehlo" } {
TCP::release
serverside { TCP::collect}
set ehlo 1
TCP::collect
}
in when SERVER_DATA insert 250-STARTTLS\r\n to payload of server response
if { $ehlo == 1 } {
insert 250-STARTTLS... at beginning of the payload
TCP::payload replace 0 0 "250-STARTTLS\r\n"
TCP::release
set ehlo 0
}
Nat - Damion
Cirrus
But the server will respond with the default responses, I think the issue was not specifying the serverside or client side in the opposite respective when clauses. What about the following:
when CLIENT_ACCEPTED {
SSL::disable
}
when SERVER_CONNECTED {
TCP::collect
}
when CLIENT_DATA {
set lcpayload [string tolower [TCP::payload]]
if { $lcpayload starts_with "ehlo" } {
TCP::release
serverside { TCP::collect }
} elseif { $lcpayload starts_with "starttls" } {
TCP::respond "220 Ready to start TLS\r\n"
TCP::payload replace 0 [TCP::payload length] ""
TCP::release
SSL::enable
serverside { TCP::collect }
} else {
TCP::release
serverside { TCP::collect }
}
}
when SERVER_DATA {
TCP::release
clientside { TCP::collect }
} - kraigk_52257
Nimbostratus
Damion,
Tried your code above and still got the "250 CHUNKING" error. Clear text worked. I guess the logic would go something like this:
Nat - I tried to work your suggestion into my irule and had no luck, too lousy at this. :( - Nat_Thirasuttakorn
Employee
try this. I did a quick test with thunderbird...when CLIENT_ACCEPTED { set ehlo 0 SSL::disable } when SERVER_CONNECTED { TCP::collect } when CLIENT_DATA { set lcpayload [string tolower [TCP::payload]] if { $lcpayload starts_with "ehlo" } { set ehlo 1 serverside { TCP::collect } TCP::release TCP::collect } elseif { $lcpayload starts_with "starttls" } { TCP::respond "220 Ready to start TLS\r\n" TCP::payload replace 0 [TCP::payload length] "" TCP::release SSL::enable } else { TCP::release } } when SERVER_DATA { if { $ehlo == 1 and not([string tolower [TCP::payload]] contains "starttls") } { TCP::payload replace 0 0 "250-STARTTLS\r\n" } TCP::release clientside { TCP::collect } } - kraigk_52257
Nimbostratus
Well I'll be damned. You did it Nat. Both SSL and clear text work. And I can telnet in for a lovely SMTP conversation. You guys are the best. Your code worked as it stands, no changes. This should be put in the codeshare, would no doubt be useful to others.
Thanks again!
-kraig - Colin_Walker_12Historic F5 AccountAsk and ye shall receive. CodeShare entry created:
http://devcentral.f5.com/wiki/default.aspx/iRules/SMTPStartTLS.html
Awesome work Nat, I want to be like you when I grow up. ;)
Colin - kraigk_52257
Nimbostratus
Thanks Colin. If I ever grow up.. agreed. - Colin_Walker_12Historic F5 AccountSure thing, thanks for the awesome feedback to help get this one wrapped up. I love forum threads like this.
Colin
Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
