User Tools

Site Tools


computing:mailserver

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
computing:mailserver [2025/04/12 22:51] oemb1905computing:mailserver [2025/05/15 19:21] (current) oemb1905
Line 11: Line 11:
 ------------------------------------------- -------------------------------------------
  
-This tutorial is for users of Debian GNU/Linux who want to set up a proper email server.. This tutorial assumes you know how to set up A, AAAA, SPF, DKIM, DMARC, MX, and PTR records. Set an A record for example.org and mail.example.org. If you don't know how, then learn up, and do not proceed. //Thanks to LinuxBabe for a great jumping off point//. Let's begin by editing our hosts file ''sudo nano /etc/hosts'' as follows:+This tutorial is for users of Debian GNU/Linux who want to set up a proper email server.. This tutorial assumes you know how to set up A, AAAA, SPF, DKIM, DMARC, MX, and PTR records. Set an A record for example.org and mail.example.org and make sure you or your ISP has set a PTR record to mail.example.org for the IPv4 and IPv6 addresses. If you don't know how, then learn up, and do not proceed. //Thanks to LinuxBabe for a great jumping off point//. Let's begin by editing our hosts file ''sudo nano /etc/hosts'' as follows:
  
   127.0.1.1 example.org example   127.0.1.1 example.org example
Line 22: Line 22:
   sudo apt install ufw   sudo apt install ufw
   sudo ufw allow 22/tcp   sudo ufw allow 22/tcp
-  sudo ufw allow 53/tcp 
   sudo ufw allow 25/tcp   sudo ufw allow 25/tcp
   sudo ufw allow 587/tcp   sudo ufw allow 587/tcp
   sudo ufw allow 143/tcp   sudo ufw allow 143/tcp
 +  sudo ufw allow 465/tcp
   sudo ufw allow 993/tcp   sudo ufw allow 993/tcp
   sudo ufw allow 80   sudo ufw allow 80
Line 125: Line 125:
   <mail_location = maildir:~/Maildir>   <mail_location = maildir:~/Maildir>
  
-Let's make sure dovecot is part of the mail group with ''sudo adduser dovecot mail'' and now we can configure dovecot with ''sudo nano /etc/dovecot/conf.d/10-master.conf'' in order to be able to leverage lmtp:+Let's make sure dovecot is part of the mail group, including any users you intend to use email: 
 + 
 +  sudo adduser dovecot mail 
 +  sudo adduser username mail 
 +   
 +Now we can configure dovecot over at ''sudo nano /etc/dovecot/conf.d/10-master.conf'' in order to be able to leverage lmtp:
  
   service lmtp {   service lmtp {
Line 182: Line 187:
    reject_unauth_destination,    reject_unauth_destination,
    check_policy_service unix:private/policyd-spf    check_policy_service unix:private/policyd-spf
 +
 +You also need to make sure that your spf policy is not set to reject emails by default. 
 +
 +  nano /etc/postfix-policyd-spf-python/policyd-spf.conf
 +  
 +Make sure that ''Fail'' is changed to ''False'' for the top two entries. The policy will ensure that those spf violations are logged, but the change to False ensures no email is lost as a result. 
 +
 +  HELO_reject = False
 +  Mail_From_reject = False
  
 Now, it is time to set up DKIM on your server. After creating the DKIM record/key on your server, you will need to create a corresponding TXT record for it to establish that anything over smtp with that signature is, in fact, you/your server. Let's install opendkim with ''sudo apt install opendkim opendkim-tools'' and add postfix to its group with ''sudo adduser postfix opendkim'' and then adjust the configuration in ''sudo nano /etc/opendkim.conf'' as follows: Now, it is time to set up DKIM on your server. After creating the DKIM record/key on your server, you will need to create a corresponding TXT record for it to establish that anything over smtp with that signature is, in fact, you/your server. Let's install opendkim with ''sudo apt install opendkim opendkim-tools'' and add postfix to its group with ''sudo adduser postfix opendkim'' and then adjust the configuration in ''sudo nano /etc/opendkim.conf'' as follows:
Line 200: Line 214:
   sudo chmod 711 /etc/opendkim/keys   sudo chmod 711 /etc/opendkim/keys
      
-Once all the directories and key locations are created, let's open the signing table with ''sudo nano /etc/opendkim/signing.table'' and enter the following:+Once all the directories and key locations are created, let's open the signing table with ''sudo nano /etc/opendkim/signing.table'' and enter the following (without the single quotes required here due to markdown conflict):
  
-  *@example.com      default._domainkey.example.com +  '*@example.com      default._domainkey.example.com' 
-  *@*.example.com    default._domainkey.example.com+  '*@*.example.com    default._domainkey.example.com'
  
 Now that the signing table is setup, we need to edit the key table with ''sudo nano /etc/opendkim/key.table'' and enter the following: Now that the signing table is setup, we need to edit the key table with ''sudo nano /etc/opendkim/key.table'' and enter the following:
Line 211: Line 225:
 The trusted hosts is next, over in ''sudo nano /etc/opendkim/trusted.hosts'' which we simply enter: The trusted hosts is next, over in ''sudo nano /etc/opendkim/trusted.hosts'' which we simply enter:
  
 +  127.0.0.1
 +  localhost
   .domain.com   .domain.com
      
Line 249: Line 265:
   AuthservID OpenDMARC   AuthservID OpenDMARC
   TrustedAuthservIDs mail.yourdomain.com   TrustedAuthservIDs mail.yourdomain.com
-  RejectFailures true+  RejectFailures false #track only, do not stop at gate
   IgnoreAuthenticatedClients true   IgnoreAuthenticatedClients true
 +  RequireHeaders true
   SPFSelfValidate true   SPFSelfValidate true
   Socket local:/var/spool/postfix/opendmarc/opendmarc.sock   Socket local:/var/spool/postfix/opendmarc/opendmarc.sock
Line 354: Line 371:
   sudo sievec /var/mail/SpamToJunk.sieve   sudo sievec /var/mail/SpamToJunk.sieve
      
-RESUMEEEEEEEEE!!!!! +This rule does one thing. It checks whether spam assassin identified the message as spam, and if so, it uses dovecot to file it in Junk. This means your spam assassin scores and config are what drive the success rate of this sieve rule. It's also important to note that this rule is global, and impacts all user names on the mail server. It's a good approach for the most heinous spam, leaving more customized rules to roundcube's sieve implementation, later in this tutorial. Let's open ''sudo nano /etc/spamassassin/local.cf'' and adjust it as follows.
- +
-We can now configure some custom scores and white/black lists as needed so ''sudo nano /etc/spamassassin/local.cf''. I've included the default and explicit header lines as well, which can help with debugging. Specifically, SA will not give a score breakdown on ham unless those are specified.+
  
   report_contact webmaster@domain.com   report_contact webmaster@domain.com
-  required_score 5.0+  #adjust score below to your use-case 
 +  required_score 5.0 
   #rewrite_header Subject **Possible Spam**   #rewrite_header Subject **Possible Spam**
   report_safe 0   report_safe 0
-  always_add_headers = 1 +  add_header all Spam-Flag _YESNO_ 
-  #add_header all Flag _YESNO_ +  add_header all Score _SCORE_ 
-  #add_header all Status "_YESNO_, score=_SCORE_ required=_REQD_ tests=_TESTS_ autolearn=_AUTOLEARN_ version=_VERSION_" +  add_header all Report _REPORT_ 
-  #add_header all Report _REPORT_ +  add_header all Level _STARS_ 
-  #add_header all Level _STARS_ +  add_header all Status "_YESNO_, score=_SCORE_ required=_REQD_ tests=_TESTS_ autolearn=_AUTOLEARN_ version=_VERSION_" 
-  #add_header all Checker-Version "SpamAssassin _VERSION_ (_DATE_) on _HOSTNAME_"+  add_header all Checker-Version "SpamAssassin _VERSION_ (_DATE_) on _HOSTNAME_" 
 +  #legacy/deprecated header config - do not use, retained for historical record 
 +  #always_add_headers = 1
  
-Before we enter the custom scores and white and black listslet's install and enable unboundso that spam-assassin can query the RBLs. RBLs do not allow upstream DNS queriesthus we are required to run our own recursive resolver hereTake care not to expose this publicly. I prefer unbound, but one can also use bind9 or othersSpecify the DNS in the ''local.cf'' and create your rules/lists+I included some header optionswhich can help with debugging. Also, I disable safe reporting and Subject rewriting because they alter the original emailwhich I think is overkill. In order to activate all that spam assassin can do, we need to have our own recursive DNS resolver, required by RBL servicesLet's use the DNS server unbound and install it as follows ''sudo apt install unbound''. It works out of the box, but you can also tweak it by looking at my tutorial here: [[https://wiki.haacksnetworking.org/doku.php?id=computing:unbounddns|Unbound DNS]]. Okay, let's now insruct spamassassin to use our dns server by opening ''sudo nano /etc/spamassassin/local.cf'' and entering the DNS server. We will also add some common scores and white and black lists while at it.
  
-  sudo apt install unbound +  dns_server 127.0.0.1 
-  sudo nano /etc/spamassassin/local.cf +  score MISSING_FROM                      5.0 
-  <dns_server 127.0.0.1> +  score MISSING_DATE                      5.0 
-  <score MISSING_FROM                      5.0> +  score MISSING_HEADERS                   3.0 
-  <score MISSING_DATE                      5.0> +  score PDS_FROM_2_EMAILS                 3.0 
-  <score MISSING_HEADERS                   3.0> +  score FREEMAIL_FORGED_REPLYTO           3.5 
-  <score PDS_FROM_2_EMAILS                 3.0> +  score DKIM_ADSP_NXDOMAIN                5.0 
-  <score FREEMAIL_FORGED_REPLYTO           3.5> +  score FORGED_GMAIL_RCVD                 2.5 
-  <score DKIM_ADSP_NXDOMAIN                5.0> +  score FREEMAIL_FORGED_FROMDOMAIN        3.0 
-  <score FORGED_GMAIL_RCVD                 2.5> +  score HEADER_FROM_DIFFERENT_DOMAINS     3.0 
-  <score FREEMAIL_FORGED_FROMDOMAIN        3.0> +  score FREEMAIL_FROM                     3.0 
-  <score HEADER_FROM_DIFFERENT_DOMAINS     3.0> +  score ACCT_PHISHING                     3.0 
-  <score FREEMAIL_FROM                     3.0> +  score AD_PREFS                          3.0 
-  <score ACCT_PHISHING                     3.0> +  score ADMAIL                            3.0 
-  <score AD_PREFS                          3.0> +  score ADMITS_SPAM                       3.0 
-  <score ADMAIL                            3.0> +  score CONFIRMED_FORGED                  3.0 
-  <score ADMITS_SPAM                       3.0> +  score FROM_PAYPAL_SPOOF                 3.0 
-  <score CONFIRMED_FORGED                  3.0> +  score SPF_SOFTFAIL                      2.0 
-  <score FROM_PAYPAL_SPOOF                 3.0> +  score SPF_FAIL                          5.0 
-  <score SPF_SOFTFAIL                      2.0> +  whitelist_from *@statefarm.com 
-  <score SPF_FAIL                          5.0> +  blacklist_from *@email.freethinkerdaily.com
-  <whitelist_from *@statefarm.com> +
-  <blacklist_from *@email.freethinkerdaily.com>+
  
-Additionally, if you check the full headers, you will see that the RBLs can now be queried without issue. Note that whitelisting adds a -100 score and that blacklisting adds a +100 score. To understand how to tweak the symbolic headers better, one should review their spam and headers periodically and update rules. It is also possible to manage behaviors for whitelist, blacklist, and spam scores after dovecot receives them and from Roundcube. This would be instead of managing them with spam assassin at the CLI before dovecot receives themTo do thatcomment out white and black list rulesand remove the ''sieve_before'' rule we created above. Navigate to roundcube > settings > filters > edit filter set. To replicate the same functionality as above, I created the following:+Additionally, if you check the full headers, you will see that the RBLs can now be queried without issue. Note that whitelisting adds a -100 score and that blacklisting adds a +100 score. To understand how to tweak the symbolic headers better, one should review their spam and headers periodically and update rules based on the headers you see in the full message sourceMake sure to compile the sieve file with ''sievec'' each time you adjust the config, and restart postfix and dovecot. This approach above is good to do for egregiously bad emailbut individual users will likely need their own controls. Sofor larger servers, you can alternately use Roundcube instead. Remember, you must pick one or the other because the ''sieve_before'' rules above will bypass Roundcube's sieve logicBearing this in mind, if you want to use Roundcube for sieve rules, let's navigate to roundcube > settings > filters > edit filter set. To replicate similar functionality as above, I created the following:
  
-  #open roundcube, click the Edit filter set 
-  #copy paste this into the block, replace everything 
   require ["fileinto"];   require ["fileinto"];
   # rule:[whitelist]   # rule:[whitelist]
Line 432: Line 446:
   }   }
  
- Additionally, the best way to monitor your server is with pflogsum. +These rules are processed sequentially. Monitor the Junk folder periodically and refine whitelists as needed. If something escapes, like a full health dirty marketing scam, adjust your blacklist. That's all there is to it. Now that spam controls are setup, we need to setup some auditing tools to monitor how well our server is doing these tasksFor postfix, that tool is pflogsumm. Let's install it with ''sudo apt install pflogsumm'' and let's use rsyslog and log rotate to manage the logs, requiring us to also install rsyslog with ''sudo apt install rsyslog''
- +
-  sudo apt install pflogsumm +
-  sudo apt install rsyslog+
      
-Disable the ''/var/log/mail.log'' entries that are in ''rsyslog'' and any others that are located in ''/etc/logrotate.d/''Once that's done, create a new rule as follows: +Disable the ''/var/log/mail.log'' entries that are in the ''rsyslog'' logrotate rule in ''/etc/logrotate.d/''This is because we are going to make our own logrotate rule that works nicely with pflogsumm. Create the file ''sudo nano postfix-log'' inside ''/etc/logrotate.d/'' and enter the following:
- +
-  sudo nano postfix-log +
-   +
-In that file, enter the following:+
  
   /var/log/mail.log {   /var/log/mail.log {
Line 452: Line 459:
   }   }
  
-Once that's done, let's create script and cronjob to send us daily reports+Once that's done, let's create script and cronjob to send us daily reports by creating a file ''sudo nano /usr/local/bin/pflog-run.sh'' and entering something like:
- +
-  sudo nano /usr/local/bin/pflog-run.sh +
-   +
-In that script, enter something like this:+
  
   #!/bin/sh   #!/bin/sh
-  #/usr/sbin/logrotate -f /etc/logrotate.d/postfix-log+  #/usr/sbin/logrotate -f /etc/logrotate.d/postfix-log [helpful for manual testing]
   gunzip /var/log/mail.log.0.gz   gunzip /var/log/mail.log.0.gz
   /usr/sbin/pflogsumm /var/log/mail.log.0 --problems-first --rej-add-from --verbose-msg-detail -q |  mail -s "[pflog-lastlog]-$(hostname -f)-$(date)" email@email.com   /usr/sbin/pflogsumm /var/log/mail.log.0 --problems-first --rej-add-from --verbose-msg-detail -q |  mail -s "[pflog-lastlog]-$(hostname -f)-$(date)" email@email.com
Line 473: Line 476:
   30 12 * * * /bin/bash /usr/local/bin/pflog-run.sh >> /home/logs/pflog-run.log   30 12 * * * /bin/bash /usr/local/bin/pflog-run.sh >> /home/logs/pflog-run.log
      
-In extreme casesdirectly block problem domains in postfix in ''/etc/postfix/main.cf'' by adding ''reject_sender example.com'' within the ''smtpd_sender_restrictions ='' blockMake sure to add all users to the mail group.+You can also use the ''-d yesterday'' flag in pflogsumm and wildcard your domainswhich I later found out. But, this works too and I retain its use in my production servers. This ends our primary configuration. If you don't have Roundcube setup, look here: [[https://wiki.haacksnetworking.org/doku.php?id=computing:roundcube|Roundcube Tutorial]]The rest of this tutorial is miscellaneous information that has come up along the way.
  
-  sudo adduser username mail+-------------------------------------------
      
 The SASL module packages should be brought in as dependencies of postfix and/or dovecot. However, on upgrades, etc., they might be removed during dependency resolution. If you get "no sasl" report on your logs suddenly, despite everything working prior, use: The SASL module packages should be brought in as dependencies of postfix and/or dovecot. However, on upgrades, etc., they might be removed during dependency resolution. If you get "no sasl" report on your logs suddenly, despite everything working prior, use:
Line 485: Line 488:
   nano /etc/dovecot/conf.d/10-logging.conf   nano /etc/dovecot/conf.d/10-logging.conf
   <mail_debug yes>   <mail_debug yes>
 +
 +To setup autodiscovery, setup a separate vhost in apache with autodiscover.domain.com, and then create your A, AAAA, and discovery records:
 +
 +  _imap._tcp          10    1                   143        mail.haacksnetworking.org
 +  _submission._tcp    10    1                   587        mail.haacksnetworking.org
 +  _imaps._tcp                               993        mail.haacksnetworking.org
 +  _submissions._tcp                         465        mail.haacksnetworking.org
 +  _autodiscover._tcp  10    1                   443        mail.haacksnetworking.org
 +  autodiscover        A     8.28.86.125         
 +  autodiscover        AAAA  2604:fa40:0:10::18  
 +
 +After that, setup your ''autodiscover.xml'' file:
 +
 +  sudo nano /var/www/autodiscover.haacksnetworking.org/public_html/autodiscover/autodiscover.xml
      
-To check record health after you set your DNS, you can do the following:+Inside that file, enter something similar to this entry below, obviously adjusting for your priority, weight, and desired client configuration behavior: 
 + 
 +  <?xml version="1.0" encoding="UTF-8"?> 
 +  <Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006"> 
 +    <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a"> 
 +      <Account> 
 +        <AccountType>email</AccountType> 
 +        <Action>settings</Action> 
 +        <Protocol> 
 +          <Type>IMAP</Type> 
 +          <Server>mail.haacksnetworking.org</Server> 
 +          <Port>993</Port> 
 +          <LoginName>%EMAILADDRESS%</LoginName> 
 +          <Domain>haacksnetworking.org</Domain> 
 +          <Encryption>SSL</Encryption> 
 +        </Protocol> 
 +        <Protocol> 
 +          <Type>IMAP</Type> 
 +          <Server>mail.haacksnetworking.org</Server> 
 +          <Port>143</Port> 
 +          <LoginName>%EMAILADDRESS%</LoginName> 
 +          <Domain>haacksnetworking.org</Domain> 
 +          <Encryption>STARTTLS</Encryption> 
 +        </Protocol> 
 +        <Protocol> 
 +          <Type>SMTP</Type> 
 +          <Server>mail.haacksnetworking.org</Server> 
 +          <Port>465</Port> 
 +          <LoginName>%EMAILADDRESS%</LoginName> 
 +          <Domain>haacksnetworking.org</Domain> 
 +          <Encryption>SSL</Encryption> 
 +        </Protocol> 
 +        <Protocol> 
 +          <Type>SMTP</Type> 
 +          <Server>mail.haacksnetworking.org</Server> 
 +          <Port>587</Port> 
 +          <LoginName>%EMAILADDRESS%</LoginName> 
 +          <Domain>haacksnetworking.org</Domain> 
 +          <Encryption>STARTTLS</Encryption> 
 +        </Protocol> 
 +      </Account> 
 +    </Response> 
 +  </Autodiscover> 
 + 
 +Pretty much everything one needs is now setup. To check record health after you set your DNS records, you can do the following:
      
   dig txt +short _dmarc.jonathanhaack.com   dig txt +short _dmarc.jonathanhaack.com
Line 499: Line 560:
   sudo opendkim-testkey -d haacksnetworking.org -s default -vvv   sudo opendkim-testkey -d haacksnetworking.org -s default -vvv
      
-You should test email health with the CLI and/or use a service like mail-tester.com. I recommend using both CLI to send email and a common client. Both domain.com and mail.domain.com should work if you set everything right. Here's how to send a simple email at the CLI:+You should test email health with the CLI and/or use a service like [[https://www.mail-tester.com/|Mail Tester]]. I recommend using both CLI to send email and a common client. Both domain.com and mail.domain.com should work if you set everything right. Here's how to send a simple email at the CLI:
  
   echo "Hi, I am testing the subdomain email health." | mail -s "CLI Email Test" oemb1905@jonathanhaack.com   echo "Hi, I am testing the subdomain email health." | mail -s "CLI Email Test" oemb1905@jonathanhaack.com
Line 509: Line 570:
   postsuper -d E900C4780073   postsuper -d E900C4780073
   postsuper -d ALL   postsuper -d ALL
 +  
 +These tools prove helpful if/when emails get stuck, etc.
  
- --- //[[alerts@haacksnetworking.org|oemb1905]] 2025/04/12 22:10//+ --- //[[alerts@haacksnetworking.org|oemb1905]] 2025/05/15 19:19//
computing/mailserver.1744498291.txt.gz · Last modified: 2025/04/12 22:51 by oemb1905