summaryrefslogtreecommitdiff
path: root/src/Securing_a_Postfix_Smtp_Server.adoc
diff options
context:
space:
mode:
Diffstat (limited to 'src/Securing_a_Postfix_Smtp_Server.adoc')
-rw-r--r--src/Securing_a_Postfix_Smtp_Server.adoc226
1 files changed, 226 insertions, 0 deletions
diff --git a/src/Securing_a_Postfix_Smtp_Server.adoc b/src/Securing_a_Postfix_Smtp_Server.adoc
new file mode 100644
index 0000000..79f20f5
--- /dev/null
+++ b/src/Securing_a_Postfix_Smtp_Server.adoc
@@ -0,0 +1,226 @@
+Securing a Postfix Smtp Server
+==============================
+:author: Aaron Ball
+:email: nullspoon@iohq.net
+
+
+== {doctitle}
+
+I must start this post with the acknowledgement that I know only what I've
+experienced on this topic.
+
+I recently set up my own mail server for the fun of it. I figured it was
+something I'd never done, so why not, right?
+
+Well, one day later, spammers discovered my server and began using it to send
+out spam mail (curse you spammers!). I didn't notice this until I received a
+notification from my hosting provider that my network IO was over the threshold
+I had set. I promptly logged in, tailed the mail logs and discovered
+unbelievable amounts of mail being rejected by Google, Yahoo, Aol, and Hotmail.
+Why? Spam.
+
+With that, I spent the next day figuring out how to better secure my smtp
+server. I'd like to detail some of the exploits that the spammers used to get
+in to my server, how I failed in configuring my server properly, and how I
+fixed it.
+
+[[leaving-an-open-relay]]
+Leaving an Open Relay
+~~~~~~~~~~~~~~~~~~~~~
+
+An open relay is basically an smtp server that requires no authentication
+and/or allows connections from outside ip addresses, so anyone can send emails
+from anywhere to anywhere. The settings in question specific to this issue in
+my configuration were the following:
+
+----
+smtpd_recipient_restrictions = permit_mynetworks, check_relay_domains
+...
+mynetworks = 0.0.0.0/0 127.0.0.0/8 [::fff:127.0.0.0]/104 [::1]/128
+----
+
+Basically that is an open relay. Here's why.
+
+* Firstly, *smtpd_recipient_restrictions = permit_mynetworks* allows any
+ email to be sent without any restrictions as long as the email originated
+ from a box in the IP ranges specified in the mynetworks variable.
+
+* Secondly, *mynetworks = 0.0.0.0/0* allows emails to be sent through my
+ smtp server from any client within the ip range of 0.0.0.0-255.255.255.255.
+ This is bad because any computer can try to send emails through my smtp
+ server and succeed because of the permit_mynetworks restriction (or lack
+ therof).
+
+[[specifying-incorrect-configuration-parameters]]
+Specifying Incorrect Configuration Parameters
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+One of my first mistakes when configuring Postfix was misspelling some smtpd
+parameters using smtp_ instead of smtpd_ to prefix them. As it turns out, if
+you do this, Postfix ignores your attempted configuration without a peep. This
+one went on for a long time before I noticed that two of my smtpd_ fields were
+missing the 'd'. As soon as I put those in there, everything started working as
+it should, albeit still insecure, but at least it was following the
+specifications of my config file.
+
+
+[[not-specifying-a-correct-smtpd_sasl_path]]
+Not Specifying a Correct smtpd_sasl_path
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This one took me a while. The *smtpd_sasl_path* is a path to the socket file
+for your SASL server. In my case, this is Dovecot.
+
+As it turns out, Postfix defaults to running in chroot mode which makes its
+root directory /var/spool/postfix/. This was my first mistake. I was specifying
+
+----
+smtpd_sasl_path = /var/spool/postfix/private/auth-client
+----
+
+and it was not starting up because it couldn't find the socket file. This was
+because it was looking for the file at
+/var/spool/postfix/var/spool/postfix/private/auth-client a path which clearly
+does not exist. The solution to this is to simply specify a relative path.
+
+----
+smtpd_sasl_path = private/auth-client
+----
+
+I decided that I would get smart though and shave off some text from the field
+value by configuring Dovecot to place the socket file at
+/var/spool/postfix/auth-client rather than at
+/var/spool/postfix/private/auth-client (speaking in absolute terms despite
+running in chroot mode). This returned the following error
+
+----
+warning: when SASL type is "dovecot", SASL path "auth-client" should be a socket pathname
+----
+
+As it turns out, postfix won't operate with the SASL socket file path outside
+of the private directory. So with that, I placed my auth-client file back in
+the private directory and Postfix started up fine.
+
+
+[[not-specifying-the-allowed-senders-file]]
+Not Specifying the Allowed Senders File
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Even if you do have authentication required, you still need to specify which
+users can send email with what addresses. This was a bit of a surprise to me
+initially because I was under the impression that a password is associated with
+an email address, not an email address(s) associated with a username and
+password. To keep users from being able to send email as addresses that are not
+theirs (specifically randomly generated addresses in my case), you need to
+create a mapping file that maps usernames to the addresses they are authorized
+to send mail as. In my case, this is a one to one relationship (one address per
+username). Before my example I'd like to note that the filename is not
+required to be the one I use (though my filename is the one used in the Postfix
+setup documentation).
+
+Okay. Let's create the map file. To do this, open up and edit
+/etc/postfix/controlled_envelope_senders (this file likely doesn't exist yet)
+
+----
+vim /etc/postfix/controlled_envelope_senders
+----
+
+Once you've got that open, you simply need to put the maps in there.
+
+----
+# envelope sender owners jcricket@example0.com jimminey
+----
+
+Now that we've done that, we need to turn it into a binary. Run the following
+command and it will generate a <filename>.db binary map file in the same
+directory as the original file.
+
+----
+postmap /etc/postfix/controlled_envelope_senders
+----
+
+Presto! Now the user jimminey can send email as jcricket@example0.com. However,
+so can everyone else...still.
+
+Now that we have our controlled envelope senders file, we need to reference it
+in our postfix main.cf and set postfix up to restrict access to the maps
+specified in that file. Crack er open in your favorite editor and put the
+following line in somewhere after *smtpd_sasl_auth_enable*
+
+----
+smtpd_sasl_auth_enable = yes
+...
+# This line specifies our map file for use by postfix
+# Note that this does NOT reference controlled_envelope_senders.db
+smtpd_sender_login_maps = hash:/etc/postfix/controlled_envelope_senders
+# This line sets postfix to reject anyone who authenticates but tries to send email as an address they aren't permitted to use
+smtpd_recipient_restrictions = reject_sender_login_mismatch, permit_sasl_authenticated, reject_unauth_destination
+----
+
+So what we've just done is tell Postfix where our map file is
+(smtpd_sender_login_maps). After that, we tell Postfix to reject any users that
+have been authenticated but are trying to send with an address they aren't
+authorized to send with in our map file (smtpd_recipient_restrictions). Please
+note that *reject_sender_login_mismatch* comes at the beginning of the
+smtpd_recipient_strictions field. This is key. It is so key in fact, that I
+missed it (I only miss the key stuff of course thanks Murphy). This was the
+forth exploit attempt that got me.
+
+
+[[misordering-smtpd_recipient_restrictions]]
+Misordering smtpd_recipient_restrictions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This one is the final bit that let the spammers in (so far at least).
+
+The smtpd_recipient_restrictions are restrictions that you can place on
+the users and their emails based on various things. In my case, I had
+the following restrictions string
+
+----
+smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_sender_login_mismatch, reject_unauth_destination
+----
+
+Postfix applies these restrictions in the order in which they are specified. As
+they put it <blockquote>Restrictions are applied in the order as specified; the
+first restriction that matches wins.</blockquote> As soon as one restriction
+matches, then the ones that follow don't get applied. This was very
+problematic because in my case permit_mynetworks is first. So that I can log
+in from my cell phone which has an IP address that changes, I set
+
+----
+mynetworks = 0.0.0.0/0 127.0.0.0/8 [::fff:127.0.0.0]/104 [::1]/128
+----
+
+which allows any IP address to connect to my SMTP server. Since Postfix takes
+the first match and goes no further and any IP address is in 0.0.0.0/0, anyone
+can send mail through my SMTP server. This = bad.
+
+What you should do is start your restrictions with the the most strict
+restrictions followed by the less strict. In my case, that looks like
+
+----
+smtpd_recipient_restrictions = reject_sender_login_mismatch, permit_sasl_authenticated, reject_unauth_destination
+----
+
+In the event someone tries to send an email, first they must login. If they
+don't log in, they are rejected due to reject_sender_login_mismatch (we can't
+do a match if we don't have a sender username). Secondly, once logged in, the
+user must be authorized to use the address they are trying to send as as
+specified in the smtpd_sender_login_maps line. Finally, once the user has been
+authenticated and they have permissions to use the address they are trying to
+send as, their email is not rejected. It follows that they are then filtered
+through permit_sasl_authenticated. This basically runs a check to see if they
+are authenticated (which we know they already are because of the previous
+filter) and since they are, they are permitted and Postfix stops looking for
+more matches because it's found one that permits the user to perform their
+requested action.
+
+As chef Elzar says, "Bam!"
+
+
+Category:Linux
+Category:Postfix
+
+
+// vim: set syntax=asciidoc:

Generated by cgit