Postfix Articles
Having setup Postfix recently I found the process very straightforward, with a lot of options for configuration. Deciding to dig a bit deeper I looked at the following advanced settings:
Full Certificate Chain
Most articles you see for setting up your certificate to encrypt emails would point you to having the following config:
smtp_tls_key_file = /etc/ssl/private.key
smtp_tls_cert_file = /etc/ssl/relay_cert.cer
smtp_tls_CAfile = /etc/ssl/inter_cert.cer
smtp_tls_cert_file = /etc/ssl/relay_cert.cer
smtp_tls_CAfile = /etc/ssl/inter_cert.cer
This has been deprecated by Postfix, and you should now use a certificate chain. This means you include your private key, cert, intermediate cert, and if needed your root cert all under one file.
While not difficult to setup, you need to be careful to get the certs/keys in the correct order, otherwise, it simply won't work.
smtp_tls_chain_files = /etc/postfix/chain.pem
smtpd_tls_chain_files = /etc/postfix/chain.pem
.pem order
Private Key
Cert
Intermediate Cert
Root Cert (if needed)
smtpd_tls_chain_files = /etc/postfix/chain.pem
.pem order
Private Key
Cert
Intermediate Cert
Root Cert (if needed)
Adding DKIM to Outgoing Mails
When you relay mails into Office365 via a connector your mail is still subject to DMARC checks. So the first step will probably be to add the public IP of the relay server so that the SPF check will pass.
Depending on how your DMARC record is setup, that may be enough. But what if your DMARC also requires DKIM to pass, or you just want the extra security of DKIM? OpenDKIM has this covered, the steps to install and configure are:
Troubleshooting
/etc/opendkim.config
====================
Domain domain.com
KeyFile /etc/postfix/dkim.key
Selector relay
SOCKET inet:8891@localhost
* There is some debate if SOCKET should be set under /etc/default/opendkim, but this seems to have been there for legacy reasons and is no longer needed.====================
Domain domain.com
KeyFile /etc/postfix/dkim.key
Selector relay
SOCKET inet:8891@localhost
/etc/postfix/main.cf
====================
milter_default_action = accept
milter_protocol = 6
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891
====================
milter_default_action = accept
milter_protocol = 6
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891

↑ Usually there are three lines of text in double quotes, remove the line breaks and quotes before adding the DNS TXT record. The t=y is for testing and can be removed.
If you have a transport rule in Exchange that adds a disclaimer to all external mails, then you will want to exclude the Postfix mails (exclude by IP) in order not to break the DKIM body.
Allow Internet access through web proxy
If your internet access is via an authenticated proxy then you will need to add your credentials in 2 places:
General: sudo nano ~/.bashrc
============================
proxy_http=username:password@proxy-server-ip:port
proxy_https=username:password@proxy-server-ip:port
Proxy for APT: /etc/apt/apt.conf
===============================
Acquire::http::Proxy "http://[username]:[password]@ [proxy-web-or-IP-address]:[port-number]";
Acquire::https::Proxy "http://[username]:[password]@ [proxy-web-or-IP-address]:[port-number]";
Also, settings can be stored in the following locations:
/etc/wgetrc
~/.wgetrc
* Don't put wget proxy settings in double-quotes.
============================
proxy_http=username:password@proxy-server-ip:port
proxy_https=username:password@proxy-server-ip:port
Proxy for APT: /etc/apt/apt.conf
===============================
Acquire::http::Proxy "http://[username]:[password]@ [proxy-web-or-IP-address]:[port-number]";
Acquire::https::Proxy "http://[username]:[password]@ [proxy-web-or-IP-address]:[port-number]";
Also, settings can be stored in the following locations:
/etc/wgetrc
~/.wgetrc
* Don't put wget proxy settings in double-quotes.
If you don't want to worry about password changes then I would suggest setting up a service account in Active Directory and setting the password to never expire.
Setup remote access with PowerShell
When setting up Postfix I decided to have a separate log file just from Postfix instead of going into the more general Mail.log. While this is set in the Postfix settings it doesn't control things like the date format, which still comes from the system itself (systemd).
In Ubuntu 24.04 the default logs are accessed via journalctl, and not the popular rsyslog. Via bash you can use '-output short-iso' to set the date format to ISO, but this will not change the settings for the postfix.log file.
While I could have spent more time on this I decided to go with what I know and setup remote PowerShell. With this, I could archive the logs daily and parse the log with tools that I already know.
I won't go into all of the details but having an auth key from the Windows server helps greatly with scripting. A combination of Bash command and PowerShell tools gives lots of options to work with.
PowerShell on Ubuntu
====================
sudo dpkg --install --ignore-depends=libicu72 powershell_7.4.2-1.deb_amd64.deb # currently there is a compatibility issue so install with this command
/etc/ssh/sshd_config
====================
Subsystem powershell /opt/microsoft/powershell/7/pwsh -SSHS -NoProfile -NoLogo
PasswordAuthentication yes
====================
sudo dpkg --install --ignore-depends=libicu72 powershell_7.4.2-1.deb_amd64.deb # currently there is a compatibility issue so install with this command
/etc/ssh/sshd_config
====================
Subsystem powershell /opt/microsoft/powershell/7/pwsh -SSHS -NoProfile -NoLogo
PasswordAuthentication yes
Apps that can't relay off Postfix
When migrating the apps from Exchange to Postfix I didn't expect there to be any issues, despite some of the apps being nearly 20 years old. When moving an Alcatel Voicemail server I found the following error in the log:
/var/logs/postfix.log
=====================
improper command pipelining after CONNECT from myserver.domain.local
=====================
improper command pipelining after CONNECT from myserver.domain.local
While I can't be certain, the most likely cause is a recent vulnerability called SMTP Smuggling. To allow the server to relay you could try the following setting:
etc/postfix/main.cf
===================
smtpd_forbid_unauth_pipelining = no
===================
smtpd_forbid_unauth_pipelining = no
But in my case, I didn't want to reduce the security of Postfix, and as the server will be retired in a few months, I decided to install SMTP Server on IIS.
It's no longer officially supported by Microsoft, but it is easy to configure. Probably a little worrying that there is no protection against SMTP Smuggling, though it will only be used internally.