Receiving Email Alerts from FreeBSD using Mailgun

Caleb Marble

2017-08-20

About

When I have to monitor many servers I use a service like Elastic Stack or Nagios, but that's a post for another time. This specific use case is for the few personal FreeBSD servers that I use and want to receive security alerts for.

You could setup the FreeBSD to send email directly, but you're going to run into some problems with spam filters and, if you're behind a restrictive ISP, delivery issues, both of which you want to avoid when it comes to delivering security alerts. There's also a whole lot more that goes into sending email detailed in this classic Coding Horror post.

I chose Mailgun as my MTA relay because I like the API support that is useful for other services like Redmine and Bitbucket. Though any email service that allows PLAIN authentication will work with this post.

You're going to need the following things to follow along with this tutorial:

Mailgun Setup

To use sendmail with Mailgun there are a few steps you need to perform on the Mailgun side of things.

Once you've setup a Mailgun account and verified your email address you need to verify you own the domain through Mailgun. Follow the steps for Adding a new Domain here: https://app.mailgun.com/app/domains

For Mailgun specifically you can't start sending emails without first upgrading your account from the free tier (requires a credit/debit card). Although if you're only sending email to yourself or your team for a few servers you won't ever reach the free limit for emails (10,000 emails per month at the time of this post) Current pricing info can be found here: https://www.mailgun.com/pricing.

FreeBSD Setup

Once Mailgun likes your domain settings you can begin setting up your FreeBSD box to send email.

Begin by installing the required packages.

pkg install sendmail+tls+sasl2 ca_root_nss

Let FreeBSD know you want to use the new sendmail binary instead of the system default.

$EDITOR /etc/mail/mailer.conf
sendmail    /usr/local/sbin/sendmail
send-mail   /usr/local/sbin/sendmail
mailq       /usr/local/sbin/sendmail
newaliases  /usr/local/sbin/sendmail
hoststat    /usr/local/sbin/sendmail
purgestat   /usr/local/sbin/sendmail

For added security I've added a Diffie-Helmen key in the /etc/mail/certs directory.

This will take a long time on slow boxes.
cd /etc/mail/certs
openssl dhparam -out dh.param 2048
cd /etc/mail
make

Now we need to make some changes to the main sendmail config file so the sendmail binary will know how to send email through Mailgun. Edit the new .mc file and add the example below before the MAILER options, replacing smtp.marblenix.com with the domain you setup for Mailgun.

$EDITOR $(hostname).mc
dnl Mailgun
MASQUERADE_DOMAIN(`smtp.marblenix.com')
MASQUERADE_AS(`smtp.marblenix.com')
FEATURE(`masquerade_envelope')
FEATURE(`authinfo', `hash /etc/mail/authinfo.db')
define(`SMART_HOST', `[smtp.mailgun.org]')
define(`confAUTH_MECHANISMS', `EXTERNAL GSSAPI DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')
define(`RELAY_MAILER_ARGS', `TCP $h 587')

We also need to allow the sendmail binary to verify the SSL certificate for Mailgun (this requires the ca_root_nss package).

mv /etc/mail/certs/cacert.pem /etc/mail/certs/cacert-old.pem
ln /etc/ssl/cert.pem /etc/mail/certs/cacert.pem

Now we want to allow sendmail to login to Mailgun using standard SMTP credentials.

In your Mailgun domain settings, click "Manage SMTP credentials". From here you need to add new credentials. Keep track of which password you use here.

Now we'll let sendmail know about the credentials.

$EDITOR /etc/mail/authinfo
AuthInfo:smtp.mailgun.org "U:USERNAME@DOMAIN" "P:PASSWORD" "M:PLAIN"

Replace USERNAME and PASSWORD with the SMTP credentials from Mailgun, and DOMAIN with the domain you registered on Mailgun (fully qualified domain including any subdomains). For example, if I called created SMTP credentials of FreeBSD and Passw0rd, and the domain I registered with Mailgun was smtp.marblenix.com, then the authinfo file would look like this:

AuthInfo:smtp.mailgun.org "U:FreeBSD@smtp.marblenix.com" "P:Passw0rd" "M:PLAIN"

Finally we want to set which email gets to have all the security messages sent to it. By default FreeBSD will send all security related messages to the root user, so all we'll need to do is give root an email alias.

$EDITOR /etc/mail/aliases
root:   user@example.net

Finalizing the Configuration

There is a few more steps to make to have our changes take effect. Essentially they boil down to backing up the old sendmail.cf file and building the required config files with a few sendmail helper commands.

Run the block of commands below only once. Running it more than once will erase the backup of sendmail.cf, making it very difficult to restore to the original configuration if you ever need to.
newaliases
makemap -r hash a/etc/mail/authinfo.db < /etc/mail/authinfo
make -C /etc/mail
mv /etc/mail/sendmail.cf /etc/mail/sendmail-old.cf
ln /etc/mail/$(hostname).cf /etc/mail/sendmail.cf
sysrc sendmail_enable="YES"
service sendmail restart

Finally you can test the new sendmail program with the following (replace user@example.net with your email alias you made for the root user):

echo "Test email body" | mail -s "Test Email; Please Ignore" user@example.net

Troubleshooting

If your email did not send, check the logs on the Mailgun logs page https://app.mailgun.com/app/logs. If FreeBSD did properly send the email to smtp.mailgun.org then you might see the following:

Rejected: 'Test Email; Please Ignore' Free accounts are for test purposes only. Please upgrade or add the address to authorized recipients in Account Settings.

If you do see the above message then you need to upgrade your Mailgun plan from the free account. Don't worry, if you only use Mailgun for these kinds of security messages then you'll never reach the 10,000 emails per month limit.

On new Mailgun accounts you are limited to 100 emails per hour. To lift this limit see this page:

https://help.mailgun.com/hc/en-us/articles/115001124753-Account-Sending-Limitation

If your email did not send and you do not see any logs inside the Mailgun logs link above, then check the maillog while sending an email.

tail -f /var/log/maillog &
echo "Test email body" | mail -s "Test Email; Please Ignore" user@example.net

You should see the following:

Aug 20 12:08:28 marblenix sendmail[54218]: from=root, size=2616, class=0, nrcpts=1, msgid=<201708XXXXXXXXXXXXX@marblenix>, relay=root@localhost
Aug 20 12:08:28 marblenix sendmail[54218]: STARTTLS=client, relay=[127.0.0.1], version=TLSv1.2, verify=FAIL, cipher=ECDHE-RSA-AES256-GCM-SHA384, bits=256/256
Aug 20 12:08:28 marblenix sm-mta[54221]: STARTTLS=server, relay=localhost [127.0.0.1], version=TLSv1.2, verify=NO, cipher=ECDHE-RSA-AES256-GCM-SHA384, bits=256/256
Aug 20 12:08:28 marblenix sm-mta[54221]: from=<root@marblenix>, size=2908, class=0, nrcpts=1, msgid=<201708XXXXXXXXXXXXX@marblenix>, proto=ESMTPS, daemon=IPv4, relay=localhost [127.0.0.1]
Aug 20 12:08:28 marblenix sendmail[54218]: to=root, ctladdr=root (0/0), delay=00:00:00, xdelay=00:00:00, mailer=relay, pri=32616, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (Message accepted for delivery)
Aug 20 12:08:28 marblenix sm-mta[54222]: STARTTLS=client, relay=smtp.mailgun.org., version=TLSv1.2, verify=OK, cipher=ECDHE-RSA-AES256-GCM-SHA384, bits=256/256
Aug 20 12:08:29 marblenix sm-mta[54222]: to=user@example.net, ctladdr=<root@marblenix> (0/0), delay=00:00:01, xdelay=00:00:01, mailer=relay, pri=33209, relay=smtp.mailgun.org. [XXX.XXX.XXX.XXX], dsn=2.0.0, stat=Sent (Great success)

For questions or comments please click View Coments below.


View Comments | Back to Blog | Back to Home