Sunday, March 31, 2013

Configuring TLS on Postfix - RedHat AWS EC2 instance - Amazon Cloud

Please note. This didn't really end up working. Leaving notes for all the things I did get working however. This is old and not recommended - just use the AWS mail services or some other cloud based mail service and save yourself some pain.

AWS SES
AWS Workmail
Gmail

---
Attempting to set up Postfix on Amazon EC2 instance with TLS and authentication to work with Postini mail security service. Steps taken (Caveat - I have never done this before today and currently re-learning Linux):

If you haven't already created a private key create one becausee you'll need it to connect to Linux server below:
 

http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-credentials.html#using-credentials-login-password

If you haven't already created a VPC (virtual private network) create one, or don't use VPC in the example below.

AWS documentation has four scenarios for setting up VPCs for different purposes:


http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Scenarios.html

Configure the VPC security group you use for the mail server below to the IP address of the machine you are using to administer the EC2 instance. You can find your IP address as the outside world sees it (not the local IP address internal to your network) at the top of http://dnsstuff.com You can give this IP access to all ports and protocols or specifically the ports and protocols needed to set up the mail server (22 for SSH, 25 for SMTP, any non-standard ports you want to send mail from, etc).


You'll also need to open up access to Postini and from any servers from which you want to relay mail to Postini on applicable mail ports (25, etc). See link regarding Postini outbound configuration in steps below.

Hint: Before even attempting anything with Postfix, make sure your network connectivity is set up correctly (your VPC and firewalls on machines). If at any point you are trying to send mail from another machine through the Postfix server and no messages are showing up in Postfix logs, it could be a network problem that has nothing to do with Postfix. A connection may have never been made to/from the local or remote machine which has nothing to do with Postfix. You'll need to fix that first. You can test network connectivity by opening up all ports between the various machines and IPs or at least the port and protocol required to ping and test that you can ping and get a reply from the postfix machine on the machine you are trying to send mail from. Once that's working then move on to Postfix configuration.

I checked and by default the Amazon AWS ec2 redhat instances do not have a firewall running. I did have to adjust the firewall on a Windows instance to open the necessary ports to access the Linux machine.

Ok now for the nitty gritty.

The goal here is to send mail from an application server through the mail server to Postini, which will then be verified encrypted and routed to the appropriate party. Using Postini ensures only valid IP ranges can send mail outbound and you can enforce TLS encryption.Postini also checks outbound mail for viruses and spam.


--- Get EC2 Linux RedHat instance from Amazon ---

1. login and go to EC2 Dashboard
2. Click "Launch instance"
3. Choose classic wizard
4. Click continue
5. Click Community AMIs
6. Enter Amazon Linux ID you want to use (ami-8e27adbe for oregon or see bottom of this page http://aws.amazon.com/amazon-linux-ami/)
Note: Make sure you select an ami in the same region where you created your VPC.
 7. Click select
8. Choose size (T1 Micro for my test)
9. Click on EC2-VPC tab (assuming you created a VPC)
10. Choose an Internet accessible subnet for your server where the VPC security group you want to use for your mail server is located.
11. Click continue on next page (I didn't change anything)
12. Update the mail tag to some name that helps you identify this server
13. Click continue
14. Choose a key pair you created previously or create a new one
15. Choose a security group - in my case I created a mail specifc security group that can access my Postini specified IP range for my account and allows access from the servers in my network that are allowed to send mail.

I opened up the ports I have configured my apps to send mail on and 25/465 to Postini (seems to only be sending on 25 at this point but my apps send mail to the mail server on other ports)

16.Click continue
17. Click launch
18. Click close (unless you want to create alarms)
19. Wait for your instance to fire up -- will say "initializing" in your instance list
20. Assign an elastic IP address from your VPC to your instance (you may have problems connecting without it)
20. Right click on the instance and choose connect
21. Enter the path to your private key and connect - you should now be able type commands that execute on your server in the window that pops up.

--- DNS - if you want ---

Configure a domain name to point to your IP address. For exmaple you may want to configure mail.yourdomain.com to point to your elastic IP address.

I'm not going into details on the above - contact your domain name provider, use a distributed, redundant DNS service like http://EasyDNS.com or check out the options from Amazon DNS service which they call "Route 53" http://aws.amazon.com/route53/.

Configure an SPF record in your DNS to indicate that only Postini IPs are valid IPs for sending mail from your domain - to help prevent people from spoofing your emails or having your mails end up in spam mailboxes (hopefully).

Something like this, though I want to go back and review this later to make sure it is the best option:

v=spf1 ip4:64.18.0.0/20 ~all


--- Install and Configure Postfix ---

Install Postfix and get rid of Sendmail if you want.

sudo yum install postfix
sudo yum erase sendmail

Note: If you have problems connecting to AWS repo see this post:
http://websitenotebook.blogspot.com/2013/03/connection-timeout-running-yum-on-ec2.html

You might want to back up the original postfix configuration files:

sudo cp /etc/postfix/main.cf /etc/postfix/bak/main.cf
sudo cp /etc/postfix/master.cf /etc/postfix/bak/master.cf

Figure out how to use vi again if you forgot like me and edit main.cf in the postfix directory

Navigate to /etc/postfix

Use VI to edit main.cf:

sudo vi main.cf

hit "i" to insert text

When you are done editing save by typing ctrl-C then:

:wq!

Edit the main.cf file with the following settings:

myhostname = [mail.yourdomain.com or whatever your mail server hostname is]

mydomain  = [mail.yourdomain.com or whatever your mail domain is]

inet_interfaces = all  [and comment out anything else]

mydestination = $mydomain, $myhostname

mynetworks = [ip addresses/ranges for which you want to allow relay - limit to trusted networks]

relayhost=outbounds[x].obsmtp.com (where [x] is the number in the domain when you login at Postini -- indicating which particular Postini server(s) your account uses)

Type ctrl-C and :wq! to save and exist the file

restart the service:

sudo service postifix restart

--- Add your new instance as a reinjection host at Postini ---

At this point, make sure your VPC is allowing access from the mail server via the VPC security group the mail server is in to the Postini IP addresses for your Postini account.

You can then add your new mail server VPC elastic IP address at Postini so Postini can send bounce messages back to your mail server.

Postini will test connection to your mail server and that it can send mail at this point so you'll know if something is wrong. Check the VPC and your Postfix Configuration if Postini can't connect to your mail server at this point.

Postini outbound configuration and IP addresses:

http://www.google.com/support/enterprise/static/postini/docs/admin/en/admin_ee_cu/ob_setup.html 

--- Send a message ---

...ok at this point you should have mail going over to Postini if your firewalls are set up correctly. You can send a test message with this command:


sendmail [put email address here]
FROM: [put email address here like ec2-user@your.domain.com]
SUBJECT: hello world
this is a test email
.

Check postfix logs to see if your message was sent. 

sudo tail -f /var/log/maillog

If you limit sending to TLS you'll see an error message related not being able to send unless TLS is enabled

451 STARTTLS is required for this sender - psmtp (in reply to MAIL FROM command))

Install mutt to check and see if you get a bounce message.

sudo yum install mutt

To run mutt must type: 

mutt
 
When you're done reading  messages type

q

There won't be a bounce because the message is still in the postfix queue. Check:

postqueue -p
  
You'll see something like this:
 
96D8C200FB      319 Sun Apr  7 05:44:10  ec2-user@mx.domain.com
(host outbounds5.obsmtp.com[64.18.6.12] said: 451 STARTTLS is required for this sender - psmtp (in reply to MAIL FROM command))
                                         user@domain.com

-- 0 Kbytes in 1 Request.


If you log into Postini and change your settings to allow SMTP the message will go through: 

Login, click on outbound servers, choose your domain, click on TLS.

1. Choose how the email protection service accepts outbound messages from your mail server. 


Choose: Accept SMTP and TLS.

Flush the Postmail queue:

sudo postfix flush
     
Now use tail command above and you should see the mail was sent.

Apr  7 06:52:05 ip-10-0-0-112 postfix/smtp[18321]: 96D8C200FB: to=, relay=outbounds5.obsmtp.com[64.18.6.12]:25, delay=4076, delays=4072/0.03/0.15/3, dsn=2.0.0, status=sent (250 Thanks)
Apr  7 06:52:05 ip-10-0-0-112 postfix/qmgr[18226]: 96D8C200FB: removed

 

That's nice. But that's not really what we want. We just sent unencrypted email over the internet which can be read by anyone.

Go back to Postini and choose the option to accept only TLS and save.

This might be a good point to make a back up of your mail config as well.

--- Get an SSL certificate for TLS ---

I  noticed that when I installed Postfix, OpenSSL was installed:

Processing Dependency: libcrypto.so.10

(OPENSSL_1.0.1)(64bit) for package: 2:postfix-2.6.6-2.14.amzn1.x86_64
 

....

Package openssl.x86_64 0:1.0.0j-1.43.amzn1 will be updated
---> Package openssl.x86_64 1:1.0.1e-4.53.amzn1 will be an update
--> Processing

Dependency: make for package: 1:openssl-1.0.1e-4.53.amzn1.x86_64
--> Running transaction check
---> Package

make.x86_64 1:3.81-20.7.amzn1 will be installed
--> Finished Dependency Resolution

Dependencies Resolve


If needed you could install openssl:

sudo yum install openssl

Make a directory for your ssl files and migrate to it:

sudo mkdir /etc/postfix/certs

Digicert has some tools to generate a CSR using openssl:

Info about OpenSSL CSR Creation:

http://www.digicert.com/csr-creation-apache.htm

A form you can fill out to create the code that generates the CSR on your server:

https://www.digicert.com/easy-csr/openssl.htm

The command it creates will look *something* like this. This has my cert specific info so make sure you go to the page above and create a CSR with your specific domain name, location, etc. I added -outform PEM because these things need to be in PEM format and I saw that on another web site. Not sure if it matters.

openssl req -new -outform PEM -newkey rsa:2048 -nodes -out domain_com.csr -keyout star_domain_com.key -subj "/C=US/ST=WA/L=Seattle/O=Radical Sofftware Inc./CN=*.domain.com"

Run the above command in your directory to get the new key and csr files.

Go to Digicert and request a new Apache cert. Paste the contents of the CSR file that was generated in your /etc/postfix/certs directory when you ran the above command into the text box for the request on the web site. See Digicert link with instructions above for more info.

Submit and wait for the new cert to be generated (varies depending on if getting new or existing).

When your cert is ready go to the Digicert web site (I prefer not to use the one that comes in the email), log into your account, and download the new cert.

Choose option for PEM file with all certs in it.

Save it in your /etc/postfix/certs directory as domain.PEM where domain is your domain name.

Download and install putty so you can telnet to your Linux machine.Run or use your telnet tool of choice.

http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html

Enter your elastic IP and choose Telnet. Click open.
  Type 

EHLO [your mail serer domain here]


For some reason the first time I type it doesn't work. I type it again and get the desired response showing TLS is running:


250-your.mailserver.tld
250-PIPELINING
250-SIZE 10240000
250-ETRN
250-STARTTLS
250 8BITMIME
 
Try another test message as described above. You'lll see the same error in the logs when you tail (451...). This is because what we just enabled is for inbound mail.

What we need to do now is encrypt outbound mail.

--- Add outbound mail configuration for TLS ---

mtp_tls_cert_file = /etc/postfix/certs/cert.pem
smtp_tls_key_file = /etc/postfix/certs/key.pem
smtp_use_tls = yes
smtp_enforce_tls = no

 

Check it out to see if our message now gets sent.

sudo postfix reload
sudo postfix flush
sudo tail -f /var/log/maillog

Using tail it looks like the message got sent but there's an error message about an untrusted issuer:

Apr  7 08:09:08 ip-10-0-0-112 postfix/smtp[18657]: certificate verification failed for outbounds5.obsmtp.com[64.18.6.12]:25: untrusted issuer /C=US/O=Equifax/OU=Equifax Secure Certificate Authority

What is odd is that the message does actually get sent. You can verify this by checking the queue and it will be empty:

sudo postqueue -p 
Mail queue is empty
 

What is also odd is that the mail doesn't show up right away in the mailbox I sent it to but does after many hours of delay. (Like I went to bed and in the morning it showed up).

I contacted DigiCert at this point and was told:

Looking at the error, it states your server is pulling an Equifax certificate.  If you have installed and bound our certificate successfully, then all you would need to do is reboot the server for it to start using our certificate.  If the reboot does not fix your problem, you will need to check the bindings on your server and correct them.

Go to ec2 instances in AWS EC2 dashboard. Right click on instance. Choose reboot.

I tried to send a new email and got the same error in the logs.

Went to DigiCert web site and downloaded individual files, zipped.

Copied DigiCertCA.crt to /etc/postfix/certs and renamed with .PEM extension.

Restarted postfix and got an error saying for some reason could not load the ca file so was disabling TLS.

Apr  7 17:03:08 ip-10-0-0-112 postfix/smtp[1687]: cannot load Certificate Authority data: disabling TLS support

I checked and the file was missing the first few letters. I am not sure if this is a problem when pasting text from a windows machine into the MindTerm AWS Linux client or I just copied only part of the file. I fixed that, saved the file, reloaded postfix.

No error. Message sent!

Apr  7 17:07:31 ip-10-0-0-112 postfix/postfix-script[1714]: refreshing the Postfix mail system
Apr  7 17:07:31 ip-10-0-0-112 postfix/master[1549]: reload -- version 2.6.6, configuration /etc/postfix
Apr  7 17:07:36 ip-10-0-0-112 postfix/qmgr[1719]: 6469620158: from=
, size=326, nrcpt=1 (queue active)
Apr  7 17:07:39 ip-10-0-0-112 postfix/smtp[1728]: 6469620158: to=
, relay=outbounds5.obsmtp.com[64.18.6.12]:25, delay=683, delays=681/0.08/0.31/2.3, dsn=2.0.0, status=sent (250 Thanks)
Apr  7 17:07:39 ip-10-0-0-112 postfix/qmgr[1719]: 6469620158: removed


Sweet. That only took a million tries to get this all working.

Only problem now is that the mail hasn't shown up in the recipient inbox.

What is also interesting is that even though my server indicates the message was sent, I see no indication in the Postini outbound logs for this domain that the message was received.

Next I looked at the quarantine for the user I am sending to and I see that the messages are, in fact there. They have been flagged as spam. Probably tripped up after sending too many requests. Should not be flagged as spam otherwise, because my SPF records are set to include the new AWS elastic IP address.


This would be another excellent point to back up your main.cf file. :)

--- Open other ports if needed ---

Ok now I want to open up some other ports to send mail on from other applications that require specific ports.

sudo vi /etc/postfix/master.cf

Add a line for the port you want to open up (make sure your VPC allows connections on this port). You can see the line I added bellow in bold. Note that the type is inet to allow connections from the Internet and the command is smtpd.

# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
smtp      inet  n       -       n       -       -       smtpd 

468       inet  n       -       n       -       -       smtpd 


Check the logs to make sure everything is groovy. No errors. Like an i at the start of the file when typing i for insert too many times which causes you to get a message about an invalid transport type. Not that I ever did such a thing.

Now open putty as instructed above and test EHLO but this time connect on your new port - 468 in the example above. If you get the expected results with EHLO your mail system is open and listening on that port.

Another fine time to back up master.cf

Now you possibly want to authenticate users (i.e. have them login with a user name and password). That's going to be handled in my next post.

Friday, March 29, 2013

Connection Timeout Running Yum on EC2 instance with VPC

I was getting a connection error like this trying to run Yum on an Amazon AWS EC2 Redhat Linux instance in a public subnet of a VPC with a security group I had set up specifically for this machine.

http://packages.us-west-2.amazonaws.com/2012.09/main/201209eb6a01/x86_64/repodata/repomd.xml: [Errno 12] Timeout on http://packages.us-west-2.amazonaws.com/2012.09/main/201209eb6a01/x86_64/repodata/repomd.xml: (28, 'connect() timed out!') Trying other mirror.

I found that opening up outbound traffic completely for the security group for that server resolved the problem and was able to successfully download packages.

Last night I talked to some Amazon folks at an event recently that told me because the VPC is a stateful firewall it would be OK to open all outbound traffic for that server.

However... If prefer to know that you are getting your updates from a valid Amazon repo or at least an Amazon IP, you can open up your outbound traffic in your security group to the specific IPs or IP ranges for the repo(s) you are trying to connect to.

For instance, if the error message says you are trying to connect to: http://packages.us-west-2.amazonaws.com...

Open a command prompt and ping packages.us-west-2.amazonaws.com
I got IP address: 205.251.235.166

The IP for this repo could change obviously but you could set up your security group to allow outbound traffic to this IP address. If the IP for that repo changes at some point you'll get an error and have to change the IP to whatever Amazon changes the domain to point to in the future.

You can also go to Arin.org and get the complete Amazon IP range for this IP and allow traffic to all Amazon IP adddresses outbound. In this case 205.251.192.0/18

http://whois.arin.net/rest/net/NET-205-251-192-0-1/pft

NetRange 205.251.192.0 - 205.251.255.255
CIDR 205.251.192.0/18
Name AMAZON-05
Handle NET-205-251-192-0-1
Parent NET205 (NET-205-0-0-0-0)
Net Type Direct
Assignment Origin AS AS7224 AS16509 AS39111
Organization Amazon.com, Inc. (AMAZON-4)
Registration Date 2010-08-27
Last Updated 2012-03-02
Comments RESTful Link http://whois.arin.net/rest/net/NET-205-251-192-0-1

When I ping  packages.sa-east-1.amazonaws.com I get a Lacnic IP address:

177.72.244.0

You'd have to go to lacnic.org to look up that IP range:
inetnum:     177.72.240/21
aut-num:     AS53032
abuse-c:     MAAZI67
owner:       A100 ROW SERVICOS DE DADOS BRASIL LTDA
ownerid:     012.147.176/0001-50
responsible: Marla Azinger
country:     BR
owner-c:     MAAZI67
tech-c:      MAAZI67
inetrev:     177.72.240/21
nserver:     pdns1.ultradns.net 
nsstat:      20130329 AA
nslastaa:    20130329
nserver:     pdns2.ultradns.net 
nsstat:      20130329 AA
nslastaa:    20130329
nserver:     pdns3.ultradns.org 
nsstat:      20130329 AA
nslastaa:    20130329
nserver:     pdns5.ultradns.info 
nsstat:      20130329 AA
nslastaa:    20130329
nserver:     pdns6.ultradns.co.uk 
nsstat:      20130329 AA
nslastaa:    20130329
created:     20110816
changed:     20111121

nic-hdl-br:  MAAZI67
person:      Marla Azinger
e-mail:      mazinger@amazon.com
created:     20111114
changed:     20111118