I'm a bit confused right now, because the container is using the correct certificate for IMAP, but the self signed one for SMPT:
$ docker exec mail_mail_1 openssl s_client -connect 0.0.0.0:143 -starttls imap -CApath /etc/ssl/certs/
---
Certificate chain
0 s:/CN=mail.MYDOMAIN.de
i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
i:/O=Digital Signature Trust Co./CN=DST Root CA X3
---
$ docker exec mail_mail_1 openssl s_client -connect 0.0.0.0:25 -starttls smtp
---
Certificate chain
0 s:/CN=f5ee59d47428
i:/CN=f5ee59d47428
---
My docker-compose looks like this:
mail:
image: tvial/docker-mailserver
hostname: mail
domainname: MYDOMAIN.de
cap_add:
- NET_ADMIN
environment:
- DMS_SSL=letsencrypt
ports:
- "25:25"
- "143:143"
- "587:587"
- "993:993"
volumes:
- ./spamassassin:/tmp/spamassassin/
- ./postfix:/tmp/postfix/
- ./mail:/var/mail
- /etc/letsencrypt:/etc/letsencrypt
What did I miss?
I took a look at /etc/postfix/main.cf inside my container and for some reasons, there are spaces:
# TLS parameters
smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key
Not sure where they're coming from..
Update:
I tried removing the spaces inside the container and restarting it. They came back.
I edited postfix/main.cf outside the container with my correct LE files without spaces.
It is now using the correct certificate, but the spaces are back again.
So i guess line 203 to 210 in start-mailserver.sh are responsible for this?
Should I not mount the /postfix directory to /tmp/postfix?
Hi @mgansler, could you try:
openssl s_client -connect 0.0.0.0:587 -starttls smtp -CApath /etc/ssl/certs/
Hey @tomav,
The port doesn't make a difference.
But I did some more testing with the start-mailserver.sh script.
if [ -f /tmp/postfix/main.cf ]; then
while read line; do
postconf -e "$line"
cat /etc/postfix/main.cf|grep smtpd_tls_
done < /tmp/postfix/main.cf
echo "Loaded '/tmp/postfix/main.cf'"
else
echo "'/tmp/postfix/main.cf' not provided. No extra postfix settings loaded."
fi
I put an extra line in there (cat /etc/postfix/main.cf|grep smtpd_tls_) and indeed. The config is initially set to LE but is changed back to self signed through these lines.
So what I did was to clone your repo, modify the docker-compose.yml file and run the container.
That way, the lines mentioned above undo all changes made by the start-mailserver.sh script up to this point because the main.cf file which is used at build time is read again.
TL;DR: Don't clone this repo and mount the provided postfix/ folder into your container :)
Hopefully I will find some time soon and I can try to build an alpine linux/s6 based image with your setup/config scripts.
I'm nearly in the same situation, if from newly container with env variable and right certificate from letsencrypt I can't connect to my server on port 587 using ssl/tls, while I can on starttls.
but firstly clear me a question:
Anyway the result of
openssl s_client -connect 0.0.0.0:587 -starttls smtp -CApath /etc/ssl/certs/
is
CONNECTED(00000003)
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = domain.tk
verify return:1
---
Certificate chain
0 s:/CN=domain.tk
i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
i:/O=Digital Signature Trust Co./CN=DST Root CA X3
---
Server certificate
-----BEGIN CERTIFICATE-----
certificatestuff
-----END CERTIFICATE-----
subject=/CN=domain.tk
issuer=/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
---
No client certificate CA names sent
---
SSL handshake has read 3247 bytes and written 456 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: sessionId
Session-ID-ctx:
Master-Key: masterkey 8777E315ABDD2AB86E3E7847C7CF2DE6
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1459767309
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
250 DSN
than it hangs there, not sure if correct or what, on enter keypress
500 5.5.2 Error: bad syntax
is return but I thinks that's intended.
I also experienced this issue after having pulled the latest version from the dockerhub. I took a quick look with docker logs and I noticed strange errors about some parsing of the main.cf file when this block of code is being executed at the startup
if [ -f /tmp/postfix/main.cf ]; then
while read line; do
postconf -e "$line"
done < /tmp/postfix/main.cf
echo "Loaded '/tmp/postfix/main.cf'"
else
echo "'/tmp/postfix/main.cf' not provided. No extra postfix settings loaded."
fi
So I took the suggestions of @mgansler and I built the docker image locally removing that block from the start-mailserver.sh script and all works fine like before (both imap and smtp serve the right certificate).
I saw that @robertdolca added that block of code, maybe he can help finding a solution?
I think that also removing the main.cf from the postfix folder should do the trick, but I find very convenient to maintain the github repo updated and then mounting directly the folders in order to integrate changes and new features very quickly.
An easy fix that just came to my mind is to add an env variable to specify if a custom main.cf is provided to the container, and to execute the previous block of code only if that variable has a certain value. But this would add another env variable, and of course it would be better find a more elegant solution.
@andrealinux1 are you using a /tmp/postfix/main.cf? I am asking because if the file is not present that code should not run. Also, are you seeing '/tmp/postfix/main.cf' not provided. No extra postfix settings loaded. message?
@robertdolca the code is executed since I mount as a volume the postfix folder provided with this repo, that contains a template of the main.cf. I think that this error occurs because other people like me mount the same folder in the container. I can delete the main.cf file and I think that all should be ok, but I think that especially a new user of the container would mount the folder in the same way having this problem. Maybe we can find a way to avoid this or just write it somewhere in the wiki.
If you think that is me that I'm doing the things in the wrong way just say it and I'll simply deploy in another way:)
I also take the opportunity to thank all the contributors of this awesome container, you all did a great work:)
I believe that the best way to go is to rename main.cf (in the code mentioned) to main.overwrite.cf or something similar and everything should be fine then.
@robertdolca maybe you are right: that way it should be clear the role of the file that add/update config options in postfix.
Anyway, I'd point out that the main.cf provided by the github repo is the same present in the docker image (built with the Dockerfile that ADD main.cf): so it seems it isn't useful to provide the same file. The feature is meant to provide extra parameter not already included (as those to enable SASL auth for a mail relay). However in the case the files are the same, once start-mailserver.sh startup and find a main.cf provided it appply the configs it finds there, _thereby countering any change made_ by start-mailserver.sh itself, even to cert and key directives.
@robertdolca : another solution could be to postpone the ssl cert setup (in the start-mailserver.sh) after the postconf/postmap for main.cf/SASL_PASSWD.
@00angus I think that, for reliability, both changes should be done
@00angus I agree with you that not providing the main.cf file should fix the thing, I only wanted to highlight this because I think that the typical workflow for using this container, at least for the first time, is:
accounts.cf and virtual files in the postfix directory according to the needsdocker-compose.yml in order to mount the directories (including the postfix one) and change the other parameters/env variablesdocker-compose upSo with this workflow we encounter the problem highlighted in the previous comments. I repeat that maybe is my workflow that is wrong, but since this issue has been opened, maybe other users are encountering the problem.
Also simply inverting the order of the instructions in the start-mailserver.sh file wouldn't create the opposite problem? Because if, for example, we provide a custom main.cf and also the $DM_SSL variable has value letsencrypt the paths provided in the custom main.cf are overwritten with the ones generated by the instruction in the letsencrypt block. I know that this particular situation doesn't make much sense from the point of view of the configuration, but still I think that we should prevent and manage also the cases in which there is a misconfiguration (obviously only if the effort to do that is to change few lines of code like in this case).
@andrealinux1 you are probably right. Let's think of the reason why we have the possibility to provide a main.cf (a recent feature, btw): it should provide configuration items not already or different from that included in the downloaded image. So in this context make more sense to parse it at the end of any change we apply in start-mailserver.sh.
So my previous suggestion shouldn't be considered.
Does this mean that SMTP connections currently do not work over SSL?
In the docker compose file there is no mapping for port 465 (smtp over ssl) also.
@awb99 yes, it does as long as you don't put the wrong main.cf in /tmp/postfix/. You can use TLS on port 25 with STARTTLS
@robertdolca Thanks Robert! I got it working with STARTTLS on port 587 which I believe is the standard port? and I guess this means that only the username/password sent on login is secure, right? But the full email over ssl which normally would be on port 465 which encrypts everthing .. this is not working.I wonder if only the port mapping is missing or if there is another reason...
@awb99 I suggest opening another issue for this matter so people can answer there.
According to wikipedia
SMTP by default uses TCP port 25. The protocol for mail submission is the same, but uses port 587. SMTP connections secured by SSL, known as SMTPS, default to port 465 _(nonstandard, but sometimes used for legacy reasons)_.
Also 465 is not exposed in the Dockerfile
@robertdolca
netstat -tap | grep docker
tcp6 0 0 [::]:smtp [::]:* LISTEN 12778/docker-proxy
tcp6 0 0 [::]:imaps [::]:* LISTEN 12722/docker-proxy
tcp6 0 0 [::]:pop3s [::]:* LISTEN 12708/docker-proxy
tcp6 0 0 [::]:submission [::]:* LISTEN 12736/docker-proxy
tcp6 0 0 [::]:pop3 [::]:* LISTEN 12764/docker-proxy
tcp6 0 0 [::]:imap2 [::]:* LISTEN 12750/docker-proxy
Now I am really confused. Only1 smtp port, but from outside I can do 25 and 587.
I think it is essential to make sure that the docker mailserver is as secure as it can get. So doing SMTP over 465 SSL sounds like the most secure way to me.
The entry listed as submission is port 587. As far as I know (I don't have allot of experience with postfix) the port number has nothing to do with the connection. As you can see in the wikipedia quote the port you are searching for is legacy.
You can force all smtp connection to be encrypted with
smtpd_tls_auth_only (default: no)
When TLS encryption is optional in the Postfix SMTP server, do not announce or accept SASL authentication over unencrypted connections.
This feature is available in Postfix 2.2 and later.
@robertdolca Thanks Robert!
I'm going to close this issue as I've implemented the @robertdolca suggestion in PR #145
Thank you guys.
Most helpful comment
@00angus I think that, for reliability, both changes should be done