OpenSMTPD
Getting the right SMTP server to work together with IMAP via LMTP
Lietuviškai ✦ in English
Neapsikęsdamas internetinio pašto centralizavimo, įsigalėjusių monopolių įžūlumo, jų pačių brukamos vienkryptės spam taršos, abonentų muštravimo ir žeminimo, vienašališkų TOS priesaikų, perteklinio sudėtingumo vis to paties „saugumo“ dingstimi, prieš keletą metų išsikrausčiau paštą online.lt ir on.lt adresais iš „Gugelio“ į nuosavą dalykinių žinių talkos serverį.
Talkos abonentų paštui laikyti, tvarkyti, skaityti kompiuteriais ir telefonais įkurdinau pažangiausią, daugiausiai IMAP, JMAP, POP, NNTP ir kitų atvirų standartų besilaikantį, vikrų, skaidrų ir patvarų „dispečerį“ (dispatcher), pavadintą pirmojo istorijoje žinomo valstybinio pašto įkūrėjo persų karaliaus vardu „Cyrus“ (Kielius, Kyras, Xerxes, Ξερξης).
Naujiems laiškams priiminėti, persiuntinėti internete ir gautiems įteikinėti patikėjau „FreeBSD“ buvusiam „Sendmail“. Jis seniausias, nuo interneto aušros stropiai veikiantis, visavertis pašto SMTP serveris. Jį vadinu pensininku, nes išmestas iš savo tėviškės JAV Kalifornijos universiteto, kaip ir pats BSD. Neilgai gyvavęs kaip talkos bendrija Sendmail.org netrukus paversta įmone, kuri galop 2013 metais nupirkta numarinti. Pavienių gerbėjų prižiūrimas „Sendmail“ tebeveikia, bet reiktų susiruošti, kol ne vėlu. Kuo pakeisti? Senokai esu nusižiūrėjęs „OpenSMTPD“. Kodėl?
Netiesioginis, kone vaikiškas, nes ir be išmanymo lengvai išmatuojamas, bet patikimas kokybės rodiklis būna programinio kūrinio „svoris“. Tiksliau santykinis jo lengvumas, lieknumas, lyginant su kitais tapačios paskirties ir pajėgumo kūriniais — šis rodiklis dar niekada manęs nėra apgavęs. OpenSMTPD „sveria“ vos trečdalį megabaito (⅓ MiB) — palyginti su 1,3 MiB „Exim“ arba su 1,7 MiB populiariausiu iš atviro kodo SMTP serveriu „Postfix“ (be priedų). Nors „OpenSMTPD“ turi tokių kasdienei priežiūrai svarbių savybių, kurių kituose nėra. Be to, „OpenSMTPD“ yra švarus, vikrus, patvarus, nepainus, palyginti visai paprastas ir aiškus, lengvas įdiegti ir suderinti — užtenka vos kelių loginių smtpd.conf eilučių įprasta žmonių kalba.
Bet tokie geriausi kūriniai, kaip mano įdarbinti „BSD“, „Adminer“, „Hiawatha“, „Textpattern“, „Textile“ nėra populiarūs — nebūna su kuo pasitarti, tenka išsiaiškinti pačiam, vienumoje. „OpenSMTPD“ įdiegiau iškart, bet susigaudyti, pritaikyti ir suderinti buvo nelengva, teko pasikamuoti, nors dabar perpratus viskas tėra juokingai paprasta ir aišku. Todėl serverių tvarkybos meistrų prašymu prisėdau aprašyti angliškai, kuriose vietose kilo pagrįsti neaiškumai ir klaidos — kad būtų galima patikslinti aprašą, gal net pataisyti programinį kodą, kad ir kitiems netektų kamuotis ir net atsisakyti šio puikaus kūrinio.
OpenSMTPD is a quite fully-featured, though extremely lightweight and very high quality, robust open-source SMTP (MSA, MTA, MDA) server. Installation of OpenSMTPD 7.6 on my FreeBSD 14.3 was quick and flawless. I love in particular the syntax of the rules that corresponds to the living human language, similar to the syntax of the PF firewall. A few lines of smtpd.conf are all it takes to customise default needs.
Unfortunately, there is no example of LMTP in the manual — I need OpenSMTPD to deliver mail to Cyrus IMAP on the same host via LMTP Unix socket. In general, the most error-prone and time-consuming part of configuring and customising stem from uncertainty, from the lack of clarity in terms. I do not blame the manual — on the contrary, its conciseness is its strength. Alongside, however, some guide would be helpful. Most importantly, with examples. Because the human brain is not capable of purely theoretical reasoning without examples. In the absence of suitable examples, we have to imagine them, which can lead to mistakes.
- for local
- Specify that session may address any local domain.
states the smtpd.conf(5) manual.
Alas,
match from local !for local action "relay"
match from src <vip> !for local action "relay"
— wrong, should be:
match from local !for domain <domains> action "relay"
match from src <vip> !for domain <domains> action "relay"
(‹vip› there is an IP table of our virtual users, and ! means “not”).
:include: /path/name
The FreeBSD Manual: ALIASES(5)
:include:/path/to/file
The OpenBSD Manual: ALIASES(5)
OpenSMTPD is running on my FreeBSD, so I have to follow its manual. That space has been there since the beginning of the internet, and is still there now for Sendmail, for some other mailers. I would have thought that this space would be considered unnecessary — but not the other way around!
424 4.2.4 Mailing list expansion problem: <test@online.lt>
Unbelievable: a single space damaged the entire list of aliases!
Fortunately, after much trial and error I have finally overcome all the problems, OpenSMTPD together with Cyrus IMAP is working like a charm on FreeBSD now. Although I still do not know how to expand ‹aliases› before ‹virtuals› in OpenSMTPD, I have quite easily found a way to achieve that by two separate actions
with their own match
rules.
Here is my complete configuration file smtpd.conf to make it easier for others with a valid, working LMTP example:
pki "sala" cert "/home/vladas/.acme.sh/sala.online.lt/public.cert"
pki "sala" key "/home/vladas/.acme.sh/sala.online.lt/private.key"
filter "rspamd" proc-exec "/usr/local/libexec/opensmtpd/opensmtpd-filter-rspamd"
listen on all filter "rspamd" tls pki "sala"
table "domains" file:/etc/mail/local-host-names
table "users" file:/etc/mail/virtuals
table "groups" file:/etc/mail/aliases
table "vip" file:/etc/mail/vusers-ip
action "cyrus" lmtp "/var/cyrus/socket/lmtp" rcpt-to virtual <users>
action "circular" lmtp "/var/cyrus/socket/lmtp" alias <groups>
action "outbound" relay
match from src <vip> !for domain <domains> action "outbound"
match from local !for domain <domains> action "outbound"
match !from local !for domain <domains> reject
match from any for domain <domains> rcpt-to <users> action "cyrus"
# match from any for domain <domains> rcpt-to <groups> action "circular"
Thus I have listed all our email users@domain in the virtual table, and left the list of aliases for announcement circulars only. As mailing lists are very attractive to spammers, we can simply disable the last match
rule after discussing the current message — quite convenient, isn’t it?
The reject
rule seems redundant here, because that is the default. Defaults are also from local
and for local
, they can be omitted, although it might make rules a bit clearer to read and understand. The match
rules are evaluated sequentially, with the first match winning. If an envelope does not match any options, it is rejected. However, that is already laid out well in the manual, so there is no need to reiterate it here. Cheers!
