You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by "Benoit Tellier (Jira)" <se...@james.apache.org> on 2021/09/03 07:38:00 UTC
[jira] [Created] (JAMES-3645) RemoteDelivery sslEnable parameter
have no effect
Benoit Tellier created JAMES-3645:
-------------------------------------
Summary: RemoteDelivery sslEnable parameter have no effect
Key: JAMES-3645
URL: https://issues.apache.org/jira/browse/JAMES-3645
Project: James Server
Issue Type: Improvement
Reporter: Benoit Tellier
h3. Description
As an administrator I wish to secure my outgoing emails using SSL (SMTPS on port 465), and default to SMTP on port 25 (where STARTTLS can be used opportunistically).
This need is a recurring one for Gitter users (often asked, known for years to be buggy).
h3. Setting up test James servers
I did write a simple docker-compose.yml file to experiment this:
{code:java}
version: '3'
services:
james1:
image: apache/james:memory-latest
container_name: james1
hostname: james1
volumes:
- $PWD/keystore:/root/conf/keystore
james2:
image: apache/james:memory-latest
container_name: james2
hostname: james2
volumes:
- $PWD/keystore:/root/conf/keystore
{code}
I do embed two RcptHooks to diagnose where remoteDelivery connects on james2:
{code:java}
package org.apache.james;
import org.apache.james.core.MailAddress;
import org.apache.james.core.MaybeSender;
import org.apache.james.protocols.smtp.SMTPSession;
import org.apache.james.protocols.smtp.hook.HookResult;
import org.apache.james.protocols.smtp.hook.RcptHook;
public class SoutRcptHook implements RcptHook {
@Override
public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
System.out.println(" <---> SSL activated: " + sender.asPrettyString() + " sends a message securely to " + rcpt.asString());
return HookResult.DECLINED;
}
{code}
And
{code:java}
package org.apache.james;
import org.apache.james.core.MailAddress;
import org.apache.james.core.MaybeSender;
import org.apache.james.protocols.smtp.SMTPSession;
import org.apache.james.protocols.smtp.hook.HookResult;
import org.apache.james.protocols.smtp.hook.RcptHook;
public class NoSSLRcptHook implements RcptHook {
@Override
public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt) {
System.out.println(" <---> NO SSL: " + sender.asPrettyString() + " sends a message securely to " + rcpt.asString());
return HookResult.DECLINED;
}
}
{code}
Which then ellows configuring the SMTP server:
{code:java}
<smtpservers>
<smtpserver enabled="true">
<jmxName>smtpserver-global</jmxName>
<bind>0.0.0.0:25</bind>
<tls socketTLS="false" startTLS="true">
<keystore>file://conf/keystore</keystore>
<secret>james72laBalle</secret>
<provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
<algorithm>SunX509</algorithm>
</tls>
<smtpGreeting>Apache JAMES awesome SMTP Server</smtpGreeting>
<handlerchain>
<handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
<handler class="org.apache.james.NoSSLRcptHook"/>
</handlerchain>
</smtpserver>
<smtpserver enabled="true">
<jmxName>smtpserver-TLS</jmxName>
<bind>0.0.0.0:465</bind>
<tls socketTLS="true" startTLS="false">
<keystore>file://conf/keystore</keystore>
<secret>james72laBalle</secret>
<provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
<algorithm>SunX509</algorithm>
</tls>
<smtpGreeting>Apache JAMES awesome SMTP Server</smtpGreeting>
<handlerchain>
<handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
<handler class="org.apache.james.SoutRcptHook"/>
</handlerchain>
</smtpserver>
</smtpservers>
{code}
We then can review logs to know which port was eventually used to receive emails (smtp logs also tells us if STARTTLS is used).
I expect `sslEnable` parameter to govern this opportunistic SSL connection. Thus RemoteDelivery configuration looks like this:
{code:java}
<processor state="relay" enableJmx="true">
<mailet match="All" class="RemoteDelivery">
<outgoingQueue>outgoing</outgoingQueue>
<bounceProcessor>bounces</bounceProcessor>
<debug>true</debug>
<mail.smtp.ssl.trust>*</mail.smtp.ssl.trust>
<sslEnable>true</sslEnable>
<startTLS>true</startTLS>
</mailet>
</processor>
{code}
We then can create some test data and send a mail from james1 to james2:
{code:java}
docker-compose up -d
docker exec james1 james-cli adddomain james1
docker exec james2 james-cli adddomain james2
docker exec james1 james-cli adduser bob@james1 123456
docker exec james2 james-cli adduser bob@james2 123456
docker inspect james1
telnet [james1] 25
auth login
Ym9iQGphbWVzMQ==
MTIzNDU2
ehlo james1
mail from: <bo...@james1>
rcpt to: <bo...@james2>
data
Subject: rueooerwbwerb
veriobwerobwerbr
rwebeberber
.
{code}
Will generate james1 to remote-deliver a mail to james2, and we can in the process diagnose the remote delivery behaviour between the two.
h3. Actual behaviour
james1 attepts an SSL connection on port 25:
{code:java}
james1 | 06:56:43.405 [DEBUG] o.a.j.t.m.r.d.MailDelivrer - Could not connect to SMTP host: 172.30.0.2, port: 25
james1 | javax.net.ssl.SSLException: Unsupported or unrecognized SSL message
james1 | at java.base/sun.security.ssl.SSLSocketInputRecord.handleUnknownRecord(SSLSocketInputRecord.java:451)
james1 | at java.base/sun.security.ssl.SSLSocketInputRecord.decode(SSLSocketInputRecord.java:175)
james1 | at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:110)
james1 | at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1418)
james1 | at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1324)
james1 | at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:440)
james1 | at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:411)
james1 | at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:626)
james1 | at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:400)
james1 | at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:238)
james1 | at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2175)
james1 | at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:740)
{code}
And james2 do not recognizes the commands:
{code:java}
james2 | 06:56:43.410 [DEBUG] o.a.j.p.a.h.CommandDispatcher - org.apache.james.protocols.api.handler.CommandDispatcher received: ZVVF�������E�F�8T�E'F��LO��#���
james2 | 06:56:43.411 [DEBUG] o.a.j.p.a.h.CommandDispatcher - Lookup command handler for command: ZVVF�������E�F�8T�E'F��LO��#���
james2 | 06:56:43.437 [DEBUG] o.a.j.p.a.h.CommandHandlerResultLogger - org.apache.james.protocols.smtp.core.UnknownCmdHandler: [500 5.5.1 Command ZVVF�������E�F�8T�E'F��LO��#��� unrecognized.]
james2 | 06:56:43.441 [DEBUG] o.a.j.p.a.h.CommandDispatcher - org.apache.james.protocols.api.handler.CommandDispatcher received: �5��98�#�'<�%�)G@� �/��32��
james2 | 06:56:43.442 [DEBUG] o.a.j.p.a.h.CommandDispatcher - Lookup command handler for command: �5��98�#�'<�%�)G@� �/��32��
james2 | 06:56:43.442 [DEBUG] o.a.j.p.a.h.CommandHandlerResultLogger - org.apache.james.protocols.smtp.core.UnknownCmdHandler: [500 5.5.1 Command �5��98�#�'<�%�)G@� �/��32�� unrecognized.]
james2 | 06:56:43.443 [DEBUG] o.a.j.p.a.h.CommandDispatcher - org.apache.james.protocols.api.handler.CommandDispatcher received: ,*
james2 | 06:56:43.443 [DEBUG] o.a.j.p.a.h.CommandDispatcher - Lookup command handler for command: ,*
{code}
h3. Expected behaviour
We expect the mail to be sent over SSL.
We expect that if the target host do not support SSL on port 465 that we fallback to SMTP on port 25, and use STARTTLS.
h3. Interesting notice
* MXHostAddressIterator is adding the protocol (smtp VS smtps) and the port (25 VS 465). While setting these values according to SMTPS & 465 SSL is correctly performed.
The management of the fallback behavior however requires a fallback host address to be generated (SMTP + 25 after the SMTPS one), and also requires handling down the line in MailDelivrerToHost (use of two sessions, one for SMTP, one for SMTPS).
* The use of self signed certificates for the distant server when using remoteDelivery :
{code:java}
<jvmFlag>-Djavax.net.ssl.trustStore=/root/conf/keystore</jvmFlag>
{code}
--
This message was sent by Atlassian Jira
(v8.3.4#803005)
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org