simonrob / email-oauth2-proxy

An IMAP/POP/SMTP proxy that transparently adds OAuth 2.0 authentication for email clients that don't support this method.
Apache License 2.0
785 stars 84 forks source link

Feature Request - Support for SMTP STARTTLS between SMTP client and SMTP proxy #235

Closed Ar-4t closed 5 months ago

Ar-4t commented 5 months ago

Hello,

When using the SMTP proxy with certificate to create a secure connection between itself and the email client, the proxy will support SMTPS (SMTP Implicit) but won't support SMTP STARTTLS (SMTP Explicit).

Some printers (and apps) only support SMTP STARTTLS as a way to create a secure connection. As an alternative solution, I'm using plain text SMTP between clients and proxy.

I think it would be a usefull feature to have SMTP STARTTLS available between SMTP clients and Email OAuth 2.0 Proxy.

Anyway, thanks for this great tool.

simonrob commented 5 months ago

Please read the documentation – this is already supported.

Ar-4t commented 5 months ago

I have read the doc, also done some tests and tried to understand the source . When using starttls = True the proxy will handle STARTTLS negotiation with the SMTP server. It means the data exchanged between client and proxy is in plaintext.

If using 'local_certificate_path' and 'local_key_path' the proxy will support SMTP implicit for incoming connection but won't support SMTP explicit (STARTTLS).

Here is the server part of my config file : [SMTP-465] server_address = smtp.office365.com server_port = 587 starttls = True local_certificate_path = /config/smtprelay.crt local_key_path = /config/smtprelay.key

With this config, SMTP Implicit : openssl s_client -connect IP_ADDRESS:465 -crlf is working SMTP Explicit : openssl s_client -connect IP_ADDRESS:465 -crlf -starttls smtp is not working.

simonrob commented 5 months ago

Ah, ok – you are wanting the proxy to simulate STARTTLS for clients that enforce this. This was requested recently, but isn't yet supported by the proxy.

I'm happy to look at adding this feature on a consultancy basis if it needs prioritising.

Ar-4t commented 5 months ago

Yes that's what I'm looking for.

Thanks for your answer.

simonrob commented 5 months ago

Thanks for the support – could you try the smtp-local-starttls branch to see a work-in-progress version?

Add local_starttls = True to a SMTP server that has a local certificate, and your SMTP Explicit command from above should now work.

More polishing is needed (for example, server status in the GUI is now not reflected), but this should let you try things out at least.

Ar-4t commented 5 months ago

With the smtp-local-starttls branch, and the following config file the proxy kinda supports STARTTLS command for the local connection.

[SMTP-587] server_address = smtp.office365.com server_port = 587 starttls = True local_starttls = True local_certificate_path = smtprelay.crt local_key_path = smtprelay.key

CLI used to test : openssl s_client -connect IP_ADDRESS:587 -crlf -starttls smtp

But when using openssl with -starttls smtp, it send the STARTTLS command even if the server is not advertising the STARTTLS. In my case the MUA (Powershell Net.Mail.SmtpClient), is throwing error "Server does not support secure connections" cause the STARTTLS command as already been used by the proxy, therefore it's not advertised by the Office365 SMTP server.

Maybe you are aware, the SMTPS (openssl s_client -connect IP_ADDRESS:465 -crlf) is not working anymore (server config with cert and key, without local_starttls = True )

Also would it be possible for the local_starttls parameter to support a way to enforce the use of STARTTLS by the MUA ?

simonrob commented 5 months ago

Thanks for testing this. I've just commited a few refinements, and SMTP should now work in the following example configurations:

  1. Local and remote STARTTLS. Test command: openssl s_client -crlf -starttls smtp -connect localhost:1587 (or an email client with STARTTLS enabled), with the following proxy configuration:
[SMTP-1587]
server_address = smtp.office365.com
server_port = 587
server_starttls = True
local_address = 127.0.0.1
local_starttls = True
local_certificate_path = /path/to/ssl_cert.pem
local_key_path = /path/to/ssl_key.pem
  1. Remote STARTTLS only; local secure connection. Test command: openssl s_client -crlf -connect localhost:1588. Proxy configuration:
[SMTP-1588]
server_address = smtp.office365.com
server_port = 587
server_starttls = True
local_address = 127.0.0.1
local_certificate_path = /path/to/ssl_cert.pem
local_key_path = /path/to/ssl_key.pem
  1. Remote STARTTLS only; unsecured local connection. Test command: telnet localhost 1589 with proxy configuration:
[SMTP-1589]
server_address = smtp.office365.com
server_port = 587
server_starttls = True
local_address = 127.0.0.1
  1. (and 5 and 6) Each of the above, but with a remote server that doesn't use STARTTLS (e.g., smtp.gmail.com on port 465), and server_starttls omitted.

Re: your other points:

But when using openssl with -starttls smtp, it send the STARTTLS command even if the server is not advertising the STARTTLS.

This is a behaviour of openssl's s_client, not the proxy. I don't know whether it can be configured to respect the advertised capabilities. I suspect not, becuse if you're using it with a non-STARTTLS server, you'd just omit the -starttls smtp.

In my case the MUA (Powershell Net.Mail.SmtpClient), is throwing error "Server does not support secure connections" cause the STARTTLS command as already been used by the proxy, therefore it's not advertised by the Office365 SMTP server.

This should work – please could you check again using the most recent version in the smtp-local-starttls branch? It's worth pointing out that the STARTTLS commands used for local and remote connections are entirely separate, so it's not possible for one to be consumed by the other.

Maybe you are aware, the SMTPS (openssl s_client -connect IP_ADDRESS:465 -crlf) is not working anymore (server config with cert and key, without local_starttls = True )

I can't reproduce this. See the [SMTP-1588] example above for a server that uses a locally-encrypted connection, but not STARTTLS.

Also would it be possible for the local_starttls parameter to support a way to enforce the use of STARTTLS by the MUA ?

The local STARTTLS feature has already been a more complex and time-consuming development commitment than I initially anticipated so this would have to be a separate feature, but I'm happy to look at it if needed.

Ar-4t commented 5 months ago

Thanks for those updates. SMTP is working fine for plaintext, explicit TLS, and implicit TLS 🎉 Thanks very much for your work.

I have only tested it against Office365 SMTP server. If needed, here is my config for the server part.

Support for Implicit TLS (SSL/TLS on Thunderbird) : Proxy listening on port TCP 465 on any IP of the computer running the proxy.

[SMTP-465]
server_address = smtp.office365.com
server_port = 587
server_starttls = True
local_certificate_path = smtprelay.crt
local_key_path = smtprelay.key

Support for Explicit TLS (STARTTLS on Thunderbird) and plaintext SMTP (None on Thunderbird) : Proxy listening on port TCP 587 on any IP of the computer running the proxy.

[SMTP-587]
server_address = smtp.office365.com
server_port = 587
server_starttls = True
local_starttls = True
local_certificate_path = smtprelay.crt
local_key_path = smtprelay.key
Ar-4t commented 5 months ago

A few comments:

When the proxy is in STARTTLS/plaintext for local connection (Port 587 in the following output), in the log it says it's listening for TLS connection.

2024-03-12 21:34:22: Starting SMTP server at [::]:587 (TLS) proxying smtp.office365.com:587 (STARTTLS) 2024-03-12 21:34:22: Starting SMTP server at [::]:465 (TLS) proxying smtp.office365.com:587 (STARTTLS)

The local STARTTLS feature has already been a more complex and time-consuming development commitment than I initially anticipated so this would have to be a separate feature, but I'm happy to look at it if needed.

I understand and I'm really glad you could implement STARTTLS for local connection. It's really a game changer.

If you have time to spare on this extra feature, a way of doing it would be to check if the connection is secured (Client did send STARTTLS command), if not (client sending AUTH command in plaintext) the proxy send a TCP RST to close the connection. Another way, would be for the proxy to send 550 5.5.1 Protocol error which is what I am seeing with public SMTP server (Port 25) for protonmail.com and posteo.net.

simonrob commented 5 months ago

Great – I'm glad this is now working as intended. I've just updated the startup message, and will now merge this branch. Thanks for supporting the development of this feature!