From 714d9219a448e847803d9256bf2b6a9516690bf7 Mon Sep 17 00:00:00 2001 From: Malfurious Date: Fri, 2 Aug 2024 16:39:50 -0400 Subject: Add README Signed-off-by: Malfurious --- README | 333 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 333 insertions(+) create mode 100644 README diff --git a/README b/README new file mode 100644 index 0000000..54c7c56 --- /dev/null +++ b/README @@ -0,0 +1,333 @@ + _____________________________ + / ____ / / / + / .' __ \ /__./ / + / / .' \ | ________ / + / | | (_/ | ________ /_____ _____ ____ __ _____ _____ ____ _____ + / \ `.__.'\ ________ /| | _ | | | | | | | \| __| + / `.___ .' _____ / | | | | |- -| |__| | | | | | | | __| +/____________________________/ |_|_|_|__|__|____|_____|_|___|_____|____/|_____| + +Mailnode is a dockerized email service that supports virtual inboxes, virtual +mail domains, address aliases, a mailing list service, and is compatible with +the DNS-based message authentication schemes SPF, DKIM, and DMARC. + +Mailnode runs solely on well-established free software components. Mailnode's +daemons and required default port numbers are listed below. Due to the +prevalence of email spam, it is important to ensure that email ports are not +blocked or filtered by your hosting provider / ISP. + + Service Description TCP ports + ------------------------------------------------------------- + postfix Mail transfer agent 25, 465 + dovecot Mail delivery agent 993 + mlmmj Mailing list manager - + opendkim Message auth mail filter - + nginx-proxy (*) Reverse proxy / TLS helper 80, 443 + +* Nginx-proxy (with acme-companion) is an extra dependency which is required to +obtain and manage TLS certificates for the mail server. The proxy service is +used so that mailnode doesn't require exclusive control over the web ports. +docker-compose.yml contains the integrations with nginx-proxy. + + + +Prerequisites +============= + 1) Forward DNS host record(s) for mail server: Create an A record and/or + AAAA record pointed at the mail server IP address. + + 2) Reverse DNS record(s): Create PTR records for the server's IPv4 and, if + necessary, IPv6 addresses. You may need to ask your hosting provider to + do this for you. + + 3) Unblock your ports: If any of the above TCP ports are blocked (either + inbound or outbound) by your upstream provider, submit a support ticket + to have them opened. Otherwise, seek another service provider. + Mailnode makes no official recommendation regarding ISP or hosting + providers. + + 4) Run nginx-proxy: Clone docker compose files from the "proxy-docker" git + repository and launch the reverse-proxy with ACME companion service. + `docker compose --file ./docker-compose-acme.yml up --detach` + + + +Configuration +============= + docker-compose.yml + ------------------ + There are a couple variables in this file that must be filled in with + information about your server. Eg: the server hostname and a list of valid + "local" mail domains. Look for comments that say "# CONFIGURE ME!" + + Virtual domains must be comma separated. An example value for this field + might be: "foo.com,baz.bar.net" in order to accept mail for addresses like + "user@foo.com" and "user@baz.bar.net" respectively. + + + userconfig/passwd + ----------------- + This is the master user/inbox database for the Mailnode instance. It is in + the format of a standard system passwd file - fields are separated by colons, + and comments and blank lines are not allowed. The format for each line of + this file is: + + USERNAME:PASSWORDHASH:UID:GID:::: + + Username must be the user's full email address. This is because Mailnode + supports multiple receiving domains. + + A Password hash can be generated using the `makepasswd.sh` script. Hashes + are given a unique salt. Therefore, even if two users will use the same + password, it is wise to assign them independent hashes. This way, someone + reading the passwd file will be unable to determine which passwords match, + if any. + + UID and GID refer to the underlying unix account which actually owns the + stored mail files. These must be the constant value `2000`. The final few + fields are not used at the moment. + + The default file contains a dummy user record to show an example, this line + should be removed when adding real users. + + + userconfig/aliases + ------------------ + This file defines email address alias lists. Each line contains the name of + an alias, followed by one or more addresses that the alias will forward to. + Forwarding addresses can be of different domains than the alias address. + They can even reside at domains not managed by the Mailnode instance. + + Unlike the passwd file, blank lines and comment lines (`#`) are allowed. + + This example forwards both "webmaster" and "postmaster" addresses to a + generic "admin" address, and delivers all mail to admin to two real human + beings: + + webmaster@site.com admin@site.com + postmaster@site.com admin@site.com + admin@site.com alice@site.com bob@site.com + + + +Installation +============ +After making modifications to the config files, use docker compose to start +Mailnode or update an existing instance. When building and starting Mailnode +for the first time, it is recommended to direct output to a log file so you can +easily grab the DKIM key that is generated for your server. This public key +will be needed for a DNS record later. + + docker compose up --detach --build | tee log.txt + +The DKIM key generated by the build process is persisted by a named volume. +This allows the image to be rebuilt without requiring the need to rotate keys. + + + +Final DNS Records +================= +After setting up Mailnode, some additional DNS entries are required in order to +properly federate with other mail servers. Add them to your domain's zone file. +(domain.com => your domain name, mail.domain.com => mail server hostname) + + domain.com MX 10 mail.domain.com + domain.com TXT "v=spf1 mx -all" + default._domainkey.domain.com TXT "v=DKIM1; h=sha256; k=rsa; p=MIGfMA0GCSqGSIb3D....." + _dmarc.domain.com TXT "v=DMARC1; p=none; rua=mailto:postmaster@domain.com" + + + MX (Mail exchange) + ------------------ + This is a standard DNS record that instructs external senders which server(s) + to direct your incoming mail to. The given record directs all mail to + `mail.domain.com:25`. 10 is a priority value, which is meaningful if + multiple MX entries are present. + + The remaining records pertain to message sender authentication and apply to + your outgoing mail. + + + SPF (Sender policy framework) + ----------------------------- + An SPF record states which internet hosts are permitted to send mail on + behalf of your domain. The given record permits all your domain's mail + exchangers (aka: any host referred to by an MX record) and hard-fails all + others. For more information on SPF records, see: + http://www.open-spf.org/SPF_Record_Syntax/ + + + DKIM (DomainKeys identified mail) + --------------------------------- + DKIM uses asymmetric cryptography to sign outgoing mail, proving that each + message originates from one of your domain's approved mail servers. DKIM + signatures include a key selector field - this enables you to publish many + public keys in your domain. Mailnode uses only a single key pair, with the + selector name "default". Key selectors are part of the DNS entry name, as + seen above. The body of the TXT record contains all the crypto parameters + for the public key. + + To find your DKIM record value, refer to the output of the docker image + build log. After opendkim generated an initial key pair, the data for the + public key DNS record is echoed to the console. + + + DMARC (Domain-based message authentication, reporting, and conformance) + ----------------------------------------------------------------------- + DMARC instructs a message receiver what to do if a message from your domain + fails either of the SPF or DKIM checks. Note that implementing DMARC may be + optional for your site. + + The given record specifies a policy of "none", which effectively allows the + delivery of unauthenticated messages. Alternatives are "quarantine" (spam + folder) and "reject" (return error code during SMTP). The "rua" tag + specifies an email address to deliver aggregate DMARC reports to. If your + "postmaster" mailbox is not setup, change this value or remove the tag. + + For more information on DMARC records, see: + https://mxtoolbox.com/dmarc/details/what-is-a-dmarc-record + + + +Login to Mailboxes +================== +Connect to Mailnode with any normal email client using the information below. + + Incoming mail + ------------- + Server: + Protocol: IMAPS (Implicit SSL/TLS encryption, not STARTTLS) port 993 + Username: + Password: + + + Outgoing mail + ------------- + Server: + Protocol: SMTPS (Implicit SSL/TLS encryption, not STARTTLS) port 465 + Username: + Password: + +Note that new accounts initially only have an INBOX folder where new messages +are delivered. Message archival, saving sent messages, or message drafts must +be handled by clients. + +The "From:" header used in outgoing messages is managed by clients - users +configure their "real names" locally instead of on the server. However the +return path ("envelope sender", etc) must match the user's email address, +otherwise the message will be rejected. + + + +Mailing Lists +============= +Mailnode hosts configurable mailing lists using the Mlmmj mailing list manager. +Basic usage is explained here, although it is a good idea to familiarize +yourself with the underlying system: https://mlmmj.org/ + +Mlmmj uses a directory for each mailing list to record its configuration and +metadata. This includes things like the message archive, list of subscribers, +message queues, and configuration parameters. In particular, there are two +subdirectories of interest: (1) "control", which contains list configuration +options and (2) "text", which contains message templates to use when delivering +automated responses to users. + +Under Mailnode, each list's main metadata directory is managed for you. You +Only need to manually configure "control" and "text" content in directories +under `userconfig/`. + + userconfig/lists//* + ------------------------- + Create subdirectories under `userconfig/lists/` for each of your desired + mailing lists. The directory name is used to identify the list, and the + directory contents are the files which would reside in the list's "control" + (configuration options) directory. + + The `makelist.sh` script can be used to automatically create a mailing list + using some recommended sane default settings. Keep in mind that the list's + post address will really be the only user-facing identifier for the list. + The owner email address will be used as the initial list owner and moderator. + Emails sent to `listname+owner@domain.com` will be delivered to this person. + + For a fuller description of the available configuration settings, see the + Mlmmj documentation: https://mlmmj.org/TUNABLES.html + + Be careful when removing a list directory! Whenever Mailnode is restarted + (rebuilt) after removing lists, the list's real metadata directory will be + purged from the system. This includes all subscribers and the full message + archive as well! + + + userconfig/listtext/* + --------------------- + This directory contains the "text" auto mail templates that are shared by + all configured mailing lists. You shouldn't need to change anything, but if + you wish to customize any messages, this is the place to do it. + +After creating lists, rebuild and restart Mailnode. The mailing lists are +interacted with by sending an email to one of several "request" email addresses. +Assuming a mailing list whose post address is "mylist@domain.com", the following +basic actions are possible: + + mylist@domain.com Deliver message to all list subscribers + mylist+owner@domain.com Deliver message to the list owner(s) + mylist+help@domain.com Retrieve a summary of list information + mylist+subscribe@domain.com Subscribe to receive all list messages (*) + mylist+subscribe-digest@domain.com Subscribe to receive list digests (*) + mylist+unsubscribe@domain.com Unsubscribe from all list messages (*) + +For all "request" addresses ("mylist+xxx@domain.com"), the message subject and +body are ignored. + +* Subscribe and unsubscribe requests require reply to a confirmation message to +prevent abuse. + + + +Mailing List Archives +===================== +Some web frontends exist for Mlmmj to allow searching and browsing message +archives. However, I personally don't like any of the user interfaces available. + +At the moment, Mailnode does not expose any message archive interface. +Implementing one is left as a TODO for a future release. + + + +Testing and Troubleshooting +=========================== +For help validating your mail setup, check out these tools that will test your +DNS records, message signatures, and deliverability. + + https://intodns.com/ Validate domain DNS records + https://appmaildev.com/en/dkim Test SPF, DKIM, and DMARC via email + https://mxtoolbox.com/blacklists.aspx Check blacklists for server IP + https://mxtoolbox.com/SuperTool.aspx MXToolBox super tool + +Your mail server's IP address may appear on various block lists if it was +recently used to send email spam. Residential and many VPS IP blocks are also +sometimes listed. If you appear on a blocklist, you will likely have a very +hard time getting your mail accepted by major email providers such as Microsoft, +Google, and Yahoo, etc. Blacklist maintainers will usually provide a process +for getting your IP delisted. Initiate these procedures at your own discretion. + +In addition to the above tools, you can send mail to one of the auto-responders +below. A reply should be returned shortly containing your original message along +with all of the header changes that were made in transit. This will allow you +to test DKIM functionality along with two-way message deliverability. + + sa-test@sendmail.net + check-auth@verifier.port25.com + autorespond+dkim@dk.elandsys.com + dktest@exhalus.net + dkim-test@altn.com + dktest@blackops.org + +Look for the message headers "DKIM-Signature:" and "Authentication-Results:" to +have been added. Authentication results injected by the remote system should +indicate a PASS. Otherwise, there is a misconfiguration, or something along the +way altered the email to invalidate the signature. + +The auto-responder's reply mail will also be DKIM-signed. If you inspect the +reply's actual headers you should see authentication results injected by your +own server. This should also give a PASS. -- cgit v1.2.3