Sakai and Sendmail

Problem

We don't want Sakai's Tomcat running as root, and therefore it cannot start up bound to port 25. Instead, it binds 8025 for SMTP. We somehow need to relay mail to this port.

Solution #1 (Spring 2005-today)

Configure xinetd to listen on port 25 and relay TCP traffic directly to 8025. /etc/xinetd.d/smtp:

service smtp
{
        disable         = no
        socket_type     = stream
        protocol        = tcp
        user            = nobody
        wait            = no
        redirect        = 127.0.0.1 8025
}

This worked well when we accepted mail on only one Sakai server. However, the higher-ups expressed a desire to build some redundancy into the system. It seemed easy enough to do, so we started up James on another couple of our clustered servers and configured an MX record with priorities:

classesv2.yale.edu      mail exchanger = 10 munson.its.yale.edu.
classesv2.yale.edu      mail exchanger = 20 mr1.its.yale.edu.
classesv2.yale.edu      mail exchanger = 20 mr2.its.yale.edu.
classesv2.yale.edu      mail exchanger = 20 mr3.its.yale.edu.
classesv2.yale.edu      mail exchanger = 20 mr4.its.yale.edu.
classesv2.yale.edu      mail exchanger = 20 mr5.its.yale.edu.
classesv2.yale.edu      mail exchanger = 20 mr6.its.yale.edu.
classesv2.yale.edu      mail exchanger = 5 scooter.its.yale.edu.
classesv2.yale.edu      mail exchanger = 8 maris.its.yale.edu.

munson, scooter, and maris are firewalled, so the mr1-6 machines, Yale's mail relays, relay the mail through the firewall. Let's trace the path a message should take in this configuration.

foo.com wants to deliver a message to foo@classesv2.yale.edu. Its MTA looks up the MX record and tries to deliver to the highest priority (lowest number) mail exchanger, scooter. Since it's firewalled, it can't connect directly to scooter, so it then walks up the list to maris, munson, and then one of the 6 equal-priority mail relays. Assume mr3.its.yale.edu receives the message.

mr3 does the same thing as foo.com's MTA. Starting at the highest priority mail exchanger, it attempts delivery. If all is running well, delivery will succeed to scooter. xinetd listening on port 25 will accept the connection and forward the traffic to 8025. Message delivered.

Let's say that scooter's xinetd is down, so port 25 is not listening. In that case, mr3 would attempt to deliver to scooter:25, but the connection would be refused. It would then have proceeded to maris, where xinetd there would forward 25 to 8025, and the message would be delivered.

Here's the problem with this method. As long as xinetd is up, it's listening and accepting connections to port 25. Even if 8025 is not listening, xinetd will still accept the connection. After accepting the connection to 25, it tries to open a connection to localhost:8025, which fails. What do you do now with the connection you just accepted from mr3? The only thing you can do – drop the connection.

This confuses mr3's Sendmail. Rather than write it off as a bad connection and try the next exchanger, it queues the mail for delivery later. (I'm fairly sure this is what's happening. Someone please correct me if I'm wrong.)

Solution #2 (soon-the future)

Use Sendmail to relay mail from 25 to 8025. This takes two steps. The first is to create a new mailer (almost) identical to the esmtp mailer that delivers to port 8025. The second is to create a mailertable that uses this mailer for the classesv2.yale.edu domain (but not others).

I say "almost" identical to the esmtp mailer because the F= option has a new flag added to it (k) that makes sendmail not complain about mail loops. After all, you're accepting mail on a machine (on port 25) and potentially relaying it to the same machine (but on port 8025). Sounds like a loop to Sendmail!

The following was added to sendmail.mc. More details about this can be found at http://bug.sakaiproject.org/confluence/display/ENC/Sendmail+integration.

FEATURE(`mailertable',`hash -o /etc/mail/mailertable.db')dnl
MAILER_DEFINITIONS
Mesmtpjames,    P=[IPC], F=mDFMuXak, S=EnvFromSMTP/HdrFromSMTP,R=EnvToSMTP, E=\r\n, L=990,
                T=DNS/RFC822/SMTP,
                A=TCP $h 8025

A mailertable file was created with:

classesv2.yale.edu      esmtpjames:classesv2.yale.edu

After building sendmail.cf and mailertable.db, Sendmail was restarted. Now with Sendmail listening on port 25, the relaying to port 8025 is smarter. If Tomcat isn't running on scooter, Sendmail will try to connect to the next highest priority server, maris, on port 8025. If Sendmail isn't running on scooter, the lower priority mail relays (mr1-6) will try maris next.

Labels

 
(None)