Forum Discussion
Need an iRule for STARTTLS for SMTPS Server side ONLY, Not Client side.
With reference to this question i asked earlier and not had any responses for yet:
https://devcentral.f5.com/questions/smtp-starttls-server-side-only-not-client-side-on-1160-
Are there any irules guru's out there that could rewrite me a STARTTLS irule suitable for the Virtual SERVERSIDE ONLY STARTTLS requirement in that i have described in that question.
This page describes an irule to accept STARTTLS this on the client side, possibly with serverside STARTTLS as well i'm not sure: https://devcentral.f5.com/articles/iruleology-ndashsmtp-start-tls and perhaps could be rewritten to only be server side, which is perhaps much simpler as the F5 is just a "client" itself in the STARTTLS negotiation serverside.
My understanding of irule programming and STARTTLS is limited and could do with some help. (For version 11.6, a serverside SSL certificate only is applied to the virtual server)
4 Replies
- Michael_Harwoo1
Nimbostratus
I have recently found this post by someone else that shows an irule that works almost for what i wanted. https://devcentral.f5.com/questions/adding-starttls-functionality-to-outbound-smtp-sessions-via-irule
It just needed some tweaking of the "IF" statements to get it to accept the slightly different responses from the TLS SMTPS server we were trying to connect to.
when CLIENT_ACCEPTED { No SSL client side, also check no SSL running already on server side log local0. "client accepted" SSL::disable serverside } when SERVER_CONNECTED { TCP::collect } when SERVER_DATA { Read in responses from remote server into a variable and log to /var/log/ltm log local0. "server payload: [string tolower [TCP::payload]]" set payload [string tolower [TCP::payload]] if {$payload starts_with "220" and $payload contains "esmtp"} { Listen for remote servers opening 220 and esmtp message NOTE the ‘if’ statement above may need to be tweaked to except what message the other side is actually sending in reply. Logs should show this. Respond with a EHLO to server, most servers require a name after the EHLO as well. TCP::respond "EHLO insert.dns.certificate.server.name.here.com\r\n" TCP::payload replace 0 [TCP::payload length] "" TCP::release log local0. "responded to server with EHLO" serverside {TCP::collect} } elseif {$payload contains "250-starttls" } { Check server responds with "250-starttls", if so, respond with a STARTTLS TCP::respond "STARTTLS\r\n" TCP::payload replace 0 [TCP::payload length] "" TCP::release log local0. "Sent the server a STARTTLS" serverside {TCP::collect} } elseif {$payload contains "220 ready for tls" or $payload contains "220 2.0.0 continue"} { if server gives a 220 response, then start server side ssl profile NOTE the ‘if’ statement above may need to be tweaked to except what message the other side is actually sending in reply. Logs should show this. log local0. "server said he is ready for TLS, enable the SSL profile" TCP::payload replace 0 [TCP::payload length] "" TCP::release serverside {SSL::enable} TLS hanshake should now start, which is best seen in wireshark packet captures. } } when SERVERSSL_HANDSHAKE { This will only trigger if that is completed successfully. ServerSSL profile will need a certificate to match the outbound IP and DNS name, and you may want to set the "Server certificate" setting to "require", and the "Trusted Certificate Authorities" set to "ca-bundle". log local0. "SSL handshake completed." clientside { TCP::respond "220 SMTP ESMTP Relay F5\r\n" } SSL::collect } when SERVERSSL_DATA { Log the SMTP responses to see any errors. log local0. "server SSL payload: [SSL::payload]" SSL::release SSL::collect }- JG_249184
Altocumulus
How can I use this and have it enable client said ssl when it detects starttls from the client but send clear text when it doesn't?
- Sam_Novak
Altostratus
Adding on to Michaels answer above, I modified his iRule to work with O365 open relay. It took me a while to figure out, so for me the trick was to have both a ClientSSL and ServerSSL profile, and use a SMTP profile, not a SMTPS profile.
I'm not sure if this works with client initiated STARTTLS but I suspect it's just combining this with some of the work from https://devcentral.f5.com/questions/smtp-starttls-irule
when CLIENT_ACCEPTED { No SSL client side, also check no SSL running already on server side Debug mode set DEBUG 0 if { $DEBUG } { log local0. "CLIENT_ACCEPTED" } SSL::disable serverside SSL::disable } when SERVER_CONNECTED { if { $DEBUG } { log local0. "SERVER_CONNECTED" } TCP::collect } when SERVER_DATA { Read in responses from remote server into a variable and log to /var/log/ltm if { $DEBUG } { log local0. "server payload: [string tolower [TCP::payload]]" } set payload [string tolower [TCP::payload]] if {$payload starts_with "220" and $payload contains "esmtp"} { Listen for remote servers opening 220 and esmtp message NOTE the ‘if’ statement above may need to be tweaked to except what message the other side is actually sending in reply. Logs should show this. Respond with a EHLO to server, most servers require a name after the EHLO as well. TCP::respond "EHLO F5.mydomain.com\r\n" TCP::payload replace 0 [TCP::payload length] "" TCP::release if { $DEBUG } { log local0. "responded to server with EHLO" } serverside {TCP::collect} } elseif {$payload contains "250-starttls" } { Check server responds with "250-starttls", if so, respond with a STARTTLS TCP::respond "STARTTLS\r\n" TCP::payload replace 0 [TCP::payload length] "" TCP::release if { $DEBUG } { log local0. "Sent the server a STARTTLS" } serverside {TCP::collect} } elseif {$payload contains "220 ready for tls" or $payload contains "220 2.0.0 continue" or $payload contains "220 2.0.0 smtp server ready" } { if server gives a 220 response, then start server side ssl profile NOTE the ‘if’ statement above may need to be tweaked to except what message the other side is actually sending in reply. Logs should show this. O365 Edit - O365 returns 220 2.0.0 smtp server ready after enabling TLS if { $DEBUG } { log local0. "server said he is ready for TLS, enable the SSL profile" } TCP::payload replace 0 [TCP::payload length] "" TCP::release serverside {SSL::enable} TLS hanshake should now start, which is best seen in wireshark packet captures. } } when SERVERSSL_HANDSHAKE { This will only trigger if that is completed successfully. ServerSSL profile will need a certificate to match the outbound IP and DNS name, and you may want to set the "Server certificate" setting to "require", and the "Trusted Certificate Authorities" set to "ca-bundle". if { $DEBUG } { log local0. "SSL handshake completed." } clientside { TCP::respond "220 SMTP ESMTP Relay F5\r\n" } SSL::collect } when SERVERSSL_DATA { Log the SMTP responses to see any errors. if { $DEBUG } { log local0. "server SSL payload: [SSL::payload]" } SSL::release SSL::collect }- TimkenSteel
Nimbostratus
Sam: Would you mind sharing your Virtual Server configuration as well as your Client SSL and Server SSL configurations? I'm attempting to configure a SMTP relay to O365 but am not able to get SSL working for the connection between the F5 and O365.
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)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