In previous tutorials, we discussed how to set up a mail server from scratch on Linux (Ubuntu version, CentOS/RHEL version), and how to use iRedMail or Modoboa to quickly set up your own mail server without having to manually configure each component of the mail server stack. This tutorial is going to show you how to set up SMTP and IMAP proxy for your mail server with HAProxy.
When Do You Need SMTP and IMAP Proxy?
Some folks run email servers at home, but may have the following problems:
- Port 25 is blocked.
- They don’t have a static IP address.
- They can’t create PTR record.
If port 25 is blocked, you can’t send emails directly to recipients. And if you don’t have a static IP address or PTR record, your emails are likely to be rejected or land into the spam folder. If you are in this situation, you can run a VPS (Virtual Private Server) at a data center and use it as a proxy for your mail server. The VPS has a static IP address and you can create PTR record for the IP address. Other email servers would think that the VPS runs your mail service and when you send an email, they would think the email comes from your VPS.
Yes, you can also use SMTP relay services such as Mailjet to solve these problems, but there’s a limit on how many emails you can send each day and each month. If you upgrade to a paid account with Mailjet, it costs at least $9.65 each month. The more emails you send, the higher your monthly cost will be. If you run a VPS and set up mail proxy, it costs about $5 per month no matter how many emails you are going to send.
If you run a mail server for lots of people, you might need to set up mail proxy for load balancing and high availability. In this article, I will set up SMTP and IMAP proxy with HAProxy, which is a free, open-source high availability load balancer and proxy server for TCP and HTTP-based applications.
Step 1: Choose the Right VPS for Mail Proxy
You need a VPS that
- allows you to create PTR record
- doesn’t block port 25
- allows you to send unlimited emails without restrictions.
Not all VPS providers meet the above 3 requirements. For example, DigitalOcean blocks port 25 and it would not unblock port 25. If you use Vultr VPS, then port 25 is blocked by default. They can unblock it if you open a support ticket, but they may block it again at any time if they decide your email sending activity is not allowed. Vultr actually may re-block it if you use their servers to send newsletters.
I run my mail server on hostwinds, and I always recommend it when setting up mail server. An entry-level VPS is enough to run mail proxy, so you can choose the $4.49/month unmanaged Linux VPS plan. You can choose any Linux distro for your VPS, but I recommend you to use Debian, Ubuntu, or CentOS.
Once you created an account, Hostwinds will send you an email with the server SSH login details. To log into your server, you use an SSH client. If you are using Linux or macOS on your computer, then simply open up a terminal window and run the following command to log into your server. Replace 12.34.56.78 with the IP address of your VPS.
ssh root@12.34.56.78
You will be asked to enter the password. If you are using Windows, please read the following article on how to use SSH client.
Step 2: Set Up VPN Server on Your VPS
If you have a dynamic IP address at your home, then you need to set up a VPN server on your VPS, so your VPS will be able to communicate with your mail server without being interrupted due to the change of IP address. The VPN server can also help you bypass port 25 blocking.
You can set up WireGuard VPN on your VPS by following one of the tutorials below. Why do I choose WireGuard instead of other VPN protocols like OpenVPN? Because WireGuard allows you to assign static private IP addresses to VPN clients.
- Set Up Your Own WireGuard VPN Server on Ubuntu
- Set Up Your Own WireGuard VPN Server on Debian
- Set Up Your Own WireGuard VPN Server on CentOS
When following the instructions in the above articles, your VPS is the VPN server and your mail server is the VPN client. The VPS will become the default gateway for your mail server and all outbound traffic on your mail server will be tunneled through VPN, so receiving SMTP servers (Gmail, Hotmail, Yahoo Mail, etc) will think your emails come from the VPS.
You should set a PTR record, aka reverse DNS record, for your VPS. To edit the PTR record for Hostwinds VPS, log into Hostwinds client area, select Domains
-> Manage rDNS
, Then you can edit the reverse DNS record for both IPv4 and IPv6 addresses.
Step 3: Open Ports in Firewall and Set Up Permissions
The VPS needs to open port 25, 587, 465, 143 and 993 in the firewall. Run the following commands to open these ports.
Debian/Ubuntu:
sudo ufw allow 25,587,465,143,993/tcp
CentOS:
sudo firewall-cmd --permanent --add-service={smtp,smtp-submission,smtps,imap,imaps} sudo systemctl reload firewalld
The mail server needs to open various ports to the VPS. Run the following command.
Debian/Ubuntu:
sudo ufw insert 1 allow in from 10.10.10.0/24
CentOS:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.10.10.0/24" accept'
sudo systemctl reload firewalld
10.10.10.0/24
is the private IP range created by the VPN server, so the VPS can access all ports on the mail server.
Configure SELinux on CentOS
Later in this tutorial, HAProxy on the VPS needs to bind to various email ports like 25, 587, 465, 143 and 993, but is prevented from doing so by SELinux. If you use CentOS on the VPS, you need to run the following command to allow HAProxy to bind to these ports.
sudo setsebool -P haproxy_connect_any 1
Step 4: Set Up SMTP Proxy to Receive Email
Now you need to set up SMTP proxy so that other mail servers can send emails to your own mail server via the VPS. SSH into your VPS and install HAProxy.
Debian/Ubuntu
sudo apt install haproxy
CentOS
sudo dnf install haproxy
Then edit the HAProxy main configuration file.
sudo nano /etc/haproxy/haproxy.cfg
Add the following lines at the end of the file. Replace 12.34.56.78
with the public IP address of your VPS. Replace 10.10.10.101
with the private IP address of your mail server, which is assigned by your VPN server.
frontend ft_smtp bind 12.34.56.78:25 mode tcp timeout client 1m log global option tcplog default_backend bk_smtp backend bk_smtp mode tcp log global option tcplog timeout server 1m timeout connect 7s server postfix 10.10.10.101:2525 send-proxy
The above configuration will make HAProxy listen on port 25 and pass SMTP connections to port 2525 of your mail server. Save and close the file. Restart HAProxy.
sudo systemctl restart haproxy
And enable auto-start at boot time.
sudo systemctl enable haproxy
To use HAProxy as a reverse proxy for the Postfix SMTP server, you need to enable Postscreen in Postfix. SSH into your mail server and edit the Postfix master configuration file.
sudo nano /etc/postfix/master.cf
Add the following lines at the beginning of this file. Replace 10.10.10.101
with the private IP address of your mail server assigned by VPN server. This will enable Postscreen on port 2525 and it can accept HAProxy connections from your VPS. Postfix is able to obtain the original IP address of SMTP client from HAProxy.
10.10.10.101:2525 inet n - - - 1 postscreen
-o postscreen_upstream_proxy_protocol=haproxy
-o postscreen_cache_map=btree:$data_directory/postscreen_2525_cache
-o syslog_name=postfix/2525
Then uncomment the following 3 lines. (Note: If you use iRedMail or Moboboa to run your mail server, then the following 3 lines are uncommented by default.)
smtpd pass - - y - - smtpd dnsblog unix - - y - 0 dnsblog tlsproxy unix - - y - 0 tlsproxy
Where:
- The first line will make Postscreen pass SMTP connection to
smtpd
daemon. - The dnsblog (DNS Blacklist Logger) service enables logging of DNS blacklist checks.
- The tlsproxy service enables STARTTLS support for postscreen, so remote SMTP clients can establish encrypted connection when Postscreen is enabled.
Save and close the file. Restart Postfix for the change to take effect.
sudo systemctl restart postfix
Now add a new MX record for your domain name like below, and your mail server is able to receive emails via the VPS.
Record Type Name Mail Server Priority
MX @ hostname-of-your-VPS 0
Don’t forget to add DNS A record for the hostname of your VPS.
Step 5: Set Up Submission Proxy
Your users can submit outgoing emails to your mail server without proxy, but what if you want your users to be able to submit outgoing emails through the VPS? You need to set up proxy for the Postfix submission service.
Edit the HAProxy main configuration file on your VPS.
sudo nano /etc/haproxy/haproxy.cfg
Add the following lines at the end of the file. Replace 12.34.56.78
with the public IP address of your VPS. Replace 10.10.10.101
with the private IP address of your mail server, which is assigned by your VPN server.
frontend ft_submission bind 12.34.56.78:587 mode tcp timeout client 1m log global option tcplog default_backend bk_submission backend bk_submission mode tcp log global option tcplog timeout server 1m timeout connect 7s server postfix 10.10.10.101:10587 send-proxy frontend ft_smtps bind 12.34.56.78:465 mode tcp timeout client 1m log global option tcplog default_backend bk_smtps backend bk_smtps mode tcp log global option tcplog timeout server 1m timeout connect 7s server postfix 10.10.10.101:10465 send-proxy
There are commonly two ports that can accept email submissions from authenticated users: 587 and 465. So in the above configuration, we defined two front ends in HAProxy listening on port 587 and 465. They will pass connections to port 10587 and 10465 of your mail server, respectively.
Save and close the file. Restart HAProxy.
sudo systemctl restart haproxy
Then edit Postfix master configuration file on your mail server.
sudo nano /etc/postfix/master.cf
Add the following lines at the end of this file. Replace 10.10.10.101
with the private IP address of your mail server, which is assigned by your VPN server. Please allow at least one whitespace (tab or spacebar) before -o
. In postfix configurations, a preceding whitespace character means that this line is continuation of the previous line. However, you should not add space before or after the equal sign (=
).
10.10.10.101:10587 inet n - y - - smtpd -o syslog_name=postfix/10587 -o smtpd_tls_security_level=encrypt -o smtpd_tls_wrappermode=no -o smtpd_sasl_auth_enable=yes -o smtpd_relay_restrictions=permit_sasl_authenticated,reject -o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject -o smtpd_sasl_type=dovecot -o smtpd_sasl_path=private/auth -o smtpd_upstream_proxy_protocol=haproxy 10.10.10.101:10465 inet n - y - - smtpd -o syslog_name=postfix/10465 -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject -o smtpd_sasl_type=dovecot -o smtpd_sasl_path=private/auth -o smtpd_upstream_proxy_protocol=haproxy
In the above configuration, we enabled two submission services listening on port 10587 and 10465, and they support the haproxy
protocol, so they will be able to accept connections from HAProxy. Save and close the file. Restart Postfix for the change to take effect.
sudo systemctl restart postfix
Step 6: Set Up IMAP Proxy
We also want users to be able to log into the IMAP server via the VPS, so we need to set up IMAP proxy.
Edit the HAProxy main configuration file on your VPS.
sudo nano /etc/haproxy/haproxy.cfg
Add the following lines at the end of the file. Replace 12.34.56.78
with the public IP address of your VPS. Replace 10.10.10.101
with the private IP address of your mail server, which is assigned by your VPN server.
frontend ft_imap bind 12.34.56.78:143 mode tcp default_backend bk_imap backend bk_imap mode tcp balance leastconn stick store-request src stick-table type ip size 200k expire 30m server imap1 10.10.10.101:10143 send-proxy-v2 frontend ft_imaps bind 12.34.56.78:993 mode tcp default_backend bk_imaps backend bk_imaps mode tcp balance leastconn stick store-request src stick-table type ip size 200k expire 30m server imaps1 10.10.10.101:10993 send-proxy-v2
There are two ports for the IMAP service: 143 and 993. Port 143 can use STARTTLS and port 993 uses implicit TLS, so in the above configuration, we added two front ends in HAproxy listening on port 143 and 993. They will pass connections to port 10143 and 10993 of your mail server, respectively. Save and close the file. Restart HAProxy.
sudo systemctl restart haproxy
Edit Dovecot configuration file on your mail server.
sudo nano /etc/dovecot/conf.d/10-master.conf
Add HAProxy support for IMAP and IMAPS like below.
service imap-login { inet_listener imap { port = 143 } inet_listener imaps { port = 993 ssl = yes } inet_listener imap_haproxy { port = 10143 haproxy = yes } inet_listener imaps_haproxy { port = 10993 ssl = yes haproxy = yes } }
In the above configuration, we enabled two IMAP services: imap_haproxy
and imaps_haproxy
, listening on port 10143 and 10193, respectively. They support the haproxy
protocol, so they will be able to accept connections from HAProxy. Save and close the file.
Then we need to add trusted proxy hosts in Dovecot. Edit the Dovecot main configuration file.
sudo nano /etc/dovecot/dovecot.conf
Add the following two lines at the end of this file. Replace 10.10.10.1
with the private IP address of your VPN server.
haproxy_trusted_networks = 10.10.10.1
haproxy_timeout = 3s
Save and close the file. Restart Dovecot for the change to take effect.
sudo systemctl restart dovecot
Now you should be able to log into the IMAP server and submit outgoing emails via the VPS.
Step 7: Set Up HTTPS Proxy
If you would like to access webmail such as Roundcube via the VPS, then edit the HAProxy main configuration file on your VPS.
sudo nano /etc/haproxy/haproxy.cfg
Add the following lines at the end of the file. Replace 12.34.56.78
with the public IP address of your VPS. Replace 10.10.10.101
with the private IP address of your mail server, which is assigned by your VPN server. Replace mail.yourdomain.com
with the domain name used by your webmail.
frontend https bind 12.34.56.78:443 mode tcp tcp-request inspect-delay 5s tcp-request content accept if { req_ssl_hello_type 1 } use_backend webmail if { req_ssl_sni -i mail.yourdomain.com } default_backend webmail backend webmail mode tcp option ssl-hello-chk server webmail 10.10.10.101:443 check
Save and close the file. Then restart HAProxy.
sudo systemctl restart haproxy
Note that the HTTPS proxy can interfere with Let’s Encrypt TLS certificate renewal if you use the default http-01
challenge in certbot. It’s recommended to use dns-01
challenge when you renew your Let’s Encrypt TLS certificate with certbot.
Final Thoughts
Notice that we enabled proxy support for Postfix and Dovecot by adding more listening ports (2525, 10587, 10465, 10143, 10993). We didn’t enable proxy support for existing ports (25, 587, 465, 143 and 993), because if we do, then Postfix and Dovecot will accept connections from HAProxy only and deny connection from other IP addresses, including localhost. This can prevent your webmail or web application running on the mail server to use 127.0.0.1:25
to send emails, and prevent the webmail client from fetching emails from Dovecot. You will probably see the following error when this happens.
host mail.example.com refused to talk to me: 421 4.3.2 No system resources
And your Postfix SMTP server would log the following message in the mail log.
postfix/postscreen[1479]: warning: haproxy read: time limit exceeded
Configure HAProxy Automatic Restart
I found the haproxy.service
on CentOS/RHEL can fail to start at boot time. The error is as follows.
Starting frontend ft_smtp: cannot bind socket [23.254.225.226:25]
If I manually start the service, it works, which is confusing to me. To solve this issue, we can edit the haproxy.service
to make it automatically restart on failure. To override the default systemd service configuration, we create a separate directory.
sudo mkdir -p /etc/systemd/system/haproxy.service.d/
Then create a file.
sudo nano /etc/systemd/system/haproxy.service.d/restart.conf
Add the following lines in the file.
[Service] Restart=always RestartSec=5s
Save and close the file. Then reload systemd.
sudo systemctl daemon-reload
Postfix/Dovecot Automatic Restart
It’s also recommended to configure Postfix and Dovecot on the mail server to automatically restart on failure.
Postfix
Create a separate directory.
sudo mkdir -p /etc/systemd/system/postfix.service.d/
Then create a file.
sudo nano /etc/systemd/system/postfix.service.d/restart.conf
Add the following lines in the file. Note that on Debian/Ubuntu, the postfix.service
is an oneshot
service, which doesn’t allow Restart=always
.
[Service] Restart=on-failure RestartSec=5s
Save and close the file. Then reload systemd.
sudo systemctl daemon-reload
Dovecot
Create a separate directory.
sudo mkdir -p /etc/systemd/system/dovecot.service.d/
Then create a file.
sudo nano /etc/systemd/system/dovecot.service.d/restart.conf
Add the following lines in the file.
[Service] Restart=always RestartSec=5s
Save and close the file. Then reload systemd.
sudo systemctl daemon-reload
IP Blacklist Removal
What if the IP address of your VPS is blacklisted by a particular email service provider? You can read the following article to learn how to get your IP address removed from blacklists.
I hope this tutorial helped you set up SMTP and IMAP proxy. As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks. Take care 🙂
Rate this tutorial
[Total: 5 Average: 5]