Notes about Solaris Nevada/OpenSolaris Sendmail Configuration

About maybe a month ago, I started seeing hard drive DMA errors reported in the logs on one of my venerable servers that's been receiving most of my family's email since 1999. It originally had a whopping 15GB drive which was posh for 1999, but that drive died suddenly with a shorted out power supply unit, which prompted a self-repair of the PSU (my first attempt a soldering new high frequency switch caps into a PSU) in 2001. I swapped that out with a new 40GB Seagate ST3004xx something drive that was the rage back then. The first, I think, with the fluid dynamic bearings or something like that and ultra quiet. Fast forward to last month and the PSU is still working great but the disk drive, now on its 7th year, had started to go bad.

At first it was just a couple error messages on the console per week. But as the weeks progressed, the errors were becoming more frequent, to the point where I was seeing 23 errors in less than 30 minutes a couple weeks ago. I decided to swap out and upgrade that venerable box to new smaller, cooler, lower-power hardware. I had been dreading this task because I remembered the pains it took to configure the sendmail daemon back then. But with my final backup of email taking over 15 minutes for an incremental 6.8 MB of data, I managed to probably avert data loss by the thinnest of margins.

The new box - an older system

I'm not one to throw away perfectly good hardware, even if it is past its prime. And with hardware rev'ving every quarter, just about any box over a year old is past its prime. I decided to base my new mail server on a first generation EPIA 800 from VIA. It's a mini-ITX board with 800MHz VIA c3 cpu that chugs along and sips power. The first generation boards were shipped in quantity starting in 2002, and I picked up a couple back in 2003, so these are 5 years old. A real slow poke, but for a headless mail server box, it's perhaps perfect. It isn't like I can afford a fat OC3 pipe to my house anyway, so for normal broadband type speeds, this is perfect. Plus, at 14Watts idle, and 17Watts when small chunks of email come in, the system works just fine. I enclosed this system with a very small Morex/Cubid 2699 style case with AC adapter power supply, and included a 60 GB IDE notebook drive and slim optical DVD drive. I originally debated whether to keep the optical drive in the case because of fear that the standby power might be quite high. But as it turns out, it's only about 1Watt in standby mode. When burning, the drive can cost an extra 10 Watts. The motherboard has onboard audio, video and LAN. I have 1 GB (2 x 512MB PC133 SDRAM) in the box.

OS Install and Systems Admin

For a mail server, I went into BIOS and pretty much disabled the audio, the serial ports, and configured the system to reboot to its original power state if there is a sudden loss of power. Solaris Nevada b90 was the latest available and it installs fine on this 32-bit system, only the old Unichrome graphics isn't well supported. But for a box that is running headless, it was easy enough to avoid the SXDE installer and use the old style express installer in text console mode. After booting for the first time, I logged in and disabled cde-login:

    # svcadm disable cde-login

I then used a USB stick to transfer Murayama's vfe2.6.2a driver source code and the GLDv3 headers required to compile the driver (mac.h, mac_ethers.h, dld.h) to compile and install the network driver.

Once booted and up on the network, I quickly enable tcp_wrappers and ipfilter. A mail server is going to sit on the public internet and get probed many thousands of times per day, so it's not for the faint of heart. It really requires hardening the the network configuration. Some folks opt for a hardware firewall, but I've seen attackes against those, too that can corrupt firmware or take over the firewall box. But it's not too difficult to quickly shut things down.

TCP services can be firewalled immediately by creating a file called /etc/hosts.deny and having:

    ALL:    ALL

inside that file. And conversely, an /etc/hosts.allow file which has specific hosts and services listed. I basically open up everything to my localhost, SSH for my internal private network, and sendmail and imapd to the world.

    ALL:   localhost
    imapd: ALL
    sendmail:  ALL

To start TCPwrappers, just issue the commands:

    # inetd -M tcp_wrappers=true; svcadm refresh inetd

I also shutdown any RPC communications with TCPwrappers by using the command:

    # svccfg -s rpc/bind setprop config/enable_tcpwrappers=true; svcadm refresh rpc/bind

There should be some great articles hosted on Sun's BigAdmin website on TCPwrappers configuration that folks can use their favourite search engine and find.

To configure IP Filters, I edit the file /etc/ipf/ipf.conf and put something like:

# IP Filter rules to be loaded during startup
# See ipf(4) manpage for more information on
# IP Filter rules syntax.
# IP Filter config file - James Liu, 2005-Jan-19
# -----------------------------------------------------
# let all loopback traffic flow freely
pass in quick on lo0 all
pass out quick on lo0 all
# -----------------------------------------------------
# default rule set - block all incoming packets but let in
# certain protocols and keep state 

# Nasty short packets which are fragmented too short to be real.
block in log quick all with short

# start by blocking and logging everything on vfe0 by default
block in log on vfe0 all
block out log on vfe0 all

# block and drop network spoof packets (these are reserved) and
# any packets that should only be on loopback only for vfe0
pass in quick on vfe0 proto tcp from to any keep state
block in quick on vfe0 from to any
block in quick on vfe0 from to any
block in quick on vfe0 from to any
block in quick on vfe0 from to any
block in quick on vfe0 from to any
block in quick on vfe0 from to any
block in quick on vfe0 from to any
block in quick on vfe0 from to any

# log any attempts to route to reserved network or broadcast addrs
block in log quick on vfe0 from any to
block in log quick on vfe0 from any to

# Any tcp, udp from this interface outbound, pass out
# Any icmp from this interface outbound, pass out
pass out quick on vfe0 proto tcp/udp from to any keep state
pass out quick on vfe0 proto icmp from to any keep state
#-------------------- web service -----------------------
pass in quick on vfe0 proto tcp from any to port = 80 flags S keep state
pass in quick on vfe0 proto tcp from any to port = 443 flags S keep state
#-------------------- ssh service -----------------------
pass in quick on vfe0 proto tcp from any to port = 22 flags S keep state
#-------------------- sendmail service -----------------------
pass in quick on vfe0 proto tcp from any to port = 25 flags S keep state
pass in quick on vfe0 proto tcp from any to port = 587 flags S keep state
#-------------------- secure imaps service -----------------------
pass in quick on vfe0 proto tcp from any to port = 993 flags S keep state

Basically, you'll need to change IP addresses for your network. But as you can see, I open up HTTP and HTTPS ports on 80 and 443 just in case I want to run some web-email-proxy software like Squirrel Mail so folks can get their email via a web browser, like Yahoo! or GMail. I run Apache and it's a standalone server process not using TCPwrappers, but the SSHd daemon and sendmail are compiled to use libwrap, so hence we have entries for them in the /etc/hosts.allow file. I need to be able to SSH to the box to manage it so I open up port 22. Sendmail and sendmail's mail submission program listen on ports 25 (smtp) and 587 (submission) respectively. The port 587 was specified because many ISPs block port 25 traffic inside their DHCP networks to reduce spam. The switchs and routers only permit SMTP traffic to their own mail servers where they have control of who's routing the email to whom. Port 587 is configurable and allows folks to workaround the port 25 blockage and route email outside to a different SMTP server the user knows is available. Lastly, since I run secure IMAP with SSL, I open up port 993 which is the default for most imaps clients.

Once the network is relatively secured, I streamline the server by removing or moving out most of the legacy services in /etc/rc3.d and /etc/rc2.d. I also disabled a lot more services like webconsole, wbem, smserver, some of the rpc/cde stuff, the font/fc-cache, basicreg, ndp, installupdates, print/ppd-xxx, autofs, uucp, and stuff that a mail server isn't going to need.

Sendmail Server Configuration

The default distribution of Nevada or OpenSolaris has a fairly vanilla configuration that's basically the same as Berkeley Sendmail. It supports almost all of the features you'd find in 8.14.2 and if you telnet localhost 25 on the box, that's what the HELO/EHLO ESTMP reponse comes back with. But what's missing still are some default configurations that allow a user to take OpenSolaris and start up a real, external facing mail server. But if you've done this before on another box, even a Linux box, you can usually take the (m4 macro file) and move it over, and if the configuration is for a relatively recent version of sendmail, it should just compile and generate a working

Nevada and OpenSolaris keep the sendmail cf/mc files in /usr/lib/mail/cf. There's a handy Makefile inside that directory that can help you create a custom easily. I have a standing .mc file from a few years back that seems to work okay. I leverage some of the Berkeley anti-spam features as well as setup a mail relay based on a limited number of known hosts. My mail server has to host a number of email domains, so I need to provide features to receive email for multiple domains, for virtual users, and to control access. My .mc file looks like the one below, and is really a mish-mash of stuff I cut/paste from looking at other sendmail configs:

VERSIONID(`@(#)    1.00 (Potsticker Guru) 2008/05/30')
define(`confPRIVACY_FLAGS', `authwarnings,novrfy,noexpn,restrictqrun')dnl
define(`confSMTP_LOGIN_MSG',`$j Sendmail $v/$Z; $b; C=US ST=CA - NO UCE WANTED - NO UBE WANTED - NO SPAM WANTED')dnl
FEATURE(`dnsbl',`',`"550 Rejected because " $&{client_addr} " was blacklisted.  Please see"',`t')dnl
FEATURE(`dnsbl',`',`"550 Rejected because " $&{client_addr} " was blacklisted.  Please see"',`t')dnl


Note the use of DNS Blacklisting which relies on SORBS and SPAMHaus. These services are free to small/low-volume users, like my home system and they save a HUGE amount of spam. Without them, I would get about 2000+ spam emails per day, and probably just 10 legit emails. To generate the .cf file, I simply cd into /usr/lib/mail/cf/ and run:

    # make

The Makefile searches for a corresponding .mc file with the same prefix name and generates the .cf file. I then copy it over to /etc/mail and replace the regular with mine.

By default, the sendmail daemon in Solaris Nevada, since quite a few years ago, only allowed the MTA to connect to localhost. We want to open it up and so we need to configure Sendmail's SMF setting using:

    # svccfg -s sendmail setprop config/local_only=false

To activate the sendmail daemon for wide area network access, this particular configuration isn't like other SMF services. Restarting, or svcadm disable/enable, or even rebooting doesn't pick up the new configuration. You MUST run:

    # svcadm refresh sendmail; svcadm restart sendmail

I'm not sure why, but that seems to do the trick.

We're almost done, but not quite. The sendmail daemon requires that a bunch of files and binary database versions of those files exist in /etc/mail. With the above .mc configuration file, the daemon will expect to see:


The access, aliases, domaintable, mailertable and virtusertable .db files are all binary compiled from text files with name-value pairs of descriptors. The names of the files are /etc/mail/access, /etc/mail/aliases, /etc/mail/mailertable, /etc/mail/domaintable, /etc/mail/virtusertable and after hashing them into a binary format, each file is appended with the suffix ".db". You can learn more about the formats by going to and reading up on documentation. One is for access control, one is to define mail aliases, mail group aliases, one is to define domain translation rules, one is to define mail address rewriting rules, and the last is to define virtual user email addresses. Some features overlap like the virtusertable and the aliases file. To create the databases, I create text files without the .db suffix corresponding to each .db file. I have a lot of entries in access.db for anti-spam, and I manage quite a few aliases and virtual users. My local-host-names are many as well, one for each domain I host. But domaintable and mailertable are pretty much left null. But I found that I need them present because sendmail is checking for their presence to verify legitimacy of inbound emails destined for virtual users listed in the virtusertable for some reason. I don't understand why, but the email address translation directives in virtusertable are ignored when the inbound email address differs in final domainname of the recipient that is mapped in the virtusertable - but only when mailertable and domaintable .db files are NOT present. Sounds like I need to file a bug against the Berkeley sendmail daemon. Maybe later. But for now, just having them there, even empty files gets makes the virtusertable work, so I keep it there.

To generate the .db files, I created a simple Makefile, shamelessly copied from an old Linux distribution. Basically, it looks like:

    all:  virtusertable.db access.db domaintable.db mailertable.db

    %.db : %
        @makemap hash $@ < $<

        rm -f \*.db \*~

Put the Makefile into /etc/mail and run it each time you modify any of the above files. The aliases.db is created when the "newaliases" command is run, which is just a call sym-linked to the sendmail binary. Now you can svcadm restart sendmail and you should be able to have a working mail server.

Clearly, there are no guarantees that this will work for you. You need to make sure your mail server is properly configured as a DNS client on the network (i.e. it points to the right DNS and you've config'd /etc/nsswitch.conf and /etc/resolv.conf) is properly configured for your mail server and you have the right DNS MX records entries provided and hosted by your DNS registration provider.

If you've done everything right, you should be able to go to a free mail provider (e.g. Yahoo! or GMail) and send yourself some email. You should be able to watch the mail logs as the email comes in at /var/log/syslog. And if you do a ps -ef | grep sendmail, you should clearly see that the sendmail -bd -q15 has no trailing -C anymore.

If you plan to read/access your server through IMAP and or SquirrelMail, you can do an internet search for those packages and install them. may have all the packages pre-compiled for you as well. You may need to follow the directions also to generate PEM certificates for your IMAP server so it can run SSL. The command I use to create a self-signed PEM certificate is

# /usr/sfw/bin/openssl req -new -x509 -nodes -out imapd.pem -keyout imapd.pem -days 3650

This cert must be put at the destination: /usr/local/ssl/certs/imapd.pem.

One funny thing I encountered in IMAP server 2006e with SSL is that it claims that it doesn't work correctly with TCP wrappers on most UNIX/Linux distros. But I like running IMAP from the inetd because it kicks off the imapd server only when needed and is not present otherwise. So I had to attempt to see if it still worked, despite the warning. It's not so straightforward like the old days to configure the inetd daemon by editing the /etc/inetd.conf and restarting by pkill -HUP inetd. But I was able to everything working. First, I edited /etc/services and added 993 as a service port for imaps, then I added this line to the /etc/inetd.conf (legacy file - only active line):

imaps   stream  tcp     nowait  root    /usr/sbin/tcpd  /usr/local/sbin/imapd

and then ran the inetconv(1M) command which then puts this service into SMF and under the inetd process. A restart of the inetd daemon and everything just worked.


Post a Comment:
Comments are closed for this entry.



« July 2016