1 |
slords |
1.1 |
******************** |
2 |
|
|
*** INTRODUCTION *** |
3 |
|
|
******************** |
4 |
|
|
|
5 |
|
|
STARTTLS is the standard (RFC 2487) way of doing SMTP encrypted with |
6 |
|
|
SSL/TLS. Although it does not provide end-to-end encryption of email |
7 |
|
|
messages, it can be useful to protect the passwords of an AUTH PLAIN |
8 |
|
|
login, and possibly to protect mail which will travel a very specific |
9 |
|
|
route known in advance. |
10 |
|
|
|
11 |
|
|
qmail-smtpd doesn't have native support for STARTTLS. Many people run |
12 |
|
|
qmail for it's extremely good security record, and are reluctant to |
13 |
|
|
have the security of their mail system depend on the many thousands of |
14 |
|
|
lines of code in openssl. One way to avoid this is to run a proxy |
15 |
|
|
which can handle the encryption and the STARTTLS command itself, and |
16 |
|
|
then have it hand off to the standard qmail-smtpd. Even better is if |
17 |
|
|
the proxy can run in an environment secured by chroot(), setuid(), and |
18 |
|
|
setgid(). |
19 |
|
|
|
20 |
|
|
That's the approach that this document describes, with stunnel acting |
21 |
|
|
as the proxy. Basic SMTP/STARTTLS proxy support is already included |
22 |
|
|
in stunnel, and that support has been extended to do a plaintext proxy |
23 |
|
|
of the SMTP session if STARTTLS isn't used. stunnel runs chrooted in |
24 |
|
|
its own directory, as a special user and group. This means that even |
25 |
|
|
a grievous security error in stunnel or openssl wouldn't allow |
26 |
|
|
significant access to your system, or even allow interfering with |
27 |
|
|
mail. |
28 |
|
|
|
29 |
|
|
|
30 |
|
|
******************** |
31 |
|
|
*** INSTRUCTIONS *** |
32 |
|
|
******************** |
33 |
|
|
|
34 |
|
|
WARNING: These are not for the faint-hearted. They are confusing and |
35 |
|
|
may not work for you. This is still experimental; if you get stuck, |
36 |
|
|
email me at <sgifford@suspectclass.com>. |
37 |
|
|
|
38 |
|
|
1. Download stunnel-3.22. Apply the patch "stunnel3.22-sg2.patch". |
39 |
|
|
Compile and install it somewhere. This patch improves the SMTP |
40 |
|
|
proxy support, adds options to tell it to communicate via an |
41 |
|
|
already opened file descriptor, adds chroot() support, and improves |
42 |
|
|
setuid/setgid support; see: |
43 |
|
|
|
44 |
|
|
http://www.suspectclass.com/~sgifford/qmail-smtp-tls-proxy/stunnel3.22-sg2.README |
45 |
|
|
|
46 |
|
|
for a full description of the patch. |
47 |
|
|
|
48 |
|
|
2. Compile and install "makesock.c". |
49 |
|
|
|
50 |
|
|
3. Create your service directory for smtp-tls |
51 |
|
|
|
52 |
|
|
4. Set up a log directory for smtp-tls. |
53 |
|
|
|
54 |
|
|
5. Create a user called "stunnel" with a primary group of "stunnel". |
55 |
|
|
|
56 |
|
|
6. Create a directory in your service directory called "ssl". |
57 |
|
|
|
58 |
|
|
6a. Copy in your certificate as "stunnel.pem" |
59 |
|
|
|
60 |
|
|
6b. Copy in your SSL configuration as openssl.cnf |
61 |
|
|
|
62 |
|
|
6c. Create a seed file with "dd if=/dev/random of=seed count=10k" |
63 |
|
|
or something. |
64 |
|
|
|
65 |
|
|
6d/1. Some copies of OpenSSL will require you to create a fake |
66 |
|
|
'usr/share/ssl' directory, to placate openssl in chroot. |
67 |
|
|
Something like: |
68 |
|
|
|
69 |
|
|
mkdir -p usr/share/ssl |
70 |
|
|
|
71 |
|
|
. If your ssl expects to find its configuration elsewhere, |
72 |
|
|
make that directory instead. |
73 |
|
|
|
74 |
|
|
6d/2. If your copy of OpenSSL requires it, make a symlink to |
75 |
|
|
openssl.cnf from the fake config dir. Something like: |
76 |
|
|
|
77 |
|
|
ln -s ../../../openssl.cnf usr/share/ssl/ |
78 |
|
|
|
79 |
|
|
should do the trick, if your openssl expects its config file in |
80 |
|
|
/usr/share/ssl normally. |
81 |
|
|
|
82 |
|
|
6e. Set group-ownership of the ssl directory to "stunnel" (leaving |
83 |
|
|
user-ownership at "root") and permissions to "owner read-write, |
84 |
|
|
group read, other none" on everything in the ssl directory: |
85 |
|
|
|
86 |
|
|
chgrp -R stunnel ssl |
87 |
|
|
chmod -R u=rwX,g=rX,o= ssl |
88 |
|
|
|
89 |
|
|
7. Install the run file "smtp-tls-run" as "run" in your service |
90 |
|
|
directory. Make sure it's executable. If you've installed the |
91 |
|
|
modified stunnel somewhere other than /usr/local/bin, add that to |
92 |
|
|
the PATH near the top. |
93 |
|
|
|
94 |
|
|
8. Run the "run" file in the service directory, and find and fix any |
95 |
|
|
errors. |
96 |
|
|
|
97 |
|
|
9. Active the service, perhaps by symlinking it into /service. |
98 |
|
|
|
99 |
|
|
|
100 |
|
|
|
101 |
|
|
******************* |
102 |
|
|
*** EXPLANATION *** |
103 |
|
|
******************* |
104 |
|
|
|
105 |
|
|
Here's what the run script does. It expects everything it runs to be |
106 |
|
|
in your PATH. |
107 |
|
|
|
108 |
|
|
First, it gathers up some information from control files and from the |
109 |
|
|
system user and group database, and gets some hardcoded configuration |
110 |
|
|
information. |
111 |
|
|
|
112 |
|
|
softlimit limits the memory usage for each process to 5 MB. |
113 |
|
|
|
114 |
|
|
tcpserver listens on the SMTP port. We continue running as root from |
115 |
|
|
here (so we can do chroot() and set[ug]id() later), and when we get a |
116 |
|
|
connection we run... |
117 |
|
|
|
118 |
|
|
...makesock. This is a small C program that creates a socket with |
119 |
|
|
socketpair(), and provides one end of that socket on file descriptor 3 |
120 |
|
|
to the first program it's asked to run, and the other end on standard |
121 |
|
|
input and output to the second program it's asked to run. The first |
122 |
|
|
and second programs are separated by the command line option |
123 |
|
|
"-makesock_connect_to". |
124 |
|
|
|
125 |
|
|
The first program, the STARTTLS proxy, is stunnel. Debugging is |
126 |
|
|
turned on, since this is still experimental. "-/ ssl" (an option |
127 |
|
|
added by my patch) asks it to chroot to the "ssl" directory. "-s |
128 |
|
|
$SSLUID" asks it to change to the stunnel user. "-g $SSLGID" asks it |
129 |
|
|
to change to the stunnel group. "-i" (an option added by my patch) |
130 |
|
|
asks it to switch users immediately, instead of after binding to the |
131 |
|
|
local port for listening (which we don't ask stunnel to do, since |
132 |
|
|
tcpserver has done it for us). "-R seed" tells it to get the seed for |
133 |
|
|
the random number generator from the file "seed". "-p stunnel.pem" |
134 |
|
|
tells it to use the certificate in "stunnel.pem". "-n" smtp-" tells |
135 |
|
|
it to act as an SMTP proxy, and to act as a plaintext proxy if TLS |
136 |
|
|
isn't negotiated. "-f" asks it to stay in the foreground and write |
137 |
|
|
its errors to stderr, perfect for running under supervise! "-F 3" (an |
138 |
|
|
option added by my patch) asks it to connect to file descriptor 3 (set |
139 |
|
|
up by makesock) as the plaintext end of the proxy. |
140 |
|
|
|
141 |
|
|
The second program is the SMTP server. We first have to change to a |
142 |
|
|
safer UID than root; in most installations, tcpserver would to this |
143 |
|
|
for us, but we couldn't do that here (because we needed the ability to |
144 |
|
|
chroot() and setuid()/setgid() to a different user/group in stunnel), |
145 |
|
|
so "setuidgid" changes to the "qmaild" user and their primary group. |
146 |
|
|
stunnel doesn't seem to be very good about passing along CR/LF's |
147 |
|
|
properly, and rather than fixing that right now, I just threw in |
148 |
|
|
"fixcrio" to take care of it. Finally, the real qmail-smtpd is run. |
149 |
|
|
|
150 |
|
|
************* |
151 |
|
|
*** NOTES *** |
152 |
|
|
************* |
153 |
|
|
|
154 |
|
|
It is tempting to run this proxy as a simple TCP proxy, but that makes |
155 |
|
|
authorizing relays by IP address hard. |
156 |
|
|
|
157 |
|
|
|
158 |
|
|
************ |
159 |
|
|
*** BUGS *** |
160 |
|
|
************ |
161 |
|
|
|
162 |
|
|
* RFC 2487 requires that we restart the SMTP session completely after |
163 |
|
|
STARTTLS, in particular throwing away the EHLO information we have. |
164 |
|
|
We don't do that, because: this architecture makes it hard, qmail |
165 |
|
|
doesn't mind if it gets multiple ehlo commands, and qmail doesn't |
166 |
|
|
really do much with the ehlo argument anyways. |
167 |
|
|
|
168 |
|
|
* STARTTLS is only supported if the first command we get is an EHLO, |
169 |
|
|
and the second is STARTTLS. |
170 |
|
|
|
171 |
|
|
* makesock.c is a single-purpose ugly hack. It should take more |
172 |
|
|
command-line options, to make it a flexible tool. |
173 |
|
|
|
174 |
|
|
* There's no way for the SMTP server to know whether TLS was |
175 |
|
|
negotiated. This could be useful to, for example, only offer AUTH |
176 |
|
|
PLAIN authentication after STARTTLS. |