I was toying idly with the idea of moving to a new ISP who, while offering a faster connection, did not offer an email facility. This would mean I'd either have to use free email facilities (such as gmail) or start using the domain names I owned already for mail addresses. The latter course naturally implied that I'd need to set up the FreeBSD-based mail server to allow POP and SMTP relay access from outside the LAN, as I often work away from home for brief periods.
After some research, I determined that I'd need to setup an X.509 certificate to ensure that any SMTP/POP traffic from the Internet would be encrypted and authenticated.
I started by setting up a POP capability. I leaned heavily an article on http://www.vanemery.com/Protocols/POP/qpopper-bsd-howto.html (no longer available) on setting up a secure POP capability on FreeBSD, using qpopper. I already had qpopper installed, and this article gave a clean, step-by-step process to follow.
First, here's the steps to create a certificate, boiled down into a simple script:
# generate key for root CA cert openssl genrsa -des3 -out hydrus-ca.key 2048 # generate root CA cert openssl req -new -x509 -days 3650 -key hydrus-ca.key -out hydrus-ca.crt # generate key for mail cert openssl genrsa -out mail-key.pem 1024 # generate cert request; this has to be signed by the CA openssl req -new -key mail-key.pem -out mail-cert.csr # sign certificate request, using mini-CA facility of x509 openssl x509 -req -in mail-cert.csr -out mail-cert.pem -sha1 \ -CA hydrus-ca.crt -CAkey hydrus-ca.key -CAcreateserial -days 3650 # copy cert and key to location accessible by sendmail/qpopper cp mail-cert.pem /etc/mail/certs cp mail-key.pem /etc/mail/certs chmod 400 /etc/mail/certs/*
Running this script requires a lot of user input, in order to fill in the key fields of the root CA certificate and the mail certificate request. It is possible to create an openssl configuration file to pre-fill these inputs, as I discovered via this write-up on certificate set-up, this time for Debian.
Combining these approaches, we arrive at a modified script to create the root CA and the mail certificate:
# generate key for root CA cert openssl genrsa -des3 -out hydrus-ca.key 2048 # generate root CA cert openssl req -new -x509 -key hydrus-ca.key -out hydrus-ca.crt \ -config openssl.conf # generate key for mail cert openssl genrsa -out mail-key.pem 1024 # generate cert request; this has to be signed by the CA # remember to set the Common Name to the FQDN of the server, otherwise # users will be plagued at cert acceptance. openssl req -new -key mail-key.pem -out mail-cert.csr -config openssl.conf # sign certificate request, using mini-CA facility of x509 openssl x509 -req -in mail-cert.csr -out mail-cert.pem -sha1 \ -CA hydrus-ca.crt -CAkey hydrus-ca.key -CAcreateserial -days 3650 # copy cert and key to location accessible by sendmail/qpopper cp mail-cert.pem /etc/mail/certs/cert.pem cp mail-key.pem /etc/mail/certs/key.pem chmod 400 /etc/mail/certs/*
The openssl.conf
file the above script relies on contains
the following:
# # OpenSSL configuration file. # # Establish working directory. dir = . [ ca ] default_ca = CA_default [ CA_default ] default_days = 3650 default_md = md5 preserve = no email_in_dn = no nameopt = default_ca certopt = default_ca policy = policy_match [ policy_match ] countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional [ req ] default_bits = 2048 # Size of keys default_md = md5 # message digest algorithm string_mask = nombstr # permitted characters distinguished_name = req_distinguished_name [ req_distinguished_name ] # Variable name Prompt string #---------------------- ---------------------------------- 0.organizationName = Organization Name (company) organizationalUnitName = Organizational Unit Name (department, division) emailAddress = Email Address emailAddress_max = 40 localityName = Locality Name (city, district) stateOrProvinceName = State or Province Name (full name) countryName = Country Name (2 letter code) countryName_min = 2 countryName_max = 2 commonName = Common Name (hostname, IP, or your name) commonName_max = 64 # Default values for the above, for consistency and less typing. # Variable name Value #------------------------------ ------------------------------ 0.organizationName_default = hydrus.org.uk localityName_default = Reading stateOrProvinceName_default = Berkshire countryName_default = UK
Enable qpopper on pop3 and pop3s with the following lines in
/etc/inetd.conf.
# # Qpopper pop3 server # pop3 stream tcp nowait root /usr/local/libexec/qpopper \ qpopper -f /usr/local/etc/qpopper/STLS-110.conf pop3s stream tcp nowait root /usr/local/libexec/qpopper \ qpopper -f /usr/local/etc/qpopper/TLS-995.conf
Setup the qpopper configuration files:
# Qpopper Configuration File #1 # TCP 995 for those e-mail clients that can't handle STARTTLS (STLS) set tls-support = alternate-port set config-file = /usr/local/etc/qpopper/qpopper.conf
# Qpopper Configuration File #2 # Runs on TCP 110, uses STARTTLS (STLS) method set tls-support = stls set config-file = /usr/local/etc/qpopper/qpopper.conf
# Qpopper Main Configuration File set statistics set downcase-user set timeout = 180 set clear-text-password = tls set tls-server-cert-file = /etc/mail/certs/cert.pem set tls-private-key-file = /etc/mail/certs/key.pem
This part was mostly achieved by reference to this secure
sendmail article. To precis that article, first you need
saslauthd
, which performs a password check on behalf of
sendmail. I obtained this by:
pkg_add -r cyrus-sasl-saslauthd
Ensure that /usr/local/lib/sasl2/Sendmail.conf
exists and
contains the following line:
pwcheck_method: saslauthd
I already had cyrus-sasl2 installed to support authentication against my
ISPs mail server. Enable saslauthd by adding
saslauthd_enable="YES"
to /etc/rc.conf
To instruct sendmail to listen on the smtps port, you must add to
the /etc/make.conf
options for sendmail (in addition to the
settings to compile/link against
sasl2):
# Adding to enable alternate port (smtps) for sendmail... SENDMAIL_CFLAGS+= -D_FFR_SMTP_SSL
Rebuild sendmail (ala an earlier journal entry).
Add trust for authenticated users and location of certificates to
the sendmail config file, /etc/mail/crimson.mc
dnl Settings for SMTP AUTH as client and server define(`confAUTH_MECHANISMS',`LOGIN PLAIN') dnl Allow authenticated users relay access TRUST_AUTH_MECH(`PLAIN LOGIN')dnl dnl Offer SMTP AUTH only after encryption (STARTTLS) has been negotiated define(`confAUTH_OPTIONS',`p,y')dnl dnl Don't ask for client cert(s) define(`confTLS_SRV_OPTIONS', `V') define(`CERT_DIR', `/etc/mail/certs')dnl define(`confCACERT_PATH', `CERT_DIR')dnl define(`confCACERT', `CERT_DIR/cert.pem')dnl define(`confSERVER_CERT', `CERT_DIR/cert.pem')dnl define(`confSERVER_KEY', `CERT_DIR/key.pem')dnl define(`confCLIENT_CERT', `CERT_DIR/cert.pem')dnl define(`confCLIENT_KEY', `CERT_DIR/key.pem')dnl DAEMON_OPTIONS(`Port=smtp, Name=MTA')dnl dnl Offer STARTTLS at session beginning for smtps (M=s) DAEMON_OPTIONS(`Port=smtps, Name=TLSMTA, M=s')dnl
The flags for AUTH_OPTIONS are none-too easy to find, but are
described in the doc/op.me
file that comes with the
sendmail distribution. The options used above are as follows:
p don't permit mechanisms susceptible to simple passive attack (e.g., PLAIN, LOGIN), unless a security layer is active. y don't permit mechanisms that allow anonymous login.
There is one more option that might be useful:
A Use the AUTH= parameter for the MAIL FROM command only when authentication succeeded. This can be used as a workaround for broken MTAs that do not implement RFC 2554 correctly.
Then, build the sendmail.cf
file and restart sendmail:
cd /etc/mail make && make install && make restart
To be able to use the hydrus.org.uk domain as an email address, I had to add an IP address for hydrus.org.uk in the local DNS server (as described in this Linux oriented DNS article). Otherwise, crimson would refuse to accept mail, saying the "hydrus.org.uk" domain name was unknown. The start of the BIND zone file for hydrus.org.uk now looks like:
hydrus.org.uk IN SOA crimson.hydrus.org.uk. root.crimson.hydrus.org.uk. ( 10612 ; serial 10800 ; refresh (3 hours) 3600 ; retry (1 hour) 604800 ; expire (1 week) 3600 ; minimum (1 hour) ) NS crimson.hydrus.org.uk. A 192.168.0.10