*`Updated: 2023/07/21`* ## Setup DNS Records ### MX Record The <domain_name> can be considered as a main domain (e.g. `example.com`) or a subdomain (e.g. `mail.example.com`). Using the subdomain and MX record is a batter way for web mail server management. ``` # DNS setting example # A record for subdomain mail.cocobird.net. 3600 IN A <IP> # MX record for domain (content format: "<priority> <mail_domain>") cocobird.net. 3600 IN MX 10 mail.cocobird.net. ``` ### SPF Record ``` # SPF record example mail.cocobird.net. 3600 IN TXT "v=spf1 include:_spf.google.com ip4:<IP> ~all" ``` ### DMARC Record ``` # DMARC record example _dmarc.mail.cocobird.net. 3600 IN TXT "v=DMARC1; p=none; sp=none; rua=mailto:dmarc-reports@mail.cocobird.net" ``` ## Install and Configure postfix ### postfix Setting 1. Install postfix ```bash sudo apt install postfix # --> Select Internet Site # --> Enter domain name # --> Default the following options # Enable postfix service while start-up sudo systemctl enable postfix ``` 2. Edit configure file `/etc/postfix/main.cf` ``` # In file '/etc/postfix/main.cf' myhostname = <domain_name> # Check mydestination includes $myhostname and <domain_name> ``` 3. Restart postfix service ``` sudo systemctl restart postfix ``` ### TLS Setting 1. Edit configure file `/etc/postfix/main.cf` ``` # In file '/etc/postfix/main.cf' myhostname = <domain_name> # Check mydestination includes $myhostname and <domain_name> smtpd_tls_cert_file=/etc/letsencrypt/live/<domain_name>/fullchain.pem smtpd_tls_key_file=/etc/letsencrypt/live/<domain_name>/privkey.pem smtpd_use_tls = yes smtpd_tls_auth_only = yes smtpd_tls_received_header = yes smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated reject_unauth_destination # TLS for external smtp_use_tls = yes smtp_tls_note_starttls_offer = yes ``` 2. Edit configure file `/etc/postfix/master.cf` ``` # In file '/etc/postfix/master.cf' # Find and uncomment to enable smtps service smtps inet n - y - - smtpd # -o syslog_name=postfix/smtps -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes ``` ### Use Virtual Mailbox 1. Remove domain setting in `mydestination`, e.g. (mail.cocobird.net) 2. Add virtual mailbox setting ``` # In file '/etc/postfix/main.cf' ... virtual_transport = lmtp:unix:private/dovecot-lmtp virtual_mailbox_domains = cocobird.net, mail.cocobird.net ``` ## Install and Configure DKIM Service ### Install opendkim 1. Install opendkim ```bash sudo apt install opendkim opendkim-tools ``` 2. Add postfix to opendkim group ```bash # Add postfix user to opendkim group sudo gpasswd -a postfix opendkim ``` ### Configure opendkim #### a. Config `/etc/opendkim.conf` Method 1. Edit configure file `/etc/opendkim.conf` ``` # In file '/etc/opendkim.conf' Syslog yes SyslogSuccess yes LogWhy yes Canonicalization relaxed/simple Mode sv #SubDomains no OversignHeaders From Domain <domain_name> Selector <selector> KeyFile /etc/dkimkeys/<key_name>.private #Socket local:/run/opendkim/opendkim.sock Socket inet:8891@localhost #Socket inet:8891 #Socket local:/var/spool/postfix/opendkim/opendkim.sock ``` 2. Edit default configure file `/etc/default/opendkim` ``` # In file '/etc/default/opendkim' # Uncomment to specify an alternate socket # Note that setting this will override any Socket value in opendkim.conf # default: # SOCKET=local:$RUNDIR/opendkim.sock SOCKET="inet:8891@localhost" ``` 3. Edit postfix configure file `/etc/postfix/main.cf` ``` # In file '/etc/postfix/main.cf' . . . # Add following lines at the end # DKIM milter_default_action = accept milter_protocol = 2 smtpd_milters = inet:localhost:8891 non_smtpd_milters = inet:localhost:8891 ``` 4. Generate DKIM key ```bash opendkim-genkey --selector=<selector> --domain=<domain_name> # The keys <selector>.txt and <selector>.private will be generated under current directory. ``` Once generated the DKIM key, move the key to default DKIM key path, the path must match the `KeyFile` setting under `/etc/opendkim.conf` ```bash sudo mv <selector>.txt <selector>.private /etc/dkimkeys/ # Modify the directory owner to opendkim sudo chown -R opendkim:opendkim /etc/dkimkeys/ ``` :::warning Changing owner is an important step for opendkim.service to find the private key location. ::: #### b. Using KeyTable and SigningTable Method 1. Comment Domain, Selector and KeyFile, then and add table paths. ``` # --- /etc/opendkim.conf --- # Domain ... (註解掉) # Selector ... (註解掉) # KeyFile ... (註解掉) # 啟用對應表 KeyTable refile:/etc/opendkim/KeyTable SigningTable refile:/etc/opendkim/SigningTable InternalHosts refile:/etc/opendkim/InternalHosts ``` 2. Generate keys. ``` # 為主網域 example.com 產生金鑰,Selector 設為 default sudo mkdir -p /etc/opendkim/keys/example.com sudo opendkim-genkey -b 2048 -d example.com -s default -D /etc/opendkim/keys/example.com sudo chown -R opendkim:opendkim /etc/opendkim/keys/example.com # 為子網域 sub.example.com 產生金鑰,Selector 設為 mail sudo mkdir -p /etc/opendkim/keys/sub.example.com sudo opendkim-genkey -b 2048 -d sub.example.com -s mail -D /etc/opendkim/keys/sub.example.com sudo chown -R opendkim:opendkim /etc/opendkim/keys/sub.example.com ``` 3. Config KeyTable ``` # --- /etc/opendkim/KeyTable --- # 金鑰名稱 Domain Selector KeyFile (私鑰) key_main example.com:default:/etc/opendkim/keys/example.com/default.private key_sub sub.example.com:mail:/etc/opendkim/keys/sub.example.com/mail.private ``` 4. Config SigningTable ``` # --- /etc/opendkim/SigningTable --- # 寄件者 (From 標頭) 使用的金鑰名稱 (來自 KeyTable) *@example.com key_main *@sub.example.com key_sub ``` 5. Config InternalHosts ``` # --- /etc/opendkim/InternalHosts --- # 1. 絕對必要的基本設定 (本機) 127.0.0.1 ::1 localhost # 2. 本機伺服器的 IP 位址 # 假設您的伺服器公用 IP 是 203.0.113.10 203.0.113.10 # 假設您的伺服器內部 IP 是 192.168.1.100 192.168.1.100 # 3. (選用) 其他可信任的內部主機 # 假設您有一台 Web 伺服器在 192.168.1.200 192.168.1.200 # 4. (選用) 信任整個內部子網路 # 如果您信任 192.168.1.x 網段的所有機器 # 192.168.1.0/24 ``` ### Setup DNS DKIM Record According to the former section, The file `<selector>.txt` describes the DNS record format, simply add the content into DNS record. ```! # In file '/etc/dkimkeys/<selector>.txt' <selector>._domainkey IN TXT ( "v=DKIM1; h=sha256; k=rsa; p=<rsa_hash_code>" ) ; ----- DKIM key <selector> for <domain_name> ``` ### SMTP Firewall Setting ```bash # 用於伺服器對伺服器 (Server-to-Server) 的郵件傳輸 sudo ufw allow 25/tcp # 用於客戶端寄信 (Submission, STARTTLS) sudo ufw allow 587/tcp # (如果您有設定 SMTPS) 用於客戶端寄信 (SSL/TLS) sudo ufw allow 465/tcp ``` ## Install IMAP and POP3 Service ### Install dovecot 1. Install dovecot and lmtp module ``` sudo apt install dovecot-imapd dovecot-pop3d sudo apt install dovecot-lmtpd ``` 2. Edit configure file `/etc/dovecot/dovecot.conf` ``` # In file '/etc/dovecot/dovecot.conf' . . . # Add following lines at the end protocols = imap pop3 lmtp mail_location = maildir:~/Maildir ``` ### Auth and SSL #### System User Method 3. Edit configure file `/etc/dovecot/conf.d/10-auth.conf` ``` # In file '/etc/dovecot/conf.d/10-auth.conf' disable_plaintext_auth = no auth_username_format = %n auth_mechanisms = plain login ``` 4. Edit configure file `/etc/dovecot/conf.d/10-ssl.conf` ``` # In file '/etc/dovecot/conf.d/10-ssl.conf' ssl = yes ssl_cert = </etc/letsencrypt/live/<domain_name>/fullchain.pem ssl_key = </etc/letsencrypt/live/<domain_name>/privkey.pem ``` 5. Edit configure file `/etc/dovecot/conf.d/10-mail.conf` ``` # In file '/etc/dovecot/conf.d/10-mail.conf' mail_privileged_group = mail ``` 6. Change postfix mail location ```bash # Location same as 'mail_location' under '/etc/dovecot/dovecot.conf' sudo postconf -e "home_mailbox = Maildir/" ``` #### Virtual User Method 1. Edit `10-auth.conf` ``` # --- /etc/dovecot/conf.d/10-auth.conf --- # 關閉明文認證,除非在 SSL/TLS 加密連線中 disable_plaintext_auth = no auth_username_format = %n # 認證機制 auth_mechanisms = plain login # 註解掉 (或刪除) 系統使用者認證 #!include auth-system.conf.ext # 啟用 (取消註解) passwd-file 認證 !include auth-passwdfile.conf.ext ``` 2. Edit `auth-passwdfile.conf.ext` ``` # --- /etc/dovecot/conf.d/auth-passwdfile.conf.ext --- passdb { driver = passwd-file # 指向您的密碼檔案 # scheme=SHA512-CRYPT 指示 Dovecot 檔案中的密碼是使用此演算法加密的 # username_format=%n 捨去@domain的資訊 args = scheme=SHA512-CRYPT username_format=%n /etc/dovecot/users } userdb { # 我們使用 'static' (靜態) driver, # 這表示所有虛擬使用者的 UID/GID 和 home 目錄都使用相同規則。 driver = static # 這必須與您在 Postfix (或其他 MTA) 中設定的 vmail 使用者/目錄相符 args = uid=vmail gid=vmail home=/var/vmail/%n } ``` 3. Create vmail group ```bash # -r 建立系統使用者 # -d 指定家目錄 (所有郵件的根目錄) # -s /sbin/nologin 禁止此使用者登入 # -g vmail (先建立群組) sudo groupadd -r vmail sudo useradd -r -g vmail -d /var/vmail -s /sbin/nologin -c "Virtual Mail User" vmail ``` 4. Generate user password hash using doveadm ```bash # -s 指定加密演算法 (必須與 'args' 中的 'scheme' 相符) sudo doveadm pw -s SHA512-CRYPT ``` 5. Create `sudo nano /etc/dovecot/users` ``` # --- /etc/dovecot/users --- # 格式: user:{scheme}hash user1:{SHA512-CRYPT}$6$....(user1 的雜湊值)... user2:{SHA512-CRYPT}$6$....(user2 的雜湊值)... ``` 6. Set file permission ``` # 將檔案擁有者設為 dovecot (或 root) sudo chown dovecot:dovecot /etc/dovecot/users # 設定權限為 600 (只有擁有者可讀寫) sudo chmod 600 /etc/dovecot/users ``` 7. Set LMTP (Local Mail Transfer Protocol) ``` # --- /etc/dovecot/conf.d/10-master.conf --- service lmtp { unix_listener /var/spool/postfix/private/dovecot-lmtp { mode = 0660 user = postfix group = postfix } } ``` ### IMAP/POP3 Firewall Settings ```bash # IMAP (STARTTLS) sudo ufw allow 143/tcp # IMAPS (SSL/TLS) sudo ufw allow 993/tcp # (如果您也啟用了 POP3) # POP3 (STARTTLS) sudo ufw allow 110/tcp # POP3S (SSL/TLS) sudo ufw allow 995/tcp ``` ## Relayhost Setting 1. Edit configure file `/etc/postfix/main.cf` ``` # In file '/etc/postfix/main.cf' # SASL (Dovecot Not Support Client) smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth smtpd_sasl_auth_enable = yes #relayhost = [mail.cocobird.net] smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd #smtp_sasl_auth_enable = yes #smtp_tls_security_level = encrypt #smtp_sasl_tls_security_options = noanonymous #smtp_sender_dependent_authentication = yes #smtp_sasl_security_options = noanonymous, noplaintext #smtp_sasl_tls_security_options = noanonymous #smtp_sasl_mechanism_filter = plain, login ``` 2. Edit configure file `/etc/postfix/sasl_passwd` ``` # In file '/etc/postfix/sasl_passwd' [<domain_name>] username:password # Alternative form: # [<domain_name>]:submission username:password ``` 3. Edit configure file `/etc/postfix/sasl_passwd` ``` # In file '/etc/postfix/sasl_passwd' # Find and uncomment service auth { . . . # Postfix smtp-auth unix_listener /var/spool/postfix/private/auth { mode = 0660 user = postfix group = postfix } } ``` ## Mail Server Testing - MXToolBox - https://mxtoolbox.com/ - MXToolBox Mail deliverability - https://mxtoolbox.com/deliverability - Google Admin Toolbox Check MX - https://toolbox.googleapps.com/apps/checkmx/ - mail-tester - https://www.mail-tester.com/ - CheckTLS - https://www.checktls.com/TestReceiver ## Reference - SASL - https://www.postfix.org/SASL_README.html#client_sasl