Cygwin, exim & a pop3 server
Latest update:
What I wanted is local mail on a lan. To make this interesting I also
wanted to do it under Windows, but w/o using any Windows-specific mail
software. Why?
A man can't just sit around.
-- Larry Walters
Turns out, you can't even compile cyrus-imap, courier imap or dovecot
under Windows. This leaves us w/ an unmaintainable port of uw-imap & a
curious package called mailutils.
The latter is so bizarre that I almost gave up on trying to setup its
pop3d server. Considering the fact that my debug skills under Windows
are wanting, I compiled it under Fedora & wasted a couple hours
running it under strace(1) & reading its source code. (I think it
would have been more interesting just to write a fresh pop3 server
instead.)
The final setup includes a single Windows box with:
- a dns server: unbound, that has a native Windows binary;
- an smtp server: exim, that routes mail inside lan, but employs a
smart host for non-lan domains; most mail accounts are virtual; the
storage format is mbox, for it's simple & 'performance' quirks are
tangential for a small network;
- a pop3 server: mailutils' pop3d that uses 'virtual domains' feature
for auth.
DNS
I had 0 problems w/ unbound, hence I won't talk about it. Just run
unbound_setup_x.y.z.exe
, then edit its config. E.g.:
$ cat /cygdrive/c/Program\ Files/Unbound/service.conf
server:
verbosity: 0
use-syslog: yes
# we need this, for by default it listens/grants_access on
# localhost only
access-control: 192.168.0.0/16 allow
interface: 0.0.0.0
# this should be the default, but it's not
private-address: 192.168.0.0/16
private-address: 172.16.0.0/12
private-address: 10.0.0.0/8
private-address: 169.254.0.0/16
private-address: fd00::/8
private-address: fe80::/10
private-domain: "lan"
local-zone: "lan." static
local-data: "castle.lan. IN A 192.168.111.1"
local-data-ptr: "192.168.111.1 castle.lan"
# ...
forward-zone:
name: "."
forward-addr: 1.1.1.1
forward-addr: 1.0.0.1
remote-control:
# If you want to use unbound-control.exe from the command line, use
control-enable: yes
control-interface: 127.0.0.1
control-use-cert: no
The installation should have created a Windows service.
You can't setup mail servers w/o working dns. Don't proceed further,
unless you can resolve my-server.lan
from client machines.
Exim
# exim-config
When asked 'Enter the value of CYGWIN for the daemon', I typed
ntsec
.
If you're like me, who have never configured Exim before, read at
least first 4 chapters of an excellent The Exim SMTP mail server
book.
Because some hosts in the lan have its own smtp servers running, this
route
# a perfectly conventional DNS routing operation,
# but only for the domains that match *.lan
my_local_network:
driver = dnslookup
transport = remote_smtp
domains = ! +local_domains : *.lan
no_more
sends emails straight to them, when a email have an address of
bob@castle.lan
form.
I won't paste here anything about a smart host--the default config
covers that already. What it lacks is support for virtual users. The
idea is: we search for a virtual user name in
/etc/exim.users.$domain
text file. The route that does this must
come before any other route that has check_local_user
option:
my_virtual_local:
driver = accept
domains = +local_domains
local_parts = lsearch;/etc/exim.users.$domain
transport = my_virtual_mbox
The corresponding transport is almost a copy of local_delivery
:
my_virtual_mbox:
driver = appendfile
file = /var/spool/mail-virtual/$local_part/INBOX
delivery_date_add
envelope_to_add
return_path_add
# group = mail
initgroups = no
# modes are wide open to allow unprivileged direct delivery
directory_mode = 01777
lockfile_mode = 0666
mode = 0666
mode_fail_narrower = no
check_group = no
check_owner = no
You don't need to create any directories yourself--Exim does it on the
fly.
Mailutils
This mysterious package has 1 of the most grotesque documentation I've
ever encountered. It contains thorough, elaborate descriptions of its
configurable parameters, multiple little, tiny configuration chunks,
scattered through the manual, but not a single, complete example of a
working config file. The only example I managed to locate was a Tcl
script (in the repo) that generated a partial config for a test
suite. (It was very helpful.)
I failed to find a single tutorial/article/comment that describes how
to setup pop3d/imap4d daemons--there is absolutely nothing, as if 'a
swiss army knife of electronic mail handling' was announced a mere
week ago.
Mailutils is > 20 years old. It had multiple maintainers through its
life, it has a GNU-branded website, an active maintainer, several of
established disros (Debian, Arch) have it in their repos (IBM
Fedora doesn't). It even had 7 CVEs in the distant past. Why there
is no 'community' of any kind, except for bug-mailutils mailing
list? What went wrong?
Anyway, by default pop3d produces very scarce error output & there is
no 'be verbose' option, hence, before doing anything, create
/etc/mailutils.conf
file w/ 1 line:
include /etc/mailutils/debug.conf;
that included file doesn't exist obviously--you need to populate it
with the following pretty nonsense:
debug {
level auth.trace9;
level address.trace9;
level attribute.trace9;
level auth.trace9;
level body.trace9;
level config.trace9;
level envelope.trace9;
level filter.trace9;
level folder.trace9;
level header.trace9;
level iterator.trace9;
level list.trace9;
level locker.trace9;
level mailbox.trace9;
level mailer.trace9;
level message.trace9;
level mime.trace9;
level mailcap.trace9;
level property.trace9;
level remote.trace9;
level stream.trace9;
level ticket.trace9;
level url.trace9;
level wicket.trace9;
level assoc.trace9;
level acl.trace9;
level server.trace9;
level tls.trace9;
level app.trace9;
}
Next, create mail
group in Windows. The name is hardcoded in pop3d
sources, & it won't start w/o it in the daemon mode.
Then you need to decide how pop3d will authenticate+authorize
users. Under Linux you may do nothing: if all pop3 users have real
accounts on a machine, then pop3d should auth successfully. Under
Cygwin this assumption fails, for modern Cygwin doesn't have
/etc/passwd
, if you create /etc/passwd
it won't contain hashed
passwords, & if you manually make a proper /etc/shadow
, this won't
work either, for mailutils has bugs.
pop3d has a notion of 'virtual mail domains': it can read a
passwd-like file, where a home directory field is not a home
directory, but a directory with (again) a hardcoded INBOX
file. This
is the file that our my_virtual_mbox
transport in Exim appends to.
To make the passwd-like file, run:
# cd /etc/mailutils
# mkpasswd -bl > castle.lan.template
edit out irrelevant accounts, add any number of virtual users, replace
each 2nd field with a real password, then run:
$ cat castle.lan.template | awk 'BEGIN { FS=OFS=":" } { "openssl passwd -6 " $2 | getline $2; print}' > castle.lan
It produces something like:
# cat /etc/mailutils/castle.lan
alex:$6$0bATz46nrnNO/O1x$CHU...:197610:197121::/home/alex:
luddite:$6$KVmsoeOgRnTIjXZx$wlz...:999:999::/var/spool/mail-virtual/luddite:
Here, alex
is a real Windows account, luddite
is not (its uid/gid
are fake, which doesn't matter). alex
account also has a real home
directory under Cygwin, thus to satisfy mailutils, it's necessary to
do ln -s /var/spool/mail/alex /home/alex/INBOX
.
Add to /etc/mailutils.conf
:
virtdomain {
passwd-dir /etc/mailutils;
}
program pop3d {
mode daemon;
foreground true;
}
server 0.0.0.0 {
acl {
allow 127.0.0.1;
allow 192.168.0.0/16;
deny any;
}
}
logging {
syslog no;
session-id yes;
}
# mbox
mandatory-locking {
lock-directory /tmp;
}
The mandatory-locking
'statement' is undocumented (of course!). It
hints pop3d where to create lock files for mboxes. By default it tries
somewhere in /var/spool
, miscarries miserably & collapses.
Now, under an administrator account, type:
# /usr/sbin/pop3d -d1 --foreground
then, under a usual user account in another terminal:
$ nc 127.0.0.1 110
+OK POP3 Ready <50944.1584657081@castle.lan>
user luddite@castle.lan
+OK
pass 12345
+OK opened mailbox for luddite
^D
Pop! goes the weasel. (sorry)
Pay attention to an argument of the user command. It includes a
domain name that is equal to the file name in /etc/mailutils
dir. When you omit the domain portion, pop3d tries to parse
/etc/passwd
& /etc/shadow
files, connect to radius, ldap, whatnot
enterprise solution. The process is configurable through auth
statement that I have no desire to discuss today.
Optionally, if you want support for a so called apop command in pop3
sessions (I didn't bother), there's popauth
util. It makes a dbm
file (the path /etc/apop.db
is hardcoded in pop3d/pop3d.h
, imagine
that) with name/password pairs:
# printf "bob@castle.lan 12345\nalice@castle.lan 67890\n" | popauth -c
# popauth -l
alice@castle.lan 67890
bob@castle.lan 12345
The last thing left is to make a windows service:
# cygrunsrv -I pop3d -p /usr/sbin/pop3d -y tcpip
and start it:
# net start pop3d
Tags: ойті
Authors: ag